Showing posts with label AOP. Show all posts
Showing posts with label AOP. Show all posts

Thursday, January 9, 2014

Spring Integration Publisher

Consider a hypothetical requirement - You have a service class in your application and you want to capture some information around the calls to this service:

@Service
public class SampleBean {
 private static final Logger logger = LoggerFactory.getLogger(SampleBean.class);

 public Response call(Request request) {
  logger.info("SampleBean.call invoked");
  return new Response(true);
 }
}

AOP is a great fit for such a requirement, it allows the information around a method call(a pointcut) to be cleanly captured and some processing(an advice) to be done with this information:

public class AuditAspect {
 private static final Logger logger = LoggerFactory.getLogger(AuditAspect.class);
 @Pointcut("execution( * core.SampleBean.call(model.Request)) && args(r)")
 public void beanCalls(Request r){}

 @Around("beanCalls(r)")
 public Object auditCalls(ProceedingJoinPoint pjp, Request r) {
     logger.info("Capturing request: " + r);
  try{
   Object response = pjp.proceed();
   logger.info("Capturing response: " + response);
   return response;
  }catch(Throwable e) {
   throw new RuntimeException(e);
  }
 }
}


This appears to be good enough. Now what if I wanted to return the response back to the client immediately but continue to process the context of the method call - well we can place the logic of Advice in a separate thread using a ThreadPool. Let me add another layer of complexity now, what if we wanted to absolutely ensure that context is not lost - a good way to do this would be to keep the context of the method call outside the JVM, typically messaging providers like RabbitMQ and ActiveMQ will fit in very well.


Considering these additional requirements, a simpler solution especially with messaging scenarios coming into play will be to use Spring Integration. Let us start by defining a new Spring Integration application context:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
    xmlns:beans="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <annotation-config/>

    <channel id="tobeprocessedlater"/>

    <logging-channel-adapter channel="tobeprocessedlater" log-full-message="true"/>

</beans:beans>

It just has the definition of a channel, and an outbound adapter which reads from this channel and logs the full message. To capture the context of the call to the SampleBean a Publisher annotation can be added to the relevant methods of SampleBean which will direct "stuff" to the channel which is added to the annotation.

@Service
public class SampleBean {
 private static final Logger logger = LoggerFactory.getLogger(SampleBean.class);

 @Publisher(channel = "tobeprocessedlater")
 public Response call(@Header("request") Request request) {
  logger.info("SampleBean.call invoked");
  return new Response(true);
 }
}

what "stuff" is sent to this "tobeprocessedlater" channel is specified through additional annotations - by default the return value from the method is sent to the channel, additionally I have tagged the request also with the @Header annotation, this will make the request to be sent in as a header to the response message. Just for completeness, the integration context has a <annotation-config/> tag, this tag registers the relevant components that look for @Publisher annotation and weave in the additional action to be performed if it finds one.

If this code is executed now, the output will be along these lines:

                       core.SampleBean - SampleBean.call invoked
o.s.integration.handler.LoggingHandler - [Payload=Response{success=true}][Headers={request=RequestType1{attr='null'}, id=52997b10-dc8e-e0eb-a82a-88c1df68fca5, timestamp=1389268390212}]

Now, to layer in the first requirement, to handle the advice(in this case the logging) in a separate thread of execution:

This can be done with just a configuration change! - instead of publishing the message to a direct channel, publish it to a channel type that can buffer messages or use an executor to dispatch messages, I have opted to use an executor channel in this example:

    <channel id="tobeprocessedlater">
        <dispatcher task-executor="taskExecutor"/>
    </channel>

Now to add the requirement to make the async message processing a little more reliable by publishing it to an external Messaging provider(and processing the messages later), let me demonstrate this by publishing the messages to RabbitMQ, the code change again is pure configuration and nothing in the code changes!:

    <channel id="tobeprocessedlater"/>

    <int-amqp:outbound-channel-adapter amqp-template="amqpTemplate" channel="tobeprocessedlater"  />

The messaging sink could have been anything - a database, a file system, ActiveMQ, and the change that would have been required is pure configuration.

Monday, September 3, 2012

Ways to wire dependencies for an object outside of a Spring Container

There are a few interesting ways of setting the properties and dependencies of an object instantiated outside of a Spring container.

Use Cases

