Migrating to Spring Framework 3.0

While looking for a better programming model to implement much of the integration grunt work I’ve been doing lately, I wanted to assess Spring Integration as an alternative to Apache Camel as a EIP library. Spring Integration has definitely matured and with 2.0, it has definitely become a viable if not slightly more attractive alternative to Camel since it’s built on top of Spring Framework features, a framework we use extensively in all our projects.

However, version 2.0 of Spring Integration has a dependency on Spring Framework 3.0 and since many of our current projects are still built with Spring Framework 2.5.6, I wanted to assess how much effort is required to migrate to 3.0. Here’s my report on migrating from Spring 2.5.6 to 3.0.

The aim of this exercise is to migrate the application and tests to use the new library without tackling the larger task of migrating to use the new features and changing the configurations to use the new XML schemas and annotations.

Spring Framework

In version 3, the framework is no longer provided in a single monolithic jar but is split into a number of jars based on features. For example, there’s a separate spring-tx jar for the transactions if you choose to use it.

There were a couple of things of note here. Surprisingly, this did not require much effort other than figuring out which of the new jars to include. Helpfully, this is well documented and the naming is intuitive. One exception was remote invocation which required spring-webmvc.jar, I was hoping this would be moved to more neutral place so we don’t have to bring in the entire MVC part of the framework which we don’t use. There were only a few dependencies within our projects to Spring classes or interfaces – a clear indication that the framework is well abstracted and we’ve been careful about the dependencies.

In the end, much of the new jars are included and this gives a very high level view of how much of Spring we use – it’s not just a IOC container. It did take a little searching to figure out the names of the ivy/maven dependencies and as a convenience I’ve included the list of ivy dependencies used. Note that if you bring in spring-aop, you have to include aopalliance.jar.

As you see, we always set transitive dependencies to false, so that we can carefully hand pick which jar/classes to bring in. Others may disagree with this approach but that’s for another blog.
I was also impressed that the migration did not affect much else, especially Hibernate which is still at a much older version 3.2.0ga.

<dependency org="org.springframework" name="spring-core" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-web" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-webmvc" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-asm" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-beans" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-context" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-context-support" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-expression" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-test" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-oxm" rev="3.0.5.RELEASE" transitive="false"/>

<dependency org="org.springframework" name="spring-orm" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-jdbc" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-tx" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="org.springframework" name="spring-aop" rev="3.0.5.RELEASE" transitive="false"/>
<dependency org="aopalliance" name="aopalliance" rev="1.0" transitive="false"/>

Spring Security

Much of the rest of the effort related to Spring was spent migrating from Acegi to Spring Security because Acegi is not compatible with the new version. The configuration is now a lot more simpler and securing method invocation is now straight forward and fairly intuitive. In any case, our current application model really only make use of the security context and web session integration part of Acegi, so there was very little to do except to migrate to the new XML schema and fixed a bunch of class renaming issues. For example, HttpSessionContextIntegrationFilter is now deprecated and we now use the more apt SecurityContextPersistenceFilter.

Here’s the ivy dependencies required for Spring Security:

<dependency org="org.springframework.security" name="spring-security-core" rev="3.0.5.RELEASE" transitive="false" />
<dependency org="org.springframework.security" name="spring-security-config" rev="3.0.5.RELEASE" transitive="false" />
<dependency org="org.springframework.security" name="spring-security-web" rev="3.0.5.RELEASE" transitive="false" />

Here’s the heavily snipped (to save space) configuration XML:

<global-method-security pre-post-annotations="enabled">
</global-method-security>

<beans:bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**"
			filters="
SecurityContextPersistenceFilter
"
/>
</sec:filter-chain-map>
</beans:bean>

Apache CXF

Migrating Apache CXF was slightly more involved. CXF uses Spring under the covers and not surprisingly, the significant repackaging and renaming, caused our version (2.2.3) of CXF to fail at startup and caused a number of runtime exceptions. It required an upgrade to a more recent release of CXF but I chose the latest 2.3.2.

Unlike Spring, there is very little information I could find on how to integrate CXF and it proved to be a very long exercise to hand pick the jars based on our usage:

<dependency org="org.apache.cxf" name="cxf-rt-frontend-jaxws" rev="2.3.2" transitive="false" />
<dependency org="org.apache.cxf" name="cxf-rt-transports-http" rev="2.3.2" transitive="false" />

<dependency org="org.apache.cxf" name="cxf-api" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-core" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-bindings-soap" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-bindings-xml" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-frontend-simple" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-transports-local" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-ws-addr" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-ws-security" rev="2.3.2" transitive="false"/>
<dependency org="org.apache.cxf" name="cxf-rt-transports-common" rev="2.3.2" transitive="false" />
<dependency org="org.apache.cxf" name="cxf-common-utilities" rev="2.3.2" transitive="false" />
<dependency org="org.apache.cxf" name="cxf-rt-databinding-jaxb" rev="2.3.2" transitive="false" />
<dependency org="org.apache.cxf" name="cxf-tools-common" rev="2.3.2" transitive="false" />

So in the end, I used the bundle jar instead.

<dependency org="org.apache.cxf" name="cxf-bundle" rev="2.3.2" transitive="false" />

I have to mention that my experience with upgrade from XFire (former incarnation of CXF) to CXF and every upgrade since had not been good. You may sense slight negativity in this area.

Conclusion

All in all, the migration took a better part of a day to get the projects compiling, tests and application running again. Initially, I had expected a long painful exercise, just from reports of asm and antlr jar incompatibilities in milestone releases of version 3, but the current release has resolved these problems by repackaging these dependencies. As part of this whole exercise, I’ve noticed a number of jars which are probably left over from past integrations which we probably no longer use and should be cleaned up as a separate exercise.

On to Spring Integration next!

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply