JBoss AS7 has been released today, and there are definitely more than 7 reasons to love it.  By now, you have probably learned about its new features and have viewed the webinars. If not, I strongly recommend you to do so.

 

I'd like to follow up with a few practical examples of running Spring applications in JBoss AS7. And if you are interested in a deeper dive into the topic, continue following my blog, as this is my first post in a series that will cover:

  • an in-depth overview of dependency management and classloading and its implications for Spring;
  • persistence configuration options;
  • migrating Spring applications from older versions of JBoss AS;
  • integrating with enterprise services such as messaging and caching (including distributed and replicated caches);
  • the upcoming Snowdrop 2.0 release

... and many more. All focused on Spring and JBoss AS7.

 

There's a "Hello World" for every new technology. For this blog, the "Hello World" is actually a group of Spring examples, from the official example repository:

  1. Spring MVC showcase
  2. Webflow-primefaces-showcase
  3. Spring Petclinic
  4. Spring Travel

 

I will walk through the steps of building and deploying these applications, indicating what changes need to be made in order to get the respective application working.

 

You can also find the complete modified examples in my GitHub copy of the original Spring examples svn repository: https://github.com/mbogoevici/spring-samples/tree/as7-blog

 

Deploying and running the examples

 

Each example is a Maven-based project. Therefore a simple:

 

mvn clean package

 

will build you the appropriate war file in each case.

 

Then, you can deploy them in JBoss AS as follows:

 

cp target/<war-name>.war $JBOSS_HOME/standalone/deployments

Changes required

So, did I need to make any changes in order to get these examples run in JBoss? To begin answering that question - the changes weren't so many. In older versions of JBoss AS, the first step would have been a general pruning of the server-provided dependencies from each application, but due to the modular classloading strategy, there aren't so many server-provided dependencies that make server classes visible to your deployment. Therefore, the chance of a conflict is greatly reduced.

Spring MVC showcase

I chose it because it is an application that demonstrates most of the Spring 3 MVC features. It needs no changes in order to build and deploy properly in JBoss.  Building and copying the war in the right place is all what you need to do.

Webflow Primefaces Showcase

I chose it because it is a Spring Webflow application, and also an example of Spring JSF integration. Again, no changes. Running in JBoss AS7 comes down to building and deploying the war.

Spring Petclinic

The previous examples were mostly demos for Spring's presentation layer capabilities. How about throwing some persistence into the mix? Petclinic is a good testing ground for that, because it provides not one, but 3 persistence strategies (or 5, if you count the different persistence providers separately):

  • native JDBC;
  • native Hibernate;
  • JPA (with an option to use EclipseLink, OpenJPA and Hibernate as persistence providers).

You can switch between the options by changing the web.xml file, as well as the jpa-persistence.xml file (for switching between the various providers).

Some cleanup

One first change that I had to do to Spring Petclinic was to update Spring from 3.0.0 to 3.0.5. Apart from the fact that latest is always best, this was necessary in order to avoid running into https://jira.springsource.org/browse/SPR-7197, which causes Spring 3 versions earlier than 3.0.3 not to work properly on JBoss AS6 and JBoss AS7.

 

Also, the Spring MVC bean definitions needed to change a bit, because the servlet mapping to '/*' was not compatible with JBoss AS7 - neither does it work on versions of Tomcat 6.0.32+ or Tomcat 7. This is also reported as https://jira.springsource.org/browse/SPR-8422.

Both fixes are shown here.

 

Finally, there is bug in the application which does not prevent the application from deploying and running, but will cause it to crash when trying to delete a pet (it's not an integration issue, but simply an application bug). The fix is here.

 

What we have gotten so far is an application which uses Spring 3.0.5 and can run on latest versions of Tomcat.

Spring Petclinic with Native JDBC

The application runs without further changes.

Spring Petclinic with Native Hibernate

The application runs without further changes if the class EntityManagerClinic, which is not employed by the application is excluded from the build [1]. It's worth spending a bit time on this, though.

 

Spring 3.0 (and likely 3.1 as well) is not compatible with Hibernate 4, which is the version used by the application server. However, the Petclinic application packages Hibernate 3 already, and due to the modular classloading features of JBoss AS7, the Hibernate module (or Hibernate libraries) are not added to deployment's classpath. If you wanted, you could have added them explicitly, but in this case it's not advisable: the application runs with the included libraries).

Spring Petclinic with JPA (Hibernate)