To start with, why would we need to do inject in dependencies outside of a Spring container - I am aware of three use cases where I have instantiated objects outside of the Spring container and needed to inject in dependencies.

Consider first the case of a series of tasks executed using a Spring TaskExecutor, the tasks highlighted below are instantiated outside of a Spring container:

List<Callable<ReportPart>> tasks = new ArrayList<Callable<ReportPart>>();
        List<ReportRequestPart> reportRequestParts = reportRequest.getRequestParts();
        for (ReportRequestPart reportRequestPart : reportRequestParts) {
            tasks.add(new ReportPartRequestCallable(reportRequestPart, reportPartGenerator));
        }

        List<Future<ReportPart>> responseForReportPartList;
        List<ReportPart> reportParts = new ArrayList<ReportPart>();
        try {
            responseForReportPartList = executors.invokeAll(tasks);
            for (Future<ReportPart> reportPartFuture : responseForReportPartList) {
                reportParts.add(reportPartFuture.get());
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }

public class ReportPartRequestCallable implements Callable<ReportPart> {
 private final ReportRequestPart reportRequestPart;
 private final ReportPartGenerator reportPartGenerator;

 public ReportPartRequestCallable(ReportRequestPart reportRequestPart, ReportPartGenerator reportPartGenerator) {
     this.reportRequestPart = reportRequestPart;
     this.reportPartGenerator = reportPartGenerator;
    }

 @Override
    public ReportPart call() {
    return this.reportPartGenerator.generateReportPart(reportRequestPart);
    } 
}

The second use case is with ActiveRecord pattern say with the samples that come with Spring Roo, consider the following method where a Pet class needs to persist itself and needs an entity manager to do this:
@Transactional
    public void Pet.persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

The third use case is for a tag library which is instantiated by a web container, but needs some dependencies from Spring.


Solutions

1. The first approach is actually simple, to provide the dependencies at the point of object instantiation, through constructors or setters. This is what I have used with the first use case where the task has two dependencies which are being provided by the service instantiating the task:

tasks.add(new ReportPartRequestCallable(reportRequestPart, reportPartGenerator));


2. The second approach is a to create a factory that is aware of the Spring container, declaring the beans that are required with a prototype scope within the container and getting the beans by a getBeans method of the application context,

Declaring the bean as a prototype scoped bean:
    <bean name="reportPartRequestCallable" class="org.bk.sisample.taskexecutor.ReportPartRequestCallable" scope="prototype">
     <property name="reportPartGenerator" ref="reportPartGenerator"></property>
    </bean>
    
    <bean name="reportPartRequestCallableFactory" class="org.bk.sisample.taskexecutor.ReportPartRequestCallableFactory"/>

and the factory serving out the bean:
public class ReportPartRequestCallableFactory implements ApplicationContextAware{
 private ApplicationContext applicationContext;

 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = applicationContext;
 }
 
 public ReportPartRequestCallable getReportPartRequestCallable(){
  return this.applicationContext.getBean("reportPartRequestCallable", ReportPartRequestCallable.class);
 }
}


3.  The third approach is a variation of the above approach is to instantiate the bean and then inject dependencies using AutoWireCapableBeanFactory.autowireBean(instance), this way:
public class ReportPartRequestCallableFactory implements ApplicationContextAware{
 private GenericApplicationContext applicationContext;

 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = (GenericApplicationContext)applicationContext;
 }
 
 public ReportPartRequestCallable getReportPartRequestCallable(){
  ReportPartRequestCallable reportPartRequestCallable = new ReportPartRequestCallable();
  applicationContext.getBeanFactory().autowireBean(reportPartRequestCallable);
  return reportPartRequestCallable;
 }
}



4.  The fourth approach is using @Configurable, the catch though is that it requires AspectJ to work. Spring essentially enhances the constructor of the class to inject in the dependencies along the lines of what is being explicitly done in the third approach above:

import org.springframework.beans.factory.annotation.Configurable;

@Configurable("reportPartRequestCallable")
public class ReportPartRequestCallable implements Callable<ReportPart> {
    private ReportRequestPart reportRequestPart;
    @Autowired private ReportPartGenerator reportPartGenerator;

    public ReportPartRequestCallable() {
    }

    @Override
    public ReportPart call() {
       return this.reportPartGenerator.generateReportPart(reportRequestPart);
    }

