Spring @Transaction Method Call by the Method Within the Same Class, Does Not Work

Spring @Transactional does not work when I call a method inside of it. How can I slove it?

You need to put the @Transactional annotation above the nestedTransaction() method as well for the transaction to commit. Also, the propagation = Propagation.REQUIRED property is default, so you don't need to specify it.

Can @Transactional method call another @Transactional method without suspending?

As far as i know you can't do it with annotation REQUIRED_NEW.

But spring also support transaction manually with TransactionTemplate, TransactionDefinition.

we can use multiple definitions with just one PlatformTransactionManager.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionDefinition.html

https://www.baeldung.com/spring-programmatic-transaction-management#4-custom-transaction-configurations

Calling @Transactional method from non-transactional method in Spring 4.3

But this code works correctly in Spring 4.3.20. Is this rule actual
for Spring 4.3.20?

Yes. SonarLint is correct. Self-invocation cannot make @Transactional to take effect. It does not change even in Spring 5. That is how Spring AOP works (refer to docs). Your codes works most probably because you start another transaction inside itemDao (May be you have another @Transactional marked on ItemDao#addItems()).

if I make the second method as package-private, the SonarLint warning
disappears... Why?

Don't know why. Maybe it is a bug. As mentioned in this rule , it should give you warning when mark @Transactional in private method.

The Old "@Transactional from within the same class" Situation

By reading your question it's not really clear where you are stuck, so I am going to briefly list what is needed to get AspectJ intercept your @Transactional methods.

  1. <tx:annotation-driven mode="aspectj"/> in your Spring configuration file.
  2. <context:load-time-weaver/> as well in your Spring configuration file.
  3. An aop.xml located in the META-INF folder directly in your classpath. The format of this is also explained here. It should contain an aspect definition for that handles the @Transactional annotation: <aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
  4. The weaver element in that same file should also have an include clause that tells it which classes to weave: <include within="foo.*"/>
  5. aspectjrt.jar, aspectjweaver.jar, spring-aspects.jar and spring-aop.jar in the classpath
  6. Starting the application using the flag -javaagent:/path/to/spring-instrument.jar (or spring-agent, as it is called in earlier releases)

The final step may not be necessary. It is a really simple class that enables using the InstrumentationLoadTimeWeaver, but if not available Spring will try to use another load time weaver. I have never tried that, though.

Now, if you think you have fulfilled all steps and still are having problems, I can recommend enabling some options on the weaver (defined in aop.xml):

<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">

This makes the weaver output a bunch of information what is being weaved. If you see classes being weaved, you can look for your TestClass there. Then you at least have a starting point to continue troubleshooting.


Regarding your second edit, "It's almost like the weaving isn't happening fast enough to be woven before the class tries to execute.", the answer is yes, this can happen. I experienced a situation like this before.

I am a little rusty on the specifics, but basically it is something in the lines that Spring will not be able to weave classes that are loaded before the application context is being created. How are you creating your application context? If you are doing it programatically, and that class has a direct reference to TestClass, then this problem could occur, since TestClass will be loaded too early.

Unfortunately, I have found that debugging AspectJ is hell.



Related Topics



Leave a reply



Submit