RSS feed
All(28) Eclipse(4) Java(5) JDBC(5) JSP(3) Maven(7) Personal (1) Spring(3) Tomcat(5)
<< Running PHP Scripts inside of Tomcat and accessing Java Classes via Caucho Quercus | Home | Spring Aspect Oriented Programming - Adding a simple profiler to your services layer >>

Upgrading Spring from 1.2 to 2.5

Updating your Spring dependencies and XML Configuration

I recently upgraded our spring dependencies in our java projects to 2.5.1 from 1.2.8. The main reason was our that 1.2.8 came out in October of 2006 and its now February of 2008 and I was trying to ease the xml configuration and was seeing more and more documentation based on 2.X. 

Here are some other articles on what is new in Spring 2.X

Some articles on whats new

http://static.springframework.org/spring/docs/2.5.x/changelog.txt 

Whats New in Spring 2.0

http://www.infoq.com/articles/spring-2-intro

http://static.springframework.org/spring/docs/2.0.x/reference/new-in-2.html

Whats New in Spring 2.5

http://www.infoq.com/articles/spring-2.5-part-1

 

The nice thing about Spring is that it prety much is always backwards compatible so you can just replace the jars and still use the same code and xml configuration  files. So that was the first thing I did by updating the maven dependencies and reinstalling the maven based projects.

 

Spring Dependency Changes in the pom.xml

 

            <dependency>

                  <groupId>org.springframework</groupId>

                  <artifactId>spring</artifactId>

                  <version>1.2.8</version>

            </dependency>

To

            <dependency>     

                  <groupId>org.springframework</groupId>

                  <artifactId>spring</artifactId>

                  <version>2.5.1</version>

            </dependency>

 

One of the main advantages of Spring 2.5 is less verbose xml configuration.  The xml is based on a XSD supplied by spring as opposed to the Spring 1.X DTD. Again this isnt necessary right away but the next step to take advantages of Spring 2.5.X is to switch the DTD to XSD namespaces in your applicationContext.xml (beans.xml) files.

 

The beans.xml (applcationContext.xml) files gos from a dtd to an xsd.

 

1.2.8

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

 

 

2.5.1-the namespaces you use depends on whatyour projects use but this group of namespeaces covers most of the bases

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:p="http://www.springframework.org/schema/p"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="

       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

       ">

 

So at this point you still have pretty verbose xml and what changes next is that basically some code that looks like this

 
    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>
 
Becomes 
 
    <bean name="john-modern" 
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>
 

 

This may not seem like much difference but it makes a big difference in the readability and the length of these xml confgiruation files.

 

XML config shortcuts are detailed here:

http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#xml-config-shortcuts

 

 

The next is to actually change something that your using in your applicationContext.xml. One of the most common things is a datasource and transactionManager configuration.

 

In 1.2.8

<bean id="mainDataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close" >

  <property name="url" value="jdbc:mysql://yourbox:3306/yourdb?zeroDateTimeBehavior=convertToNull&amp;dumpMetaDataOnColumnNotFound=true&amp;dumpQueriesOnException=true" />

  <property name="driverClassName" value="com.mysql.jdbc.Driver" />

  <property name="username" value="youruser"/>

  <property name="password" value="yourpass"/>

  <property name="initialSize" value="0" />

  <property name="maxActive" value="100" />

  <property name="maxIdle" value="30" />

  <property name="maxWait" value="10000" />

  <property name="removeAbandoned" value="true" />

  <property name="removeAbandonedTimeout" value="200" />

  <property name="logAbandoned" value="true" />

  <property name="defaultAutoCommit" value="false" />

  <property name="defaultReadOnly" value="false" />

  <property name="validationQuery" value="select 1"/>

  <property name="testOnBorrow" value="true" />

  <property name="timeBetweenEvictionRunsMillis" value="300000" />

  <property name="minEvictableIdleTimeMillis" value="900000" />

  <property name="testWhileIdle" value="true" />

  <property name="testOnReturn" value="true" /> 

  <property name="defaultTransactionIsolation" value="2" /> 

</bean>

 

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    <property name="dataSource" ref="mainDataSource"/>

</bean>

 

In 2.5.1 this becomes:

 

       <bean id="mainDataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource"

p:url="jdbc:mysql://yourbox:3306/yourdb?zeroDateTimeBehavior=convertToNull&amp;dumpMetaDataOnColumnNotFound=true&amp;dumpQueriesOnException=true"

       p:driverClassName="com.mysql.jdbc.Driver"

       p:destroy-method="close"

       p:username="youruser"

       p:password="yourpass"

       p:initialSize="0"

       p:maxActive="100"

       p:maxIdle="30"

       p:maxWait="10000"

       p:removeAbandoned="true"

       p:removeAbandonedTimeout="200"

       p:logAbandoned="true"

       p:defaultAutoCommit="false"

       p:defaultReadOnly="false"

       p:validationQuery="select 1"

       p:testOnBorrow="true"

       p:timeBetweenEvictionRunsMillis="300000"

       p:minEvictableIdleTimeMillis="900000"

       p:testWhileIdle="true"

       p:testOnReturn="true"

       p:defaultTransactionIsolation="2" /> 

 

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="mainDataSource"/>

 

The next thing I changed was daos (based on Firestorm DAO) which we only have to inject with an interceptor

1.2.8

<bean id="fuelTxnDao" class="com.cms.shared.gen.firestorm.cmssql.jdbc.FuelTxnDaoImpl">

  <property name=”interceptor” ref="simplestChgColumnsInterceptor">    

</bean>

 

to

2.5.1

<bean id="fuelTxnDao" class="com.cms.shared.gen.firestorm.cmssql.jdbc.FuelTxnDaoImpl"

  p:interceptor-ref="simplestChgColumnsInterceptor"/>

 

 

One of the main reasons we use Spring is for Declarative Transactions. This means that we have managers or service which serve as transactional boundaries and essentially use Springs Transaction Manager to have transactional semantics defined by Spring Configuration.

 

In 1.2.8 this looks like:

--Daos omitted for brevity

 

<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

  <property name="transactionManager" ref="transactionManager"/>

  <property name="transactionAttributes">

    <props>

      <prop key="*">PROPAGATION_REQUIRED</prop>

    </props>

  </property>

</bean>

 

<!—example of one of our managers, this manager concept is taken from the book Pro Spring -->

 

<bean id="generalLedgerManager" parent="txProxyTemplate" >

 

  <property name="transactionManager" ref="transactionManager"/>

  <property name="transactionAttributes">

    <props>

      <prop key="*">PROPAGATION_REQUIRED,-com.cms.gl.exceptions.GeneralLedgerException</prop>

    </props>

  </property>

 

  <property name="proxyInterfaces" value="com.cms.gl.GeneralLedgerManager" />

  <property name="optimize" value="true" />

 

  <property name="target">

    <bean class="com.cms.gl.GeneralLedgerManagerImpl">

      <property name="lockService" ref="lockService"/>

      <property name="glmasterDao" ref="glmasterDao"/>

      <property name="glopenDao" ref="glopenDao"/>

            <property name="gltransaDao" ref="gltransaDao"/>

            <property name="jnlcdeDao" ref="jnlcdeDao"/>

            <property name="ctldescDao" ref="ctldescDao"/>

            <property name="subtotcdsDao" ref="subtotcdsDao"/>

            <property name="accttypeDao" ref="accttypeDao"/>

            <property name="counterManager" ref="counterManager"/>

            <property name="fiscalYearManager" ref="fiscalYearManager"/>

      <property name="locnDao" ref="locnDao"/>

      <property name="glbudgetDao" ref="glbudgetDao"/>

    </bean>

  </property>

</bean>

 

In 2.5.1 this becomes:

 

<!-- this is what turns on the annotation processing in spring for all @Transactional Managers  -->

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

 

