Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Transactional is applied both as a dynamic Jdk proxy and an aspectj aspect

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?

like image 955
waxwing Avatar asked Aug 26 '10 08:08

waxwing


People also ask

What is the use of @transactional in spring?

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.

On which can the @transactional annotation be applied?

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.

What is the use of @transactional in Java?

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.

What does @transactional mean in spring boot?

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".


2 Answers

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.

like image 71
Sean Patrick Floyd Avatar answered Sep 21 '22 10:09

Sean Patrick Floyd


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/

like image 40
Rian Avatar answered Sep 18 '22 10:09

Rian