Affects: 6.0.4
When class annotated with @Transactional
annotation is registered in @Configuration
class no actual transaction is started when calling methods while running in native image. When the same class is registered with @Service
annotation everything works as expected. Both cases work fine in standard (non-native) run. This used to work in experimental version of spring-native but required manual registration of @Transactional
beans.
Provided example uses Spring Boot 3.0.2 for ease of configuration and when run in native mode the following exception occurs:
jakarta.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
The class implements an interface and the interface is injected in CommandLineRunner and a method is called to save the entity.
spring-transactional-issue.zip
Comment From: sdeleuze
I understand it could be surprising, but the behavior you observe is expected because the type exposed but the @bean
annotated method is DemoEntityService
(the interface without@Transactional
), the fact that DefaultDemoEntityService
is the implementation is invisible to the AOT engine.
If you change the return type to DefaultDemoEntityService
, it works as expected since it allows the AOT engine to infer the required hints. It should probably work as well with DemoEntityService
and manual hints.
I will update the reference documentation to mention that limitation.
Comment From: agrancaric
Hello, thanks for a quick reply. This is just an example the issue is actually in a framework that I am maintaining and uses autoconfiguration to register default implementations. I am injecting interfaces to allow users to override default behaviour by providing another implementation. I've tried to annotate the interface with @Transactional
and I've also tried registering hints for default implementation I get the same error:
java.lang.UnsupportedOperationException: CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: com.example.springtransactionalissue.service.DefaultDemoEntityService$$SpringCGLIB$$0
And if I register hints for DefaultDemoEntityService$$SpringCGLIB$$0 transaction is not started. For me it seems that Springs default registration of @Transactional
annotated classes is the problem here, and if it could be disabled for some class it could allow me to register a custom hint. Not sure is that possible somehow?
Comment From: sdeleuze
Indeed I can reproduce, I will have a deeper look.
Comment From: agrancaric
Ok, thanks.
Comment From: sdeleuze
You can make it work by moving the @Transactional
issue to the interface and configuring spring.aop.proxy-target-class=false
in Spring Boot (true
by default).
Comment From: izeye
It seems that the "type: bug" label can be dropped as there's no bug fix here.
Comment From: sdeleuze
Done and I have updated the release notes accordingly.