If I add @Validated
annotation to interface/implementation of my service then the service is not transactional anymore. Stacktrace shows there is no TransactionInterceptor
but I see only MethodValidationInterceptor
. If I remove @Validated
then I see TransactionInterceptor
and MethodValidationInterceptor
disappears of course. Are these aspects mutually exclusive?
@Service
//@Validated <- here is my problem :)
public interface AdminService {
String test(String key, String result);
}
public class AdminServiceImpl implements AdminService, BeanNameAware, ApplicationContextAware {
@Override
@Transactional(transactionManager = "transactionManager")
public String test(String key, String result) {
return "hehe";
}
}
@Configuration
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableTransactionManagement(order = AspectPrecedence.TRANSACTION_MANAGEMENT_ORDER)
public class AppConfiguration {..}
You can check if transaction is active using TransactionSynchronizationManager. isActualTransactionActive() . But you should call it before a service method executing. TransactionStatus status = TransactionAspectSupport.
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings.
You should use @Transactional at service layer, if you want to change the domain model for client B where you have to provide the same data in a different model,you can change the domain model without impacting the DAO layer by providing a different service or by creating a interface and implementing the interface in ...
The @Transactional annotation on the class level will be applied to every method in the class. However, when a method is annotated with @Transactional (like, updateFoo(Foo foo) ) this will take precedence over the transactional settings defined at the class level.
SOLVED
@Transactional
and @Validated
do not work together when a service injecting its own proxy by using ApplicationContextAware
interface like below:
private String beanName;
private AdminService self;
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
self = applicationContext.getBean(beanName, AdminService.class);
}
During the debugging process I noticed that setApplicationContext()
method is called by ApplicationContextAwareProcessor
during the post processing phase in which also MethodValidationPostProcessor
(@Validated
) and AnnotationAwareAspectJAutoProxyCreator
(@Transactional
and @Aspects
) wrap the original beans into proxy instances.
Invocation of getBean()
method in the middle of this process causes the bean not to be fully initialized because some of the post processing operations are not applied. In my case TransactionInterceptor
was not added.
For injection of the own proxy to services I finally created specialized Ordered BeaNPostProcessor executed with the LOWEST_PRECEDENCE
to be sure I operate on a fully initialized bean.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With