Vita Rara: A Life Uncommon

JBoss 4, EJB 3 Entities (JPA), and Spring


Categories: | | | | |

Over the last week or so I have been working on getting JBoss, JPA and Spring working together. When I wrote my previous entry I thought I had everything working. Well, up to that point I had not tried to save a record to the database. When I tried to do that nothing happened. This lead to a long debugging process that felt more like a hopeless goose chase at times. With the help of Costin Leau on the Spring forum I finally got it working, but it was quite the trial. Not many people have attempted to get this combination working. One of the things that complicated my setup is that my data access objects are a descendant of the JpaDaoSupport class provided in the Spring framework.

Getting them all working together is a matter of putting everything in the right place. I'm deploying as an ear file containing: a jar file with all of my JPA entities and dao's in it; and a war file that has my jsp's, other web resources, view classes and a jar file containing all of my service beans. I also have a lib directory in my ear file that contains the spring.jar file and the AspectJ jar files. This is very important. My ear file looks like this:

ear - - quadran.war
    | - quadran-data.jar     <-- my persistence archive
    | - lib
         | - spring.jar
         | - aspectjrt.jar
         | - aspectjweaver.jar
    | - META-INF
         | - MANIFEST.MF

I'm using the context loader listener to load my Spring application context from the /WEB-INF/lib/ directory of my war file. I started with putting the Spring and AspectJ jar files in this directory but ran into class loader issues. So in order to expose the Spring and AspectJ jar files to both the data jar and the war I added a classpath entry to the MANIFEST.MF file of both files. The MANIFEST files looks something like this:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.0
Created-By: 1.5.0_06-64 ("Apple Computer, Inc.")
Class-Path: ./lib/vr-utils.jar ./lib/spring.jar ./lib/aspectjweaver.ja
 r ./lib/aspectjrt.jar

I create this using the manifest argument to the ant jar task.

With this in place the ear loads, JBoss sets up the JPA entities, the war loads and the Spring ApplicationContext is created.

In order to get JPA to save things to the database it is necessary to wrap them in a transaction. I do this with the following in my applicationContext.xml file:

    <!-- JPA EntityManagerFactory setup -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="quadran" />
    </bean>

    <!-- Jpa Transaction Manager -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:advice id="managerTxAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="managerMethods" 
            expression="execution(* net.vitarara.quadran.core.business.*Manager.* (..))" />
        <aop:advisor advice-ref="managerTxAdvice" pointcut-ref="managerMethods" />
    </aop:config>

The entityManagerFactory is used by the DAO's to access the JPA EntityManager. The transactionManager is used to manage the transactions, which are defined using the tx:advice and aop:config tags. My tx:advice tag simply configures transactions on all methods. I will narrow this scope in the future, but during my debugging process I decided to cast a wide net. The aop:config uses the aop:pointcut method of selecting what classes to apply the tx:advice to. I have chosen to apply this advice to any method of any class in the net.vitarara.quadran.core.business package that ends in Manager. These classes are actually interfaces, which has the effect of applying this configuration to any class that implements those interfaces.

Deployment of the ear seems to take a while. It seems that JBoss needs to do a lot of thinking to figure out that the Classpath statements in the MANIFEST file refer to jars in the ear file. I may look at possibly adding these to the $JBOSS_HOME/$SERVER_CONFIG/lib directory, but that will take some serious experimentation before I'd really be comfortable with it.

If you know of a better way to get JBoss, JPA and Spring working together I'd love to know it.

LocalEntityManagerFactoryBean?

Hi Mark,

I'm confused about the fact that your using the LocalEntityManagerFactoryBean as your EMF implementation. According to the JavaDoc this means that you are not using the EMF provided by the Application server. Is this really what you want?

I tried to do exactly the same as you mentioned in your discussion with Colin (Spring EJB support forum). I want to use the JBoss EMF via a JNDI lookup and got the same problems (EntityManager is closed after every use of the JpaTemplate).

What happens when you mix your configuration with other DAO's that are implemented as SLSB's that use the container provided EMF? Does that mean that you got 2 persistence providers?

This is very confusing!

Bye
Martin Fischer

JBoss EntityManager

Hi Martin,

The short answer is I'm not using JBoss anymore, nor when I was using JBoss was I using the persistence context created by the application server.

My current configuration is using Spring to bootstrap my persistence context, using the Hibernate JPA implementation. I'm also not using EJB3 session beans. I've moved to a Spring environment. It fit better with my dependency and configuration needs than EJB3 did.

My environment today is Struts 2 with my Groovy Works extension for the view and controller tier, Spring using both Java and Groovy service beans, and Hibernate JPA for the data layer. Spring provides transaction support via it's AOP feature, and glues all of the services together. There's room for improvement, but in general I like it.

Mark

Spring Transactions on JPA

i have an article regarding Spring Transactions on JPA
http://www.ideyatech.com/2008/09/troubleshooting-tips-spring-transactions-on-jpa/