Rollback on every checked exception, whenever I say @Transactional Rollback on every checked exception, whenever I say @Transactional spring spring

Rollback on every checked exception, whenever I say @Transactional


Custom Shortcut Annotations

I know, that I could create a custom annotation, but that seems unnatural.

No, this is exactly the use case for a Custom Annotation. Here's a quote from Custom Shortcut Annotations in the Spring Reference:

If you find you are repeatedly using the same attributes with @Transactional on many different methods, then Spring's meta-annotation support allows you to define custom shortcut annotations for your specific use cases.

Sample Code

And here's a sample annotation for your use case:

@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Transactional(rollbackFor=Exception.class)public @interface MyAnnotation {}

Now annotate your services and / or methods with @MyAnnotation (you'll think of a better name). This is well-tested functionality that works by default. Why re-invent the wheel?


Approach with custom annotation looks good and straightforward, but if you actually don't want to use it, you can create a custom TransactionAttributeSource to modify interpretation of @Transactional:

public class RollbackForAllAnnotationTransactionAttributeSource     extends AnnotationTransactionAttributeSource {    @Override    protected TransactionAttribute determineTransactionAttribute(            AnnotatedElement ae) {        TransactionAttribute target = super.determineTransactionAttribute(ae);        if (target == null) return null;        else return new DelegatingTransactionAttribute(target) {            @Override            public boolean rollbackOn(Throwable ex) {                return true;            }        };    }}

And instead of <tx:annotation-driven/> you configure it manually as follows (see source of AnnotationDrivenBeanDefinitionParser):

<bean id = "txAttributeSource"    class = "RollbackForAllAnnotationTransactionAttributeSource" /><bean id = "txInterceptor"    class = "org.springframework.transaction.interceptor.TransactionInterceptor">    <property name = "transactionManagerBeanName" value = "transactionManager" />    <property name = "transactionAttributeSource" ref = "txAttributeSource" /></bean><bean    class = "org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor">    <property name="transactionAttributeSource" ref = "txAttributeSource" />    <property name = "adviceBeanName" value = "txInterceptor" /></bean>

Also you need <aop:config/> or <aop:aspectj-autoproxy />.

However note that such overrides may be confusing for other developers who expect a normal behaviour of @Transactional.


You can:

  • catch and wrap the checked exception into an unchecked exception - throw new RuntimeException(checkedException)
  • create a proxy around the method, using MethodInterceptor (or @AroundInvoke, or any other means to create aspects in spring), declare it to be executed before the <tx:annotation-driven /> by specifying order="1" and order="2" and catch and wrap there.