This page applied to GeDA v.2.1.1+, specifically module geda.spring-integration.

This is a basic tutorial which goes thought the example given in the integration test that can be found in the geda.spring-integration module.

Module overview

To make this absolutely clear - you DO NOT have to use geda.spring-integration. All it is - is a best practice approach to spring beans setup for GeDA. You are welcome to use just geda.core if you find spring-integration not suitable for you.

  You have the alternative to use annotation-driven Spring AOP approach which is less intrusive on your code but adds the overhead of the AOP framework.

So what does it actually do?

Spring integration module uses Spring IoC in order to enrich the functionality of your services. 

The way beans' methods are enriched by GeDA is through the <dtosupport> tag, placed on the xml declaration of the bean.

This injects DTOSupport instance singleton that will have more than enough to support your needs (see JavaDoc's for more details).

But it is always easier to see with an example...

Maven dependencies

To integrate GeDA with your Spring 3 project you will need the following two modules:

<!-- core module: use can you it on its own if you are not using Spring 3 -->
<dependency>
   <groupId>com.inspire-software.lib.dto.geda</groupId>
   <artifactId>geda.core</artifactId>
   <version>2.1.1</version>
</dependency>

<!-- spring integration: spring 3 AOP wrapper for core -->
<dependency>
   <groupId>com.inspire-software.lib.dto.geda</groupId>
   <artifactId>geda.spring-integration</artifactId>
   <version>2.1.1</version>
</dependency>

Spring 3 beans setup

  You will need to use http://geda-genericdto.svn.sourceforge.net/svnroot/geda-genericdto/schema/geda-spring-integration-xml-2.1.1.xsd schema.

I am going to describe the basic approach in this tutorial, so:

<!--
  ~ This code is distributed under The GNU Lesser General Public License (LGPLv3)
  ~ Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html
  ~
  ~ Copyright Denis Pavlov 2009
  ~ Web: http://www.inspire-software.com
  ~ SVN: https://geda-genericdto.svn.sourceforge.net/svnroot/geda-genericdto
  -->


<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:geda="http://geda-genericdto.svn.sourceforge.net/svnroot/geda-genericdto/schema"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://geda-genericdto.svn.sourceforge.net/svnroot/geda-genericdto/schema
                           http://geda-genericdto.svn.sourceforge.net/svnroot/geda-genericdto/schema/geda-spring-integration-xml-2.1.1.xsd"
>

   <geda:xml-driven dto-factory="dtoFactory"
                    dto-adapters-registrar="adapterRegistrar"
                    on-dto-assembly="onDto"
                    on-dto-assembled="onDtoSuccess"
                    on-dto-failed="onDtoFailure"
                    on-entity-assembly="onEntity"
                    on-entity-assembled="onEntitySuccess"
                    on-entity-failed="onEntityFailure"/>

   <bean id="dtoFactory" class="com.inspiresoftware.lib.dto.geda.impl.DTOFactoryImpl">
       <constructor-arg>
           <map>
               <entry key="entityKey" value="com.inspiresoftware.lib.dto.geda.test.impl.DomainObjectImpl"/>
               <entry key="annDtoKey"    value="com.inspiresoftware.lib.dto.geda.test.impl.AnnotatedExtendedDataTransferObjectImpl"/>
               <entry key="annFilterKey" value="com.inspiresoftware.lib.dto.geda.test.impl.AnnotatedDataTransferObjectImpl"/>
           </map>
       </constructor-arg>
   </bean>

   <bean id="onDto" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>
   <bean id="onDtoSuccess" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>
   <bean id="onDtoFailure" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>
   <bean id="onEntity" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>
   <bean id="onEntitySuccess" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>
   <bean id="onEntityFailure" class="com.inspiresoftware.lib.dto.geda.test.impl.CountingEventListener"/>

   <!-- Test custom property -->
   <bean id="xmlTestServiceCustomProperty"
         class="com.inspiresoftware.lib.dto.geda.test.impl.TestXmlServiceImpl">
       <geda:dtosupport property="dtoSupportBean"/>
   </bean>

   <!-- Test default property -->
   <bean id="xmlTestServiceDefaultProperty"
         class="com.inspiresoftware.lib.dto.geda.test.impl.TestXmlServiceImpl">
       <geda:dtosupport/>
   </bean>

   <bean id="adapterRegistrar" class="com.inspiresoftware.lib.dto.geda.test.impl.ExposedDTOAdaptersRegistrarImpl">
       <constructor-arg>
           <map>
               <entry key="vc" value-ref="adapterValueConverter"/>
               <entry key="er" value-ref="adapterEntityRetriever"/>
               <entry key="ma" value-ref="adapterMatcher"/>
           </map>
       </constructor-arg>
   </bean>

   <bean id="adapterValueConverter" class="com.inspiresoftware.lib.dto.geda.test.impl.ValueConverterImpl"/>
   <bean id="adapterEntityRetriever" class="com.inspiresoftware.lib.dto.geda.test.impl.EntityRetrieverImpl"/>
   <bean id="adapterMatcher" class="com.inspiresoftware.lib.dto.geda.test.impl.DtoToEntityMatcherImpl"/>

</beans>

Spring bean service and DTOSupport

  Interested reader is highly advised to look at the source code of module test classes.

So, now how do you define and implement the service?

Start with interface:

package com.inspiresoftware.lib.dto.geda.test;

public interface TestXmlService {

   <T> T transfer(Object from);

}

Well, that was easy, now the implementation:

package com.inspiresoftware.lib.dto.geda.test.impl;

import com.inspiresoftware.lib.dto.geda.DTOSupport;
import com.inspiresoftware.lib.dto.geda.test.TestXmlService;

public class TestXmlServiceImpl implements TestXmlService {

   private DTOSupport dtoSupport;

   public <T> T transfer(final Object from) {
       return dtoSupport.assembleDtoByKey("annDtoKey", from, "manual");
   }

   public void setDtoSupportBean(final DTOSupport dtoSupport) {
       this.dtoSupport = dtoSupport;
   }

   public void setDtoSupport(final DTOSupport dtoSupport) {
       this.dtoSupport = dtoSupport;
   }

}
  Please do not be confused with two IoC methods: setDtoSupportBean, setDtoSupport. This is just for demonstration purposes that the name of the method can be different. You will only need one such method. setDtoSupport is the default if you do not specify any "property" on the <dtosupport> tag.
  This example assumes that objects passed as dto's are valid instances of @Dto annotated or DSL classes.

Event listeners

So for each of the above examples (given the above spring config) event listeners will fire before and after each transfer from/to dto object and entity object.

public class CountingEventListener implements DTOCountingEventListener, BeanNameAware {

   private static final Logger LOG = LoggerFactory.getLogger(CountingEventListener.class);

   private int count = 0;
   private String name;

   public void onEvent(final Object... context) {
       // Current implementation of DTOSupport provides the following context array:
       // context[0] = context string identifier (i.e. in this example "manual")
       // context[1] = DTO object (i.e. instance of DTO named by "annDtoKey" in DTOFactory)
       // context[2] = Entity object (i.e. from object)
       // context[3] = Exception value if an exception occurs during transfer (it is up to the event handler to re-throw it!!!)
       count++;
        LOG.debug(name + " is called " + count + " times");
   }

   public int getCount() {
       return count;
   }

   public void setBeanName(final String name) {
       this.name = name;
   }
}

So this pretty much sums it up. And as mentioned above this does couple your code a bit more with GeDA - however you do get the benefit of by passing AOP (hence better performance)

Proxy template

  Be careful when putting this tag in a bean with proxy template
dtosupport tag should be placed inside the actual bean - NOT bean proxy template.

Here is an example of correct tag placement (inside the inner bean):

txProxyTemplate

      <bean id="authUserRepository"  parent="txProxyTemplate">
       <property name="target">
           <bean class="com.inspiresoftware.erp.security.locator.impl.LoggedInUserRepositoryImpl">
               <constructor-arg index="0" ref="userDAO"/>
               <geda:dtosupport/>
           </bean>
       </property>
       <property name="transactionAttributes">
           <props>
               <prop key="login">PROPAGATION_REQUIRED,readOnly,-Throwable</prop>
               <prop key="logout">PROPAGATION_REQUIRED,readOnly,-Throwable</prop>
               <prop key="transfer*">PROPAGATION_REQUIRED,readOnly,-Throwable</prop>
               <prop key="*">PROPAGATION_NOT_SUPPORTED</prop>
           </props>
       </property>
   </bean>
Tags:
Created by Vladyslav Pavlov on 2018/03/20 09:04
    
GeDA - Generic DTO Assembler © Denys Pavlov 2009 - 2019
v.1.0.0