Speedo user manual: Integration with Spring

 FinalLogo.jpg
 FinalLogo.jpg
  1. What is Spring ?
  2. Integrating Speedo with Spring

Back to the Speedo documentation



  1. What is Spring ?
  2. Description

    Spring is a framework that aims at making J2EE easier to use in your developments. It comes with several features that help you put existing frameworks together, and that help managing your application's objects. The core of Spring is it's ligthweight bean container. This container is called "lightweight" because it manages Plain Old Java Objects, as opposed to EJB containers which are "heavier".
    Spring's container offers a way to plug your objects together using the Inversion of Control pattern. This pattern says that if an object A needs an object B to work, an instance of B will be given to A when needed. Object A never instanciates B itself.
    This way, A stay independant from B's implementation. A only knows B's business interface. For example, this is very useful to set up unit testing of your application's objects. You can easily change the implementation your objects will use, passing mock objects during tests.
    Another great possibility provided by Spring is Aspect Oriented Programming.

    Spring provides other useful services, especially for persistence management purposes, like transaction management and DAO pattern implementation. It then makes perfect sense to integrate Speedo with Spring (you can find more information on Spring here).


    Installation and configuration

    Dependency injection is the key feature of Spring's lightweight container. This functionnality is implemented in Spring through the BeanFactory, which actually is the container that instanciates, configures and manages your application's beans.
    A BeanFactory is represented by the org.springframework.beans.factory.BeanFactory. There are several implementations for this interface, like the org.springframework.beans.factory.xml.XmlBeanFactory or org.springframework.context.ApplicationContext, the latter subclassing the BeanFactory interface. This ApplicationContext interface provides more application services like internationalized messages, properties files to externalize configuration, AOP, ...
    To work, the container needs to know how beans can be created, and most of all, what dependencies are existing between these beans. This has to be done with an XML configuration file, which contains beans declarations. The following example shows a basic configuration file :

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    
    <beans>
      
    	<bean id="bean1" class="org.objectweb.speedo.spring.Bean1">
    		...
    	</bean>
    	
    	<bean id="bean2" class="org.objectweb.speedo.spring.Bean2">
    		...
    	</bean>
    	
    	...
    	
    </beans>
    			



  3. Integrating Speedo with Spring
  4. In this example of integrating Speedo with Spring, we will write the data access layer of a small application, which deals with Employees. We will first talk about the DAO implementation provided by Spring. Then we will see how to write our application's configuration file so our DAOs can be managed by the container.


    DAO pattern

    Spring makes it easier to write your data access objects by providing abstract classes and templates of DAO implementation. Spring's JDO support is based on two packages : org.springframework.orm.jdo and org.springframework.orm.jdo.support.
    To write our data acess objects, we are going to extend the JdoDaoSupport abstract class, which is the DAO template for JDO. This class needs a PersistenceManagerFactory to be set in Spring's configuration.

    In the following example, we define our DAO interface. Typically we only need CRUD (Create, Retrieve, Update and Delete) operations :

    public interface EmployeeDAO {
    	public Employee getEmployeeById(long id);
    	public void createEmployee(Employee emp);
    	...
    }
    			

    Then we define the implementation class using the appropriate Spring DAO template :

    import org.springframework.orm.jdo.support.JdoDaoSupport;
    
    public class EmployeeDAOImpl extends JdoDaoSupport implements EmployeeDAO {
    	
    	public Employee getEmployeeById(long id) {
    		Employee emp = null;
    		PersistentManager pm = getPersistentManager();
    		emp = getPersistenceManager().getObjectById(id);
    		pm.close();
    		return emp;
    	}
    	
    	public void createEmployee(Employee emp) {
    		PersistentManager pm = getPersistentManager();
    		
    		pm.currentTransaction().begin();
    		pm.makePersistent(emp);
    		pm.currentTransaction().commit();
    		pm.close();
    	}
    	...
    }
    			

    By extending the JdoDaoSupport abstract class, our EmployeeDAOImpl becomes "Spring aware".
    It still needs a PersistenceManagerFactory to work. In the configuration file, we'll have to declare a bean that is the PersistenceManagerFactory we want to be passed to our DAO :

    <bean id="pmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
    	<property name="jdoProperties">
    		<props>
    			<prop key="javax.jdo.PersistenceManagerFactoryClass">org.objectweb.speedo.Speedo</prop>
    			<prop key="javax.jdo.option.ConnectionURL">jdbc:hsqldb:hsql://localhost/myDB</prop>
    			<prop key="javax.jdo.option.ConnectionUserName">myUsername</prop>
    			<prop key="javax.jdo.option.ConnectionPassword">myPassword</prop>
    			<prop key="javax.jdo.option.ConnectionDriverName">org.hsqldb.jdbcDriver</prop>
    			<prop key="org.objectweb.speedo.mapperName">rdb.hsql</prop>
    		</props>
    	</property>
    </bean>
    			

    Now we can declare our DAO bean, providing its persistenceManagerFactory property with a reference to the pmf bean we declared :

    <bean id="employeeDAO" class="org.objectweb.speedo.spring.EmployeeDAO">
    	<property name="persistenceManagerFactory">
    		<ref bean="pmf"/>
    	</property>
    </bean>
    			


    Transaction management

    Spring provides powerful transaction management, either programmatically or declaratively. This latter feature allows you to externalize transaction demarcation from the code, making your application easier to maintain. The following is an example of declarative transaction management, provided by Spring's AOP feature.
    We have a first bean, EmployeeService, which contains all the business logic for employee management. This bean uses the employeeDAO bean we defined earlier to access data. The DAO is provided by its "dao" property in the Spring definition.
    The service bean needs transaction management so we first define a transactionManager bean. This transaction behaviour is then added onto the service bean. One way to do that is to use the org.springframework.transaction.interceptor.TransactionProxyFactoryBean class. This class has several attributes :

    Here is the result of this example :

    <bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    	<property name="persistenceManagerFactory">
    		<ref bean="pmf"/>
    	</property>
    </bean>
    
    <bean id="employeeServiceTarget" class="org.objectweb.speedo.spring.EmployeeService">
    	<property name="dao">
    		<ref bean="employeeDAO"/>
    	</property>
    </bean>
    
    <bean id="employeeService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="target"><ref bean="employeeServiceTarget"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="create*">PROPAGATION_REQUIRED,-MyCheckedException</prop>
                <prop key="modify*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
    			

    The result of this example is that the "employeeService" bean is kind of "enhanced" with transaction behaviour. This behaviour is configured using values of the transactionAttributes property. Methods starting with "createXXX" need transaction, and they may throw a MyCheckedException.

    Using the TransactionProxyFactoryBean allows you to fully control the way you wrap a bean with a transactional proxy. But if you want wrap several beans an identical fashion, you can use the BeanNameAutoProxyCreator. The idea is to declare a transaction interceptor, which is configured with a transactionAttributes bean, and then to affect this interceptor to a list of beans in the BeanNameAutoProxyCreator.
    This is done in the following example :

    <bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    	<property name="persistenceManagerFactory">
    		<ref bean="pmf"/>
    	</property>
    </bean>
    
    <bean id="transactionAttributes" 
    	class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
        <property name="properties">
            <value>
                create*=PROPAGATION_REQUIRED,-MyCheckedException
                find*=PROPAGATION_REQUIRED, -MyNotFoundException, readOnly
            </value>
        </property>
    </bean>
    
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    	<property name="transactionManager">
    		<ref bean="transactionManager"/>
    	</property>
    	<property name="transactionAttributeSource">
    		<ref bean="transactionAttributes"/>
    	</property>
    </bean>
    
    <bean id="employeeService" class="org.objectweb.speedo.spring.EmployeeService">
    	<property name="dao">
    		<ref bean="employeeDAO"/>
    	</property>
    </bean>
    
    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    	<property name="interceptorNames">
            <value>transactionInterceptor</value>
    	</property>
    	<property name="beanNames">
            <value>*Service</value>
    	</property>
    </bean>