Google

Jun 5, 2014

Java AOP with aopalliance -- method interceptors and custom annotations

Spring Interview Questions and Answers Q1 - Q14 are FAQs

Q1 - Q4 Overview & DIP Q5 - Q8 DI & IoC Q9 - Q10 Bean Scopes Q11 Packages Q12 Principle OCP Q14 AOP and interceptors
Q15 - Q16 Hibernate & Transaction Manager Q17 - Q20 Hibernate & JNDI Q21 - Q22 read properties Q23 - Q24 JMS & JNDI Q25 JDBC Q26 Spring MVC Q27 - Spring MVC Resolvers

Step 1: What is AOP Alliance?

AOP Alliance intends to facilitate and standardize the use of AOP to enhance existing middle ware environments (such as JEE), or development environements (e.g. Eclipse, NetBeans). The AOP Alliance also aims to ensure interoperability between Java/JEE AOP implementations to build a larger AOP community.

AOP Alliance is a set of interfaces that multiple frameworks implement, including both Guice and Spring.

  <groupId>aopalliance</groupId>
  <artifactId>aopalliance</artifactId>
  <version>1.0</version>
  

Q. Why use AOP Alliance in Spring?

Spring AOP can be used together with AOP Alliance MethodInterceptors. AOP Alliance compliant interceptors foster interoperability with other AOP frameworks such as Google Guice. Spring can be used with AspectJ as well, which has annotation syntax that is concise and expressive.

Step 2: Define a custom annotation so taht a method that is annotated with this custom annotation can be retried based on supplied values like attempts,interval, etc.

package com.interceptor.retry;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Retry {

 int attempts() default 3;
 int interval() default 3000;
 boolean nonNullReturn() default true;
 Class<? extends Throwable> exception() default RetryException.class;
 
    //static inner class 
 static class RetryException extends Throwable {
   private static final long serialVersionUID = 1L; // for serialization
   private RetryException() {}

 }  
}


Step 3: Java method interceptor using the aop alliance jar to implement retry logic as a cross cutting concern. Mthods annotated with @Retry will be retried after waiting for the supplied interval.

package com.interceptor.retry;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;


public class RetryMethodInterceptor implements MethodInterceptor {

 @Override
 public Object invoke (MethodInvocation invocation) throws Throwable {
     //
  Method annotatedMethod = invocation.getMethod();
  Method objectMethod = invocation.getThis().getClass()
                                            .getMethod(annotatedMethod.getName(), 
                                             annotatedMethod.getParameterTypes());
  Retry retry = objectMethod.getAnnotation(Retry.class);

  Throwable throwable = null;
  Object result = null;
  int attempt = 0;

  String method = String.format("%s.%s", invocation.getMethod().getDeclaringClass()
                                                               .getName(), 
                                                                invocation.getMethod().getName());
  System.out.println("Invoking {}" + method);

  do {
   attempt++;
   try {
    result = invocation.proceed();
    if (result == null && retry.nonNullReturn()) {
     throw new RuntimeException(String.format("Non-null return expected for %s", method));
    }
    System.out.println("Completed {}" + method);
    return result;
   } catch (Throwable retryThrowable) {
    throwable = retryThrowable;
    try {
     Thread.sleep(retry.interval());
    } catch (InterruptedException e) {
     System.out.println("Retry wait interrupted");
    }
   }
  } while (attempt < retry.attempts());

  //if reached here, all retires have failed
  System.out.println(String.format("Failed invoking %s", method));
  throw retry.exception().getConstructor(Throwable.class).newInstance(throwable);
 }
}


The above example is frequently used in enterprise applications to solve issues relating to

1. Deadlock retry.
2. Service retry.

Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home