I am in the process of adding Spring declarative transactions via the @Transactional annotation to an existing Java project.
When I ran into a problem (unrelated to this question), I turned on full debug logging. Curiously, I noticed the following:
17:47:27,834 DEBUG HibernateTransactionManager:437 - Found thread-bound Session [org.hibernate.impl.SessionImpl@10ed8a8e] for Hibernate transaction 17:47:27,845 DEBUG HibernateTransactionManager:470 - Participating in existing transaction 17:47:27,865 DEBUG AnnotationTransactionAttributeSource:106 - Adding transactional method 'updateUserProfile' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' 17:47:27,875 DEBUG AnnotationTransactionAspect:321 - Skipping transactional joinpoint [se.myservice.UserService.updateUserProfile] because no transaction manager has been configured
After some debugging, I found out that the first three log entries, where it says it found a thread-bound session and is using that transaction, is produced by a JdkDynamicAopProxy on my UserService class.
The last log message looks alarming though. It is invoked at a joinpoint before the method execution. When looking at the source for AnnotationTransactionAspect, it produces this message if no transaction manager has been set. In this case, because Spring never performs any dependency injection on this aspect.
It looks to me like two different "styles" of transactions are both applied: the dynamic proxy, AND the aspect. The only transaction-related configuration I have is:
<tx:annotation-driven transaction-manager="txManager" />
We are using AspectJ in the project, but there is no AnnotationTransactionAspect aspect registered in my aop.xml. We are using Spring 3.0.2.RELEASE.
Should I be alarmed by this? Does Spring register this aspect for me? Should I not use annotation-driven
when using AspectJ?
The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.
You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.
Transactional annotation provides the application the ability to declaratively control transaction boundaries on CDI managed beans, as well as classes defined as managed beans by the Java EE specification, at both the class and method level where method level annotations override those at the class level.
The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional semantics; for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction".
Strange, it sounds like you have this configuration:
<tx:annotation-driven
transaction-manager="transactionManager" mode="aspectj" />
(Transaction support using AspectJ, not JDK proxies)
Since your config doesn't have a mode attribute, the default should kick in (proxy mode). But AnnotationTransactionAspect is the exact aspect used by the aspectj mode.
To get aspectj transactions working with java config.
@EnableWebMvc
@Configuration
@ComponentScan("com.yourdomain")
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
public class ApplicationConfig extends WebMvcConfigurerAdapter {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
//...
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager bean = new JpaTransactionManager(entityManagerFactory().getObject());
return bean ;
}
@Bean
public AnnotationTransactionAspect annotationTransactionAspect() {
AnnotationTransactionAspect bean = AnnotationTransactionAspect.aspectOf();
bean.setTransactionManager(transactionManager());
return bean;
}
}
If you are using maven:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
If you are using eclipse, this will ensure that the weaving is done when deploying inside eclipse:
http://www.eclipse.org/ajdt/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With