<bean id="generalLedgerManager" class="com.cms.gl.GeneralLedgerManagerImpl"

      p:lockService-ref="lockService"

      p:glmasterDao-ref="glmasterDao"

      p:glopenDao-ref="glopenDao"

      p:gltransaDao-ref="gltransaDao"

      p:jnlcdeDao-ref="jnlcdeDao"

      p:ctldescDao-ref="ctldescDao"

      p:subtotcdsDao-ref="subtotcdsDao"

      p:accttypeDao-ref="accttypeDao"

      p:counterManager-ref="counterManager"

      p:fiscalYearManager-ref="fiscalYearManager"

      p:locnDao-ref="locnDao"

      p:glbudgetDao-ref="glbudgetDao"

/>

 

With the addition that in your java class you add the Java 5 Annotation like this.

Here is the annotation in com.cms.gl.GeneralLedgerManagerImpl.java

 

@Transactional(propagation=Propagation.REQUIRED,

            isolation=Isolation.DEFAULT,

            rollbackFor={GeneralLedgerException.class, ValidatorException.class } //array exceptions to rollbackfor

)

public class GeneralLedgerManagerImpl extends BaseGeneralLedgerManager {

}

So what happened to TransactionProxyFactoryBean named above as txProxyTemplate.

 

Well basically the same thing is still going on under the covers with spring its just that now instead of the verbose xml they have abstracted it up and the configuration is based on the annotation. The annotation basically tells Spring to treat this bean as a TransactionProxyFactoryBean.

 

Again you don’t have to modify any of the existing configuration, however I went through the exercise so I could see what the differeneces really were and so I could begin using annotations in Spring along with less verbose .xml. This whole process took me about half a day if you don’t include the readin I was doing on Spring 2.5 as well, although that was directly proportional to the number of projects I have, in any case as usual with the upgrade to Spring it was very noninvasive and easy.

You can go further and completely remove the xml configuration for a manager bean with annotations by using @AutoWired to inject dependencies in the following manner. However I’m not too hot on completely removing all information from the  applicationContext.xml.

 

/**

 * @author Robert Sinner CMSSolutions, Feb 4, 2008

 *

 */

@Transactional(propagation=Propagation.REQUIRED,

            isolation=Isolation.DEFAULT,

            rollbackFor={GeneralLedgerException.class, ValidatorException.class}//array exceptions to cause rollback

)

@Service("generalLedgerManager")

public class GeneralLedgerManagerImpl extends BaseGeneralLedgerManager {

 

@Autowired //actually in BaseGeneralLedgerManager here4 brevity    protected FiscalYearManager fiscalYearManager;

 

Having already discussed the use of the @Transactional annotation above for Spring Managers

 

Another Annotation for use in Spring Managers in 2.5.1 is

 

//import org.springframework.beans.factory.InitializingBean; //replaced by @Required annotation

import org.springframework.beans.factory.annotation.Required;

 

@Required

 

What this does is you put this on the setter of your BaseAbstractManager so that if its not called during startup an error is thrown, what this does is basically tell the Spring Container that this setter must be called because the dependency is expected to be injected.

 

This can replace in your BaseAbstractManager the use of

implements InitializingBean

with

 

An example of this is in BaseGeneralLedegerManager

public abstract class BaseGeneralLedgerManager implements GeneralLedgerManager

//, InitializingBean

//replaced with @Required annotation below on each of the setters that are expected to be called

{

 

 

    protected FiscalYearManager fiscalYearManager;

           

 

    public FiscalYearManager getFiscalYearManager() {

        return fiscalYearManager;

    }

    @Required

    public void setFiscalYearManager(FiscalYearManager fiscalYearManager) {

        this.fiscalYearManager = fiscalYearManager;

    }

 

     /*  

      * no longer required with @Required being used properly

          public void afterPropertiesSet() throws Exception { //used in conjunction with implements IntializingBean

                    

          }

     */

See the full spring documentation here:

http://static.springframework.org/spring/docs/2.5.x/reference/metadata.html#metadata-annotations

Which you use is a matter of preference however you should agree with the rest of your team so you know what to expect.

Tags :


Re: Upgrading Spring from 1.2 to 2.5

Interesting post: too bad your CSS settings make it less readable than it could if the content column was wider.

Add a comment Send a TrackBack