Aspect's Paradigm With Design Patterns (Proxy Pattern)

Implementation of Design patterns with AspectJ is another intersting episode of AspectJ.

After I have implemented a few such Design patterns, I came to realize the power of AspectJ and How beautiful it is.

So,I will share my expereince with this dimension of AspectJ

Proxy Pattren

First, I have created some Utility classes which will be assigned some role using Aspects Dynamically.


package com.aspectj.target;

import java.io.IOException;

import javax.naming.OperationNotSupportedException;

public class PureSubject {

 public String write()
 {
  System.out.println(" @@@ In PureSubject.write() @@@ ");
  return "### PureSubject.write() completed ###";
 }
 
 public String read() throws OperationNotSupportedException
 {
  throw new OperationNotSupportedException("This Operation is not Supported in this version");
 }
 
 public String update() throws OperationNotSupportedException
 {
  throw new OperationNotSupportedException("This Operation is not Supported in this version");

 }
 
}


package com.aspectj.target;

public class ProxySubject {

 public static String read()
 {
  System.out.println(" @@@ In AnotherSubject.read() @@@ ");
  return "### AnotherSubject.read() completed ###";
 }
 
 public static String update()
 {
  System.out.println(" @@@ In AnotherSubject.update() @@@ ");
  return "### AnotherSubject.update() completed ###";
 }
 
 public void proxyController(String methodName)
 {
  System.out.println(" **** Proxy controller is getting called for:"+methodName);
  if("read".equals(methodName))
   read();
  else if("update".equals(methodName))
   update();
 }
 
}
 
PureSubject has got some concrete methods, and some methods are yet to be made concrete in future releases, so when those methods will be invoked an Exception will be thrown and this thing we will byPass by doing a Proxy call, whenever those unimplemented methods are called.

All these and more, all Using AspectJ.

Now two aspects are created.


package com.aspectj.aspect;

public abstract aspect MyNewAspectProxyPattern {

 public interface Proxy                         
 {
  public boolean reject = false;
  public boolean delegate = true;
  public void invoke(String methodName);
 }
 
 public interface Subject
 {
  public Proxy getProxy();
 }
 
 public abstract pointcut createTrigger();
 public pointcut knownCaller():createTrigger();
 public abstract pointcut notKnownCaller(Subject subject);
 
 
 public abstract boolean reject();
 public abstract boolean delegate();
 
 public abstract void rejectRequest();
 public abstract void delegateRequest(Subject subject,String methodName);
 
 
}


package com.aspectj.aspect;

import java.lang.reflect.Method;




