Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Shortcut Annotations for @Transactional not working

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?

like image 711
Rafael Avatar asked May 23 '11 18:05

Rafael


People also ask

On which can be @transactional annotation be applied?

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.

Can @transactional annotation only be used at class level?

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.

What does @transactional annotation mean?

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".

Can we use @transactional on interface?

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.


1 Answers

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);
like image 78
Sean Patrick Floyd Avatar answered Nov 04 '22 10:11

Sean Patrick Floyd