    public void setReportRequestPart(ReportRequestPart reportRequestPart) {
        this.reportRequestPart = reportRequestPart;
    }

    public void setReportPartGenerator(ReportPartGenerator reportPartGenerator) {
        this.reportPartGenerator = reportPartGenerator;
    }
}

The following is also required to configure the Aspect responsible for @Configurable weaving:
<context:spring-configured/>

With these changes in place, any dependency for a class annotated with @Configurable is handled by Spring even if the construction is done completely outside of the container:

    @Override
    public Report generateReport(ReportRequest reportRequest) {
        List<Callable<ReportPart>> tasks = new ArrayList<Callable<ReportPart>>();
        List<ReportRequestPart> reportRequestParts = reportRequest.getRequestParts();
        for (ReportRequestPart reportRequestPart : reportRequestParts) {
            ReportPartRequestCallable reportPartRequestCallable = new ReportPartRequestCallable(); 
            reportPartRequestCallable.setReportRequestPart(reportRequestPart);
            tasks.add(reportPartRequestCallable);
        }
    .......


Conclusion
All of the above approaches are effective with injecting in dependencies in objects which are instantiated outside of a container. I personally prefer to use Approach 4 (using @Configurable) in cases where AspectJ support is available, else I would go with Approach 2(hiding behind a factory and using a prototype bean).

Tuesday, July 17, 2012

Reference to dynamic proxy in a proxied class

There was an interesting question in Stackoverflow about how a Spring Bean can get a reference to the proxy created by Spring to handle transactions, Spring AOP,  Caching, Async flows etc. A reference to the proxy was required because if there is a call to itself by the proxied bean, this call would completely bypass the proxy.

Consider an InventoryService interface:
public interface InventoryService{
    public Inventory create(Inventory inventory);
    public List<Inventory> list();
    public Inventory findByVin(String vin);
    public Inventory update(Inventory inventory);
    public boolean delete(Long id);
    public Inventory compositeUpdateService(String vin, String newMake);
}

Consider also that there is a default implementation for this service, and assume that the last method compositeUpdateService, internally invokes two methods on the bean itself, like this:
public Inventory compositeUpdateService(String vin, String newMake) {
    logger.info("composite Update Service called");
    Inventory inventory = this.findByVin(vin);
    inventory.setMake(newMake);
    this.update(inventory);
    return inventory;
}

If I now create an aspect to advice any calls to InventoryService with the objective of tracking how long each method call takes, Spring AOP would create a dynamic proxy for the InventoryService bean:

However the calls to compositeUpdateService will record the time only at the level of this method, the calls that compositeUpdateService internally makes to findByVin, update is bypassing the proxy and hence will not be tracked:


A good fix for this is to use the full power of AspectJ - AspectJ would change the bytecode of all the methods of DefaultInventoryService to include the call to the advice.

A workaround that we worked out was to inject a reference to the proxy itself into the bean and instead of calling say this.findByVin and this.update, call proxy.findByVin and proxy.update!

So now how do we cleanly inject in a reference to the proxy into the bean - the solution that I offered was to create an interface to mark beans interested in their own proxies:

public interface ProxyAware<T> {
    void setProxy(T proxy);
}

The interested interface and its implementation would look like this:
public interface InventoryService extends ProxyAware<InventoryService>{
...
}

public class DefaultInventoryService implements InventoryService{ 
    ...

    private InventoryService proxy;
 @Override
 public void setProxy(InventoryService proxy) {
  this.proxy = proxy;
 }
}

and then define a BeanPostProcessor to inject in this proxy!
public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {
 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  return bean;
 }

 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  if (AopUtils.isAopProxy((bean))){
   try {
    Object target = ((Advised)bean).getTargetSource().getTarget();

    if (target instanceof ProxyAware){
     ((ProxyAware) target).setProxy(bean);
    }
   } catch (Exception e) {
    return bean;
   }
  }
  return bean;
 }

 @Override
 public int getOrder() {
  return Integer.MAX_VALUE;
 }
}

Not the cleanest of implementations, but works!

Update:
Tomasz has pointed out a much simpler way to get hold of the proxy in the proxied class, this is by using AopContext.currentProxy() method. Spring AOP has to be instructed to set up this method, it is done through configuration this way:

