Search code examples
javaspringaspectjflowable

How to pass variables as parameters to an Aspect


@Component("taskCreateListener")
public class TaskCreateListener implements FlowableEventListener { 

@LogMethod
    @DetermineCaseTypeOfWork
    @Override
    public void onEvent(FlowableEvent event) {

///Do stuff that results in variables I want to pass to aspect
//For example, get ids and details and set to variables that I want to pass to insertThing() method once onEvent(FlowableEvent event) is finished executing
//ex:
//String procInstId = "abc1234";
//String type = "case1";
}

I need the onEvent to fully complete and then get local variables set in onEvent(FlowableEvent event) passed into my aspect insertThing() method:

@Aspect
@Component
public class DetermineCaseTypeOfWork {

@Transactional
@After(@annotation(path goes here))
public void insertThing() {
    //Do something here with the variables passed in from doSomething method
//if(procInstId.equals("abc1234") && type.equals("case1")) {
//do something
} else if(//other id and type) {
//do something else
} else {
//do something else
}
}

I can't modify the onEvent(FlowableEvent event) method to return something and the onEvent(FlowableEvent event) method has to fully complete first, so how would I go about passing parameters into insertThing()?


Solution

  • According your question, there is no possibility to change signature of the onEvent() method, which should be handled by an aspect. You could try to create a ThreadLocal based container class which is initialized in aspect before calling onEvent() and assessed after finishing onEvent(). But that approach requires you to be able to edit onEvent() code (but do not requires change its returning type). Here are some details:

    public class VariableContextHolder {
    
    /**
     * ThreadLocal with map storing variables
     */
    private final ThreadLocal<Map<String, Object>> threadlocal = new ThreadLocal<>();
    
    private static VariableContextHolder instance;
    
    private VariableContextHolder () {
    
    }
    
    public final static VariableContextHolder getInstance() {
        if (instance == null) {
            instance = new VariableContextHolder ();
        }
        return instance;
    }
    
    public Map<String, Object>get() {
        return threadlocal.get();
    }
    
    public void set(Map<String, Object>map) {
        threadlocal.set(map);
    }
    
    public void clear() {
        threadlocal.remove();
    }
    }
    

    Aspect class:

    @Aspect()
    public class DetermineCaseTypeOfWork {
    
    @Transactional
    @Around(@annotation("path goes here"))
    public void insertThing(ProceedingJoinPoint joinPoint) throws Throwable {
    
    // save initialized map to threadlocal    
    VariableContextHolder.getInstance().set(new HashMap<>());
    
    // method onEvent() will be called
    joinPoint.proceed();
    
    // retrieve map from threadlocal
    Map<String, Object> variablesMap = VariableContextHolder.getInstance().get();
    
    // get variables by names and handle them
    String procInstId = variablesMap.get("procInstId");
    
    // clear threadlocal after using it
    VariableContextHolder.getInstance().clear();
    }
    
    }
    

    Changes needed to be done in onEvent() method:

    public void onEvent(FlowableEvent event) {
    
        // retrieve map from threadlocal
        Map<String, Object> variablesMap = VariableContextHolder.getInstance().get();
        String procInstId = "abc1234";
        String type = "case1";
        // save variables to map
        variablesMap.put("procInstId", procInstId);
        variablesMap.put("type", type);
    }