Spring 3, Hibernate JPA, Tomcat transactions

I tried to deploy a webapp that uses Spring 3, JPA with the Hibernate implementation and Tomcat. There are domain classes with a DAO layer which is called from the Service layer. The classes are annotated correctly. All of the unit tests work. Actually the whole webapp works deployed on other web containers : but not on Tomcat!

The problem was that in my service’s save() method I required a transaction. Of course! That’s what you have to do. The actual problem is that I needed a transaction in that method but one was not being created.

1
2
3
4
5
 @Override
 @Transactional(propagation = Propagation.REQUIRED, rollbackFor=Exception.class, readOnly = false)
 public Composer create(Composer composer) {
      return this.composerDAO.create(composer);
  }

In the spring config files I did have the usual wiring:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<import resource="dataSource.xml"/>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		p:dataSource-ref="dataSource" 
		p:entityManagerFactory-ref="entityManagerFactory">
		<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
		p:dataSource-ref="dataSource" 
		p:jpaDialect-ref="jpaDialect"
		p:persistence-xml-location="classpath*:${persistence.xml}"
		p:persistenceUnitName="ComposerJPA">
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
				p:showSql="${jpaVendorAdapter.showSql}" 
				p:generateDdl="${jpaVendorAdapter.generateDdl}" 
				p:databasePlatform="${hibernate.dialect}" 
				p:database="${jpaVendorAdapter.database}"/>
		</property>
</bean>
<!-- used by tx manager and entityManagerFactory -->
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
 
<context:annotation-config />
<context:property-placeholder location="/WEB-INF/spring/db.properties" />

I know you’ve seen this all before.

It helps to modify your logging level for Spring’s transaction classes. Here’s an excerpt from my log4j.properties.

1
2
3
4
log4j.logger.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
log4j.logger.org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter=DEBUG
log4j.logger.org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean=DEBUG
log4j.logger.org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor=DEBUG

You see that my config did include the tx:annotation-driven element which creates transaction proxies for methods annotated with @Transactional.

<tx:annotation-driven transaction-manager="transactionManager" />

One thing I modified was the transaction manager’s mode.

<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

Another part of the problem is Tomcat’s classloader. You need to specify a special classloader. I created a context.xml in my webapp directly (you can create it in various other Tomcat locations).

So, I created a file named src/main/resources/META-INF/context.xml

1
2
3
4
<Context path="/ConcertMVC" reloadable="false">
    <Loader
        loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>

Since I was using the SpringSource Tools Suite which includes Tomcat that was it. If you are using a Tomcat distribution from Apache, you need to add a Spring jar to you library directory. This jar is included in the Spring download. If you use Maven then you can add the following dependency:

1
2
3
4
5
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-instrument-tomcat</artifactId>
   <version>${org.springframework-version}</version>
</dependency>

The add it to your tomcat library directory by copying from your Maven repository.

Resources

Share These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Facebook
  • Twitter
  • LinkedIn
  • email
  • DZone
  • Slashdot
  • Reddit
  • Google Bookmarks
  • Digg
  • StumbleUpon
  • del.icio.us
This entry was posted in Hibernate, JPA, Spring Framework and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>