public aspect MyNewAspectProxyPatternConc extends MyNewAspectProxyPattern {

 declare parents:com.aspectj.target.ProxySubject implements Proxy;
 declare parents:com.aspectj.target.PureSubject implements Subject;


 

 public Proxy Subject.getProxy()
 {
  return (Proxy) (new com.aspectj.target.ProxySubject());
 }

 public void Proxy.invoke(String methodName)throws Exception
 {
  proxyInvoker(this, methodName);
 }
 
 public static void proxyInvoker(Proxy proxy,String methodName) throws Exception
 {
  Method method = proxy.getClass().getMethod("proxyController", methodName.getClass());
  method.invoke(proxy, methodName);
 }
 
 public pointcut createTrigger():execution(* com.aspectj.target.PureSubject.write(..)) && target(Subject+);
 public pointcut notKnownCaller(Subject subject):((execution(* com.aspectj.target.PureSubject.*(..)) )/* || (execution(* com.aspectj.target.PureSubject.update(..))  )*/) && !createTrigger() && target(subject) ;
 //public pointcut proxyCreationIntercept():execution(* com.aspectj.target.PureSubject.getProxy(..));
 public pointcut proxyCreationIntercept():execution(* Subject+.getProxy(..));
 
 @Override
 public boolean delegate() {
  // TODO Auto-generated method stub
  return Proxy.delegate;
 }

 @Override
 public void delegateRequest(Subject subject,String methodName) {
  try{
  // TODO Auto-generated method stub
  System.out.println(" *** The Subject type for Delegating Request is:"+subject.getClass().getName());
  Proxy proxy = subject.getProxy();
  System.out.println(" *** The Proxy type for Delegating Request is:"+proxy.getClass().getName());
  proxy.invoke(methodName);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }

 @Override
 public boolean reject() {
  // TODO Auto-generated method stub
  return Proxy.reject;
 }

 @Override
 public void rejectRequest() {
  // TODO Auto-generated method stub

 }
 
 String around(): knownCaller() /*&& !target(Object)*/
 {
  System.out.println(" !!!!!For Known caller  !!!!!!");
  return proceed(); 
  
 }
 
 Object around(Subject subject):proxyCreationIntercept() /*&& !within(MyNewAspectProxyPattern+) && target(subject)*/&& this(subject) && !cflowbelow(adviceexecution())
 {
  System.out.println(" getProxy called from Outside advice so CANCELLING Proxy calls for subject:"+subject.getClass().getName());
  return null;
 }
 
 Object around(/*Subject subject*/):proxyCreationIntercept() /*&& within(MyNewAspectProxyPattern+)&& target(subject)*/ && cflowbelow(adviceexecution())
 {
  System.out.println(" getProxy() called from within advice ");
  return proceed();
 }

 
 String around(Subject subject) : notKnownCaller(subject) /*&& !target(com.aspectj.target.PureSubject)*/ /*&& !cflowbelow(adviceexecution())*/
 {
  
  String methodName = (thisJoinPoint.getSignature().toString()).substring((thisJoinPoint.getSignature().toString()).lastIndexOf(".")+1, (thisJoinPoint.getSignature().toString()).lastIndexOf("("));
  System.out.println(" !!!!!For UN-Known caller !!!!!!, So delegating the request for Subject:"/*+subject.getClass().getName()*/);
  if(reject())
   rejectRequest();
  if(delegate())
   delegateRequest(subject,methodName);
  return null ;
 }
 
 

}


Now, the first Aspect is a Generalization and the later is the Specialization.

PureSubject is assigned the role of Subject.

ProxySubject will be assigned the role of Proxy, which will used to proxy the unimplementated methods of Subject.

Now when the execution of the Known method as intercepted by the pointcut createTrigger() occurs, then the flow remains as normal i.e. method call as specified by the around advice

Now, when the execution of the unimplemented methods as intercepted by the pointcut notKnownCaller() occurs, then only the Proxy role comes into the picture and delegates the request of method calls of unimplemented methods of Subject Role to the class implementing the Proxy role i.e.ProxySubject.

Here One Interesting Feature is implemented through proxyCreationIntercept pointcut where the execution of the getProxy method can only be done from the Aspect Itself which is specified by the cflowbelow(adviceexecution()) pointcut expression.

Now, Here is the description of the Pointcut Expressions and the advices where they are applied.

1) knownCaller():createTrigger() ---> which intercepts the execution of com.aspectj.target.PureSubject.write() and where the target is of type Subject or aby subtype of it specified by target(Subject+).

2) notKnownCaller() ---> It intercepts the the execution of any method within PureSubject as specified by com.aspectj.target.PureSubject.*(..) and the method should not belong to the createTrigger() poincut intercepted method specified by !createTrigger() and the target should be of Subject Type specified by target(subject)

3) proxyCreationIntercept ----> It intercepts the execution of the method getProxy() on any Subject Type as specified by execution(* Subject+.getProxy(..))

Now Poincut expression: 1) is applied against an Around advice where the control just follows the normal Flow.
2) is applied against an Around advice where there is deviation from the normal flow and the delegation operation is performed.
3) is applied against two Around advices where in the first advice it is checked whether the method invocation(getProxy()) is ouside the Aspect, if so then there will be no method invocation (null is returned) and in the second advice, if it is from within Aspect then the method execution will continue.
This is in short the application of Aspect on the Proxy Design Pattern. Indeed it is beautiful and Aspect has got so much Power wow!!!!

Please keep posting your issues and experiences, and Happy Coding......

Comments

Popular posts from this blog

Use of @Configurable annotation.

Spring WS - Part 5

Spring WS - Part 4