I have a Spring MVC app with all logic related to a single business concern within a single Java package (controller, service, repository, DTO and resource). I enforce this by making all methods across presentation, service and persistence layers package-private (no interfaces are used). NB: layer separation is enforced with Maven modules with optional dependencies (presentation layer does not see persistence layer).
However, the repository shall also be @Transactional
, and using Spring defaults (adding spring-tx
Maven dependency + declaring @EnableTransactionManagement
+ creating a new DataSourceTransactionManager(dataSource)
@Bean
) isn't enough: the repository is no more proxified when it does not have at least one public method (I check this with AopUtils.isAopProxy()
in an integration test).
What is the most straightforward way (minimal example) to solve this with Maven + annotation-based Spring + Tomcat? (I heard about AspectJ and would prefer to avoid it if another solution fits the need, because AspectJ seems complex to set up and is incompatible with Lombok --but I guess I could replace it with @AutoValue, custom aspects, Spring Roo, etc.)
EDIT: I attempted to use AspectJ and could so far add aspects (only using @Aspect
i.e. without any transactions involved) to a package-private class with only package-private methods (using compile-time weaving). I'm currently stuck trying to do the same with @Transactional
. When I make the class and its methods public and define @EnableTransactionalManagement
, it works (getCurrentTransactionName()
shows something). But as soon as I change to @EnableTransactionalManagement(mode = ASPECTJ)
, it does not work any more, even when the class and its methods remain public (getCurrentTransactionName()
shows null
). NB: proxyTargetClass
is irrelevant when using AspectJ mode.
EDIT2: OK I managed to solve this with AspectJ, both with compile-time and load-time weaving. The critical information I was missing was the JavaDoc of AnnotationTransactionAspect
: package-private methods do not inherit transactional information from class annotations, you must put @Transactional
on the package-private method itself.
Aucun commentaire:
Enregistrer un commentaire