<aop:aspectj-autoproxy expose-proxy="true"/>

Once this is done, in the proxied class, the reference to the proxy can be obtained by calling AopContext.currentProxy()!

Reference: http://blog.springsource.org/2012/05/23/understanding-proxy-usage-in-spring/

Saturday, June 9, 2012

Creating a Java Dynamic Proxy

Java Dynamic proxy mechanism provides an interesting way to create proxy instances. The steps to create a dynamic proxy is a little tedious though, consider a proxy to be used for auditing the time taken for a method call for a service instance -

public interface InventoryService {
    public Inventory create(Inventory inventory);
    public List<Inventory> list();
    public Inventory findByVin(String vin);
    public Inventory update(Inventory inventory);
    public boolean delete(Long id);
    public Inventory compositeUpdateService(String vin, String newMake);
}

The steps to create a dynamic proxy for instances of this interface is along these lines:
1. Create an instance of a java.lang.reflect.InvocationHandler, this will be responsible for handling the method calls on behalf of the actual service instance, a sample Invocation handler for auditing is the following:
...
public class AuditProxy implements java.lang.reflect.InvocationHandler {

    private Object obj;

    public static Object newInstance(Object obj) {
        return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                .getClass().getInterfaces(), new AuditProxy(obj));
    }

    private AuditProxy(Object obj) {
        this.obj = obj;
    }

    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
        Object result;
        try {
            logger.info("before method " + m.getName());
            long start = System.nanoTime();
            result = m.invoke(obj, args);
            long end = System.nanoTime();
            logger.info(String.format("%s took %d ns", m.getName(), (end-start)) );
        } catch (InvocationTargetException e) {
            throw e.getTargetException(); 
        } catch (Exception e) {
            throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
        } finally {
            logger.info("after method " + m.getName());
        }
        return result;
    }
}

2. When creating instances of InventoryService, return a proxy which in this case is the AuditProxy, composing instances of InventoryService, which can be better explained using a UML:




This is how it would look in code:
InventoryService inventoryService = (InventoryService)AuditProxy.newInstance(new DefaultInventoryService());

Now, any calls to inventoryService will be via the AuditProxy instance, which would measure the time taken in the method while delegating the actual method call to the InventoryService instance.



So what are proxies used for:
1. Spring AOP uses it extensively - it internally creates a dynamic proxy for different AOP constructs
2. As in this example, for any class decoration - AOP will definitely be a better fit for such a use case though
3. For any frameworks needing to support interface and annotation based features - A real proxied instance need not even exist, a dynamic proxy can recreate the behavior expected of an interface, based on some meta-data provided through annotations.

Thursday, September 8, 2011

Simple Introduction to AOP - Session 5

This will be a wrap up of the AOP intro, with an example that will comprehensively exercise the concepts introduced in the previous sessions.

The use case is simple, I am going to define a custom annotation, PerfLog, I expect the calls to methods annotated with this annotation to be timed and logged.
Let me start by defining the annotation:

package org.bk.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PerfLog {
    
}
Now to annotate some service methods with this annotation:

@Service
public class DefaultInventoryService implements InventoryService{
    
    private static Logger logger = LoggerFactory.getLogger(InventoryService.class);

    
    @Override
    public Inventory create(Inventory inventory) {
        logger.info("Create Inventory called");
        inventory.setId(1L);
        return inventory; 
    }

    @Override
    public List<Inventory> list() {
        return new ArrayList<Inventory>();
    }

    @Override
    @PerfLog
    public Inventory update(Inventory inventory) {
        return inventory;
    }

    @Override
    public boolean delete(Long id) {
        logger.info("Delete Inventory called");
        return true;
    }

    @Override
    @PerfLog
    public Inventory findByVin(String vin) {
        logger.info("find by vin called");
        return new Inventory("testmake", "testmodel","testtrim","testvin" );
    }

    @Override
    @PerfLog
    public Inventory compositeUpdateService(String vin, String newMake) {
        logger.info("composite Update Service called");
        Inventory inventory = findByVin(vin);
        inventory.setMake(newMake);
        update(inventory);
        return inventory;
    }
}

Here three methods of DefaultInventoryService have been annotated with @PerfLog annotation - update, findByVin, compositeUpdateService which internally invokes the methods findByVin and update.

Now for the Aspect which will intercept all calls to methods annotated with @PerfLog and log the time taken for the method call:

package org.bk.inventory.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
public class AuditAspect {

    private static Logger logger = LoggerFactory.getLogger(AuditAspect.class);

    @Pointcut("execution(@org.bk.annotations.PerfLog * *.*(..))")
    public void performanceTargets(){}
   

    @Around("performanceTargets()")
    public Object logPerformanceStats(ProceedingJoinPoint joinpoint) {
        try {
            long start = System.nanoTime();
            Object result = joinpoint.proceed();
            long end = System.nanoTime();
            logger.info(String.format("%s took %d ns", joinpoint.getSignature(), (end - start)));
            return result;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}

Here the pointcut expression -
@Pointcut("execution(@org.bk.annotations.PerfLog * *.*(..))")
selects all methods annotated with @PerfLog annotation, and the aspect method logPerformanceStats logs the time taken by the method calls.

To test this:
package org.bk.inventory;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.bk.inventory.service.InventoryService;
import org.bk.inventory.types.Inventory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/testApplicationContextAOP.xml")
public class AuditAspectTest {

    @Autowired 
    InventoryService inventoryService;
        
    @Test
    public void testInventoryService() {
        Inventory inventory = this.inventoryService.create(new Inventory("testmake", "testmodel","testtrim","testvin" ));
        assertThat(inventory.getId(), is(1L));
        
        assertThat(this.inventoryService.delete(1L), is(true));
        assertThat(this.inventoryService.compositeUpdateService("vin","newmake").getMake(),is("newmake"));
    }

}

When this test is invoked the output is the following:
2011-09-08 20:54:03,521 org.bk.inventory.service.InventoryService - Create Inventory called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - Delete Inventory called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - composite Update Service called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - find by vin called
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.findByVin(String) took 64893 ns
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.update(Inventory) took 1833 ns
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.compositeUpdateService(String, String) took 1371171 ns

the advice is correctly invoked for findByVin, update and compositeUpdateService.

This sample is available at : git://github.com/bijukunjummen/AOP-Samples.git


Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example

Friday, September 2, 2011

Simple Introduction to AOP - Session 4

Yet another way to define an aspect - this time using native aspectj notation.
package org.bk.inventory.aspect;

import org.bk.inventory.types.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public aspect AuditAspect {
    private static Logger logger = LoggerFactory.getLogger(AuditAspect.class);

    pointcut serviceMethods() : execution(* org.bk.inventory.service.*.*(..));

    pointcut serviceMethodsWithInventoryAsParam(Inventory inventory) : execution(* org.bk.inventory.service.*.*(Inventory)) && args(inventory);

    before() : serviceMethods() {
        logger.info("before method");
    }

    Object around() : serviceMethods() {
        long start = System.nanoTime();
        Object result = proceed();
        long end = System.nanoTime();
        logger.info(String.format("%s took %d ns", thisJoinPointStaticPart.getSignature(),
                (end - start)));
        return result;
    }

    Object around(Inventory inventory) : serviceMethodsWithInventoryAsParam(inventory) {
        Object result = proceed(inventory);
        logger.info(String.format("WITH PARAM: %s", inventory.toString()));
        return result;
    }
    after() : serviceMethods() {
        logger.info("after method");
    }
}


This maps to the previously defined @AspectJ notation

Since this is a DSL specifically for defining Aspects, it is not understood by the java compiler. AspectJ provides a tool(ajc) to compile these native aspectj files and to weave the aspects into the targeted pointcuts. Maven provides a plugin which seamlessly invokes ajc at the point of compilation:

   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.0</version>
    <dependencies>
     <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
     </dependency>
     <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>${aspectj.version}</version>
     </dependency>
    </dependencies>
    <executions>
     <execution>
      <goals>
       <goal>compile</goal>
       <goal>test-compile</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <outxml>true</outxml>
     <aspectLibraries>
      <aspectLibrary>
       <groupId>org.springframework</groupId>
       <artifactId>spring-aspects</artifactId>
      </aspectLibrary>
     </aspectLibraries>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>



Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example

Saturday, August 20, 2011

Simple Introduction to AOP - Session 3

Another way of defining an Aspect is using @AspectJ annotaions - which is natively understood by Spring:
package org.bk.inventory.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
public class AuditAspect {

    private static Logger logger = LoggerFactory.getLogger(AuditAspect.class);

    @Pointcut("execution(* org.bk.inventory.service.*.*(..))")
    public void serviceMethods(){
        //
    }

    
    @Before("serviceMethods()")
    public void beforeMethod() {
        logger.info("before method");
    }

    @Around("serviceMethods()")
    public Object aroundMethod(ProceedingJoinPoint joinpoint) {
        try {
            long start = System.nanoTime();
            Object result = joinpoint.proceed();
            long end = System.nanoTime();
            logger.info(String.format("%s took %d ns", joinpoint.getSignature(), (end - start)));
            return result;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
      
    @After("serviceMethods()")
    public void afterMethod() {
        logger.info("after method");
    }    
}


The @Aspect annotation on the class identifies it as an aspect definition. It starts by defining the pointcuts:
@Pointcut("execution(* org.bk.inventory.service.*.*(..))")
    public void serviceMethods(){}
The above basically identifies all the methods of all types in org.bk.inventory.service package, this pointcut is identified by the name of the method on which the annotation is placed - in this case "serviceMethods". Next, the advice is defined using the @Before(serviceMethods()), @After(serviceMethods()) and @Around(serviceMethods()) annotation and the specifics of what needs to happen is the body of the methods with those annotations. Spring AOP natively understands the @AspectJ annotations, if this Aspect is defined as a bean:
<bean id="auditAspect" class="org.bk.inventory.aspect.AuditAspect" />
Spring would create a dynamic proxy to apply the advice on all the target beans identified as part of the pointcut notation.

Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example

Saturday, August 13, 2011

Simple Introduction to AOP - Session 2

Here, I will show how the cross-cutting concern that was introduced in the previous session, can be implemented using Spring AOP - Spring offers multiple ways of implementing Aspects - XML configuration based, @AspectJ based. In this specific example, I will use XML configuration file based way of defining the aspect

Spring AOP works in the context of a Spring container, so the service implementation that was defined in the previous session needs to be a Spring bean, I am defining it using the @Service annotation:
@Service
public class DefaultInventoryService implements InventoryService{
...
}
Now, I want to record the time taken for each of the method calls of my DefaultInventoryService - I am first going to modularize this as an "advice":
package org.bk.inventory.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AuditAdvice {

    private static Logger logger = LoggerFactory.getLogger(AuditAdvice.class);

    public void beforeMethod() {
        logger.info("before method");
    }

    public void afterMethod() {
        logger.info("after method");
    }

    public Object aroundMethod(ProceedingJoinPoint joinpoint) {
        try {
            long start = System.nanoTime();
            Object result = joinpoint.proceed();
            long end = System.nanoTime();
            logger.info(String.format("%s took %d ns", joinpoint.getSignature(), (end - start)));
            return result;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
        
}

This advice is expected to capture the time taken by the methods in DefaultInventoryService. So now to wire this advice to the DefaultInventoryService spring bean:
 <bean id="auditAspect" class="org.bk.inventory.aspect.AuditAdvice" />

 <aop:config>
  <aop:aspect ref="auditAspect">
   <aop:pointcut id="serviceMethods" expression="execution(* org.bk.inventory.service.*.*(..))" />

   <aop:before pointcut-ref="serviceMethods" method="beforeMethod" />  
   <aop:around pointcut-ref="serviceMethods" method="aroundMethod" />
   <aop:after-returning pointcut-ref="serviceMethods" method="afterMethod" /> 
  </aop:aspect>
 </aop:config>

This works by first defining the "pointcut" - the places(in this example, the service methods) to add the cross cutting concern(capturing the method execution time in this example) to. Here I have defined it using a pointcut expression -
execution(* org.bk.inventory.service.*.*(..))
, which is essentially selecting all methods of all the types in the org.bk.inventory.service package. Once the pointcut is defined, it defines what needs to be done around the pointcut(the advice), using the expression:
<aop:around pointcut-ref="serviceMethods" method="aroundMethod" />
This basically says, that around every method of any service type, execute the aroundMethod of AspectAdvice that was defined earlier. Now, if the service methods are executed, I would see the advice getting invoked during the method execution, the following is a sample output if DefaultInventoryService, createInventory method is called:
org.bk.inventory.service.InventoryService - Create Inventory called
org.bk.inventory.aspect.AuditAdvice - Inventory org.bk.inventory.service.InventoryService.create(Inventory) took 82492 ns
Spring's AOP implementation works by generating a dynamic proxy at runtime for all the target beans, based on the defined pointcut.
Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example

Tuesday, August 9, 2011

A simple introduction to AOP - Session 1

Why use AOP, a simple way to answer this question is to show an implementation of a cross cutting concern without using AOP.

Consider a simple service and it's implementation:
public interface InventoryService {
    public Inventory create(Inventory inventory);
    public List list();
    public Inventory findByVin(String vin);
    public Inventory update(Inventory inventory);
    public boolean delete(Long id);
    public Inventory compositeUpdateService(String vin, String newMake);
}

and its default implementation:
public class DefaultInventoryService implements InventoryService{
    
    @Override
    public Inventory create(Inventory inventory) {
        logger.info("Create Inventory called");
        inventory.setId(1L);
        return inventory; 
    }

    @Override
    public List list() {
        return new ArrayList();
    }

    @Override
    public Inventory update(Inventory inventory) {
        return inventory;
    }

    @Override
    public boolean delete(Long id) {
        logger.info("Delete Inventory called");
        return true;
    }
....

This is just one service. Assume that there are many more services in this project.

So now, if there were a requirement to record the time taken by each of the service methods, the option without AOP would be something along the following lines. Create a decorator for the service:
public class InventoryServiceDecorator implements InventoryService{
    private static Logger logger = LoggerFactory.getLogger(InventoryServiceDecorator.class);
    private InventoryService decorated;

    @Override
    public Inventory create(Inventory inventory) {
        logger.info("before method: create");
        long start = System.nanoTime();
        Inventory inventoryCreated = decorated.create(inventory);
        long end = System.nanoTime();
        logger.info(String.format("%s took %d ns", "create", (end-start)) );
        return inventoryCreated;
    }
This decorator would essentially intercept the call on behalf of the decorated, record the time taken for the method call while delegating the call to the decorated object.

Imagine doing this for all the methods and all the services in the project. This is the scenario that AOP addresses, it provides a way for the cross cutting concerns(Recording time for the service method calls for eg.) to be modularized - to be packaged up separately without polluting the core of the classes.

To end the session, a different way to implement the decorator would be using the dynamic proxy feature of Java:


public class AuditProxy implements java.lang.reflect.InvocationHandler {
    
    private static Logger logger = LoggerFactory.getLogger(AuditProxy.class);
    private Object obj;

    public static Object newInstance(Object obj) {
        return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                .getClass().getInterfaces(), new AuditProxy(obj));
    }

    private AuditProxy(Object obj) {
        this.obj = obj;
    }

    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
        Object result;
        try {
            logger.info("before method " + m.getName());
            long start = System.nanoTime();
            result = m.invoke(obj, args);
            long end = System.nanoTime();
            logger.info(String.format("%s took %d ns", m.getName(), (end-start)) );
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        } catch (Exception e) {
            throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
        } finally {
            logger.info("after method " + m.getName());
        }
        return result;
    }
}

So now, when creating an instance of InventoryService, I would create it through the AuditProxy dynamic proxy:
InventoryService inventoryService = (InventoryService)AuditProxy.newInstance(new DefaultInventoryService());

the overridden invoke method of java.lang.reflect.InvocationHandler would intercept all calls to the InventoryService created in this manner, where the cross cutting concern of auditing the method call time is recorded. This way the cross cutting concern is modularized to one place(AuditProxy), but still needs to be explicitly known by the clients of InventoryService, when instantiating InventoryService.

In the next few sessions, I will demonstrate how this can be more cleanly accomplished using Spring AOP, Spring AOP with @AspectJ, AspectJ, @AspectJ with compile time weaving and finish it off with a comprehensive example.

Links to all sessions on AOP:
AOP Session 1 - Decorator Pattern using Java Dynamic Proxies
AOP Session 2 - Using Spring AOP - xml based configuration
AOP Session 3 - Using Spring AOP - @AspectJ based configuration - with/without compile time weaving
AOP Session 4 - Native AspectJ with compile time weaving
AOP Session 5 - Comprehensive Example