Results 1 to 2 of 2

Thread: Spring @transactional behaving strangely with mode=aspectj

  1. #1
    Join Date
    Oct 2011
    Posts
    2

    Default Spring @transactional behaving strangely with mode=aspectj

    I've been trying to get Spring transactions working properly in my application for days, and now I have nowhere to turn but to the community. Thanks in advance for your help.

    My application has specific requirements where I need to annotate a protected overridden method with @Transactional and call this method from the abstract parent class. From what I've read, I can not use proxies, and must use mode=aspectj.

    First, some configuration:

    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSou rceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"
    proxy-target-class="false" mode="aspectj" />

    <context:load-time-weaver />

    <bean name="ID_DataAccessor" class="dal.DataAccessor">
    <constructor-arg ref="dataSource" />
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost" />
    .....
    <property name="defaultAutoCommit" value="true" />
    </bean>
    If I use the @Transactional annotation on a method in ID_DataAccessor, then the connection is transactional (DataSourceUtils.isConnectionTransactional(c, dataSource) == true). This is useless to me though, because the transaction commits as soon as the method is completed. When I use @Trasnactional on a method that calls a method in DataAccessor, the connection aquired in DataAccessor (from DataSourceUtils.getConnection(dataSource)) is NOT transactional. Additionally, I put a breakpoint in DataSourceTransactionManager.doGetTransaction(), and this is only called if the @Transactional annotation is directly on the method acquiring the connection. Forgive me for overloading the terminology, but it appears that the @Transactional annotation does not propagate up the stack.

    Here's some more context, which may or may not be helpful:
    - DataAccessor contains methods such as getData() and storeData(). It stores a Spring-injected DataSource reference internally and interacts with it through DataSourceUtils.
    - A Processor class contains business logic and interacts with the Spring-injected DataAccessor.
    - The Processor class has an abstract parent class with an abstract protected doProcess() method. The parent defines a public process() method that in turn calls doProcess().
    - I want the transaction to begin in some cases on protected Process.doProcess(), in some cases on another method in the Processor which is invoked by Process.doProcess(), and in some cases to be excluded (no transaction).

    I'm completely baffled. Please help!

  2. #2
    Join Date
    Oct 2011
    Posts
    2

    Default

    This problem was solved on StackOverflow.

    http://stackoverflow.com/questions/7...h-mode-aspectj

    I just about gave up on this one. It was quite non-obvious. Your problem is caused by using the EndOfDayProcess class in your entry point. It's a problem because it causes the class to be loaded, and more generally, it'll extend to any of your *Process and *EntryPoint classes. At that point in your code, Spring hasn't been started yet, so its load-time weaver isn't active, and the class gets loaded normally, without the transaction code woven into it. Of course, classes are only loaded once, so it's there to stay, and when you create the bean in Spring, it's a bean whose type doesn't have anything to do with transactions, except it has @Transactional annotations on it. By then, there's nobody there to see them anymore, though. I see two possible (good) solutions:

    1. Switch to build-time weaving. Then it's impossible to load a class before its woven.
    2. Change the way you determine which *Process bean to use based on the entry point. Use anything you like except for something that causes the *Process class to be loaded.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •