Platinum Partner
java,aop,aspectj,aspect

Inter Aspect Communication

When you want to develop an application like “performance monitor”, you must go with AOP. Here passing values between one aspect (advice in spring) to another is not possible.

 

The following example explains how to pass a value generated in one aspect to another.

Step1: Create a Data Holder using ThreadLocal.

ThreadLocalDataHolder.java

package com.rpm.mahesh.util;

import java.util.HashMap;
import java.util.Map;

/**
* @author Maheshkumar Periyasamy
* @version 1.0 Date: Oct 5, 2010
*/
public abstract class ThreadLocalDataHolder {

private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL_MAP = new ThreadLocal<Map<String, Object>>();

private ThreadLocalDataHolder() {
}

/**
* Bind the given Object to the current thread by key.
*
* @param id the String to use as key
* @param object the Object to expose
* @see #add(java.util.Map)
*/
public static void set(String id, Object object) {
currentThreadData().put(id, object);
}

/**
* Append the given Map<String,Object> to current Thread.
*
* @param map the Map to expose
* @see #set(String, Object)
*/
public static void add(Map<String, Object> map) {
currentThreadData().putAll(map);
}

/**
* Return the Object currently bound to the thread by key.
*
* @param id the String to use as key
* @return the Object currently bound to the thread,
* or <code>null</code> if none bound
*/
public static Object get(String id) {
return currentThreadData().get(id);
}

/**
* Return the Map currently bound to the thread.
*
* @return the Map currently bound to the thread,
* or empty <code>Map</code> if none bound
*/
public static Map<String, Object> getAll() {
return currentThreadData();
}

/**
* Remove the object currently bound to the thread by key.
*
* @param id the String to use as key
*/
public static void remove(String id) {
currentThreadData().remove(id);
}

/**
* Reset the ThreadLocalData for the current thread.
*/
public static void reset() {
THREAD_LOCAL_MAP.remove();
}

private static Map<String, Object> currentThreadData() {
Map<String, Object> currentMap = THREAD_LOCAL_MAP.get();
if(currentMap == null) {
currentMap = new HashMap<String, Object>();
THREAD_LOCAL_MAP.set(currentMap);
}
return currentMap;
}

}

Step2: Add necessary values to ThreadLocalDataHolder in your FirstAspect.

FirstLayer.java

package com.rpm.mahesh.util;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;

/**
* @author Maheshkumar Periyasamy
* @version 1.0 Date: Aug 19, 2010
*/
@Aspect
public abstract class FirstLayer {

public Object performAspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
String transactionId = "build your id here";
ThreadLocalDataHolder.set("TRANSACTION_ID", transactionId);
ThreadLocalDataHolder.set("X", "x");
ThreadLocalDataHolder.set("Y", "y");
Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
ThreadLocalDataHolder.remove("TRANSACTION_ID");
ThreadLocalDataHolder.remove("X");
ThreadLocalDataHolder.remove("Y");
return returnValue;
}
}

Step3: Access the values in your upcoming Aspects as below.

SecondLayer.java

package com.rpm.mahesh.util;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;

/**
* @author Maheshkumar Periyasamy
* @version 1.0 Date: Aug 19, 2010
*/
@Aspect
public abstract class SecondLayer {

public Object performAspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//Access the values from ThreadLocalDataHolder, which are added in previous Aspect
String transactionId = (String) ThreadLocalDataHolder.get("TRANSACTION_ID");
Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
return returnValue;
}
}
{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}