For this example, we will switch the persistence provider to Hibernate. Eclipse and OpenJPA require the presence of a LoadTimeWeaver, and the one provided by Spring 3.0 is not compatible with JBoss AS7. While this may be supported by a fix in Spring 3.1/3.2, Snowdrop 2.0 will contain a JBoss AS7-compatible LoadTimeWeaver. However, I prefer to address the topic of load-time weaving in a dedicated post. Also, Hibernate is the most popular JPA provider when running on JBoss and does not require a load-time weaver, so this choice this will already cover a majority of the use cases.

 

In order to switch to Hibernate, change the applicationContext-jpa.xml file and switch the jpaVendorAdaptor to org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter as shown here. Your final definition should look like this:

 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
             p:dataSource-ref="dataSource">
     <property name="jpaVendorAdapter">
 

        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
              p:database="${jpa.database}" p:showSql="${jpa.showSql}"/>
     </property>
     <property name="persistenceXmlLocation" value="classpath:META-INF/jpa-persistence.xml"/>
</bean>

 

In the previous case, the application was isolated from the Hibernate libraries. But for applications that use JPA, the persistence API and Hibernate libraries are attached automatically by the server, as described here.

 

So it is necessary to tell JBoss not to include these. You can do this very easily, by adding a /WEB-INF/jboss-deployment-structure.xml file with the following content:

 

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
  <deployment>
    <exclusions>
       <module name="org.hibernate"/>
    </exclusions>
  <deployment>
</jboss-deployment-structure>

 

 

After doing so (the commit is here), the application is good to go.

 

Spring Travel

Spring Travel uses Spring Webflow, and it is another example of Spring JPA integration. In a similar fashion to Spring Petclinic JPA, it uses a Spring-bootstrapped EntityManagerFactory.

 

The main difference between Spring Petclinic and Spring Travel is that, while Spring Petclinic describes its persistent unit in a WEB-INF/classes/META-INF/jpa-persistence.xml file, Spring Travel uses /WEB-INF/classes/META-INF/persistence.xml as its persistence unit configuration location.

 

Since the content of /WEB-INF/classes/META-INF/persistence.xml  is not a deployable persistence unit definition (e.g. there is no datasource definition, which is supposed to be supplemented by Spring), the application will not deploy properly. In order to prevent that from happening, you may rename the persistence unit definition file and update the entity manager factory bean definition as in the following commit. Here is how your Spring definition may look like:

 

 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="dataSource" ref="dataSource" />
   <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
   <property name="persistenceXmlLocation" value="classpath*:META-INF/jpa-persistence.xml"/>
</bean>

 

 

In future versions of JBoss AS it will be possible to instruct the application server to suppress the deployment of a persistence units altogether which would elliminate the need to rename the file. Until then, renaming the persistence definition file is a Spring-supported way of ensuring that no conflicts exist. And it is portable across application servers!

 

As well, because Spring 3 cannot interact properly with the Hibernate 4 module added automatically by the server, you need to exclude the 'org.hibernate' module by adding the /WEB-INF/jboss-deployment-structure.xml as shown above. Here's the commit.

 

Note that starting with Spring 3.1.0.RC1 (unreleased at the time when this article was written), it will be possible to use Hibernate 4 as a JPA provider with Spring (but not in a native scenario), so you may opt between including Hibernate in your application and excluding the server-provided module or using the server dependency (case in which we advise to exclude Hibernate from your build). [See note 2]

 

After doing so, you can build, run the example and enjoy the power of the JBoss AS7.

Conclusions

My main goal was to show you how a few Spring examples which have not been specifically designed to be compatible with JBoss AS7 can be deployed and executed without changes, or in the worst case scenario, with a minimal set of changes.

 

The new modular classloading strategy of the application server reduces the number of conflicts and duplications, and allows you more leeway to package your own dependencies in the application. The only time when a conflict happened was for JPA applications and you have seen how to elliminate the classloading conflicts, as well as how to prevent the server from acting upon a file which is not compatible with the Java EE deployment requirements.

 

There is many more to discuss about persistence management in JBoss AS7. In my next post, I will dive a bit deeper into the persistence configuration options and how do they affect Spring applications. 

 

Notes:

 

[1] The EntityManagerClinic is not being used in the Hibernate version of the application. However, the presence of the @PersistenceContext       annotation will lead to the addition of the Hibernate 4 module as a dependency as shown here. If you would prefer to include this class in the deployment, then add the /WEB-INF/jboss-deployment-structure.xml to the project as well.

 

[2] Thanks to Juergen Hoeller for providing this information.

 

Edits:

 

1. Corrected file name from /WEB-INF/jboss-deployment-structure.xml

2. Added information about Hibernate 4 JPA support in Spring 3.1.0.RC1

3. Clarified the behaviour of the Hibernate version of the application, mentioning the exclusion of EntityManagerClinic.