Google

Apr 15, 2014

Understanding dynamic proxies in Java with a practical example -- Service retry example

We earlier looked at  Java dynamic proxy class example --  Performance testing your Java application.

Design pattern: If you are asked to describe or talk about a design pattern, you could mention this dynamic proxy class as a proxy design pattern. Many pick either singleton or factory design pattern. It would be nicer to pick something other than these two common patterns. Some interviewers specifically ask you to pick anything except factory and singleton design pattern.

In real life applications, you need to retry services that fail. Let's us this retry service scenario to demonstrate dynamic proxy design pattern in Java.

Step 1: Create a dummy service to emulate an internal or external service with outage.


public interface DummyService {
     abstract void execute();
}


Step 2: The dummy service implementation that emulates failure every time except every 3rd call.

public class DummyServiceImpl implements DummyService {
 
 private int count = 0 ;
 
 public void execute() {
  count++;
  if(count % 3 == 0){
   System.out.println ("Executing service ............. ");
  }
  else {
   throw new RuntimeException("Service Cannot be accessed ..... ");
  }
 }

}




Step 3: Write a Retry service class using the dynamic proxy pattern, which acts as a proxy to retry services on its delegate i.e. DummyService. The service  invoker can specify the retry count.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class RetryProxy<T> implements InvocationHandler {

 final T delegate; // underlying object
 int retryCount;

 //create a proxy
 public static Object newInstance(Object obj, int retryCount) {
  return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
    obj.getClass().getInterfaces(), new RetryProxy(obj, retryCount));
 }

 private RetryProxy(T underlying, int retryCount) {
  this.delegate = underlying;
  this.retryCount = retryCount;
 }

 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  int retries = 0;
  boolean completed = false;
  Object ret = null;

  while (!completed) {
   try {
    ret = method.invoke(delegate, args);
    completed = true;
   } catch (Exception e) {
    retries++;
    if (retries > retryCount) {
     completed = true;
     throw e;
    }
    System.out.println("Retrying the service. Retry count " + retries);
   }
  }

  return ret;

 }
}



Step 4: The test class to invoke the DummyService via its proxy.

public class DummyServiceInvocationTest {

 public static void main(String[] args) {
  DummyServiceInvocationTest test = new DummyServiceInvocationTest();
  test.method1();
 }

 public void method1() {
  DummyService service = (DummyService) RetryProxy.newInstance(new DummyServiceImpl(), 1);
  service.execute();
 }

}


Output:

Retrying the service. Retry count 1
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
 at com.sun.proxy.$Proxy0.execute(Unknown Source)
 at DummyServiceInvocationTest.method1(DummyServiceInvocationTest.java:13)
 at DummyServiceInvocationTest.main(DummyServiceInvocationTest.java:8)
Caused by: java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:491)
 at RetryProxy.invoke(RetryProxy.java:28)
 ... 3 more
Caused by: java.lang.RuntimeException: Service Cannot be accessed ..... 
 at DummyServiceImpl.execute(DummyServiceImpl.java:12)
 ... 8 more


Increase the number of recounts to 3

 public void method1() {
  DummyService service = (DummyService) RetryProxy.newInstance(new DummyServiceImpl(), 3);
  service.execute();
 }



Output:


Retrying the service. Retry count 1
Retrying the service. Retry count 2
Executing service ............. 

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home