I am trying to create custom annotations in order to shortcut, just as referenced in the documentation:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("order")
public @interface OrderTx {
}
However when I annotate methods with the custom annotation, I get an exception:
No hibernate session bound to thread, and configuration does not allow creation...
etc. While annotating the method with @Transactional
works perfectly.
Since the method that I am annotating does not belong a Bean instantiated from the Application Context, my guess is that the AnnotationTransactionAspect
is not working with custom Annotations, and AOP magic is not working.
How can I get custom annotations that shortcut transactions and work everywhere?
Am I missing something else?
The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.
Annotation Type Transactional. Describes a transaction attribute on an individual method or on a class. When this annotation is declared at the class level, it applies as a default to all methods of the declaring class and its subclasses.
The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional semantics; for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction".
You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.
Here are the pointcuts used in AnnotationTransactionAspect
:
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
I'd say it's pretty clear that meta-annotations aren't matched (and I don't even think there is a valid aspectj pointcut that could catch meta-annotations). So I guess you'll have to subclass AbstractTransactionAspect
and provide your own implementation for this pointcut to catch your custom annotation:
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
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