Article: Workflow Orchestration Using Spring AOP and AspectJ
This article provides a practical example of light-weight workflow orchestration using Spring AOP and AspectJ.
AOP has long been a science of discovering and modularizing cross-cutting concerns which are generally realized in the area of non-functional requirements such as error handling, logging, security, transaction. However, AOP is also an architectural paradigm which allows a radically different approach to addressing functional requirements. Using AOP, functional processes can be broken down into a set of individual activities which, in many cases, are shared across other processes. These activities are realized as a set of independent, stateless POJO's implemented as AOP advisors / interceptors. Each process instance, represented by a stateful token, passes through a dynamic chain of AOP interceptors and is advised by each one. Functional processes are then quickly and easily assembled from such modules using standard AOP configuration.
Some of the key benefits of this architectural approach include:
- Improved understanding of functional requirements
- Full process visibility and externalized control
- Much looser coupling between individual components which allows for quick substitution when requirements change and promotes reusability
- Improved testing, since each module has a well defined input/output contract and could be developed and tested individually
- Simple, scalable performance allowed by no central point of control (i.e., BPM engine)
Re: Small change
One thing to remember is that this example was greatly simplified and generalized from the actual implementation that was delivered, but here are couple of points to keep in mind.
Although at first it might seem like each Activity delivers a single fact, in reality that is not true. Each fact is nothing more then a signal of some accomplishment therefore if you have a complex activity there could me more them a single fact registered per such Activity. However, if you decide that a particular Activity is transactional and must output all the facts or none, then you should implemented as such, but by default I am not implying transactional characteristics on fact registry, which means that a failed Activity could still register few facts based on things it managed to accomplish.
Re: Branching, etc
Having said that, I do have to acknowledge that this sample and this article is greatly simplified from what I am currently working on along the lines of Workflow Orchestration and BPM, where branching/forking, asynchronous processes, event handling and cloud-deployable tasks are all part of the implementation.
Re: Tool Support
That's a good question and I'll be honest, I haven't given it much thought yet. For now it's more about experimenting/prototyping with several different implementations at the conceptual level without set scope or constraint.
However, BPMN (in my view) is notation mechanism to document and understand "business processes" while formalizing them around basic elements such as Events, Activities, Gateways, Connections etc. . . It also recognizes and formalizes various process modeling patterns such as Basic Control, Branching and Synchronization, Iteration etc. . . However, BPMN doesn't mandate an implementation model (although one might argue this from BPEL perspective). In any event, I am currently more curious in trying to experiment with different (lighter-weight) approaches of implementing such concepts and patterns outside of current execution models implemented around BPEL. So, although I don't see any conflict in how Business process is documented (BPMN or Flow Chart), I am drawing a clear separation between Process Modeling and Process Execution.
Re: Tool Support
I am somewhat confused as to whether AOP is really adding any advantage to a simple bean doing the same.
<bean id="workflowExecutor" class="com..WorkflowExecutor">
I am not advantage of AOP but in this particular case, is it really needed to facilitate the activities?
Re: Tool Support
As far as AOP adding any advantage is rater objective and is up to the community to decide.
Having said that. . .
In your example WorkflowExecutor must maintain the code to build the list (although Spring's property editor will take care of it) of activities, then it has to iterate through it and invoke each activity etc. . . In other words you are defining the execution model, which in AOP you don't have to since AOP already defines the execution model to trigger invocation of every interceptor in the order they were defined. Second, in your example, bean1,2,3 seem to be invoked without any rule, unless the rules are programmatically maintained by WorkflowExecutor. Applying second layer of AOP allows you to introduce control and transition governance model separate from the execution model. It also allows you to introduce transition changes without changing individual activities.
AOP in this particular example is just an enabler to address two concerns:
1. Execution and direction of the activities
2. Activity transition which is based on the facts
Concurrency and parallelism comes from the actual implementation of the Activity and Transitioning interceptor(s)
Let's assume the process made of 3 activities A, B and C. Following the formula described in the article let's say it looks like this:
ProcessContext = A(d-1, 2; p-3) -> B (d-1, 3; p-4, 5) -> C(d-4, 5);
Let's say Activity B is implemented as asynchronous activity which means that B and C will be invoked "almost" concurrently. However C depends on the facts that must be registered by activity B, which most likely will not be present in the fact registry when C is invoked so it will be skipped. Activity B, however based on its implementation could easily, upon completion and fact registration, resubmit the actual process, thus allowing activity C to complete. You could also implement the wait with timeout inside of transitioning interceptor allowing activity C to wait for required facts. Don't forget, activities could register more then one fact throughout its execution which means that while activity B is still executing it might register enough facts to allow activity C to begin its execution before B is actually finished.
As for multiple VMs, activities do not have to be bound to the single JVM and could reside in the distributed environment, as long as they are reachable by some remoting mechanism(i.e., RMI or going all the way to utilize technologies such as Terracota, GridGain etc. . .)
Nevertheless, I completely agree with your solution.
Ah! Execution Model is handled by AOP in your example. My question was more around the benefit provided by AOP for this particular use case - "light-weight" workflow orchestration solution.
1. Execution (functional)
2. Transition/orchestration (non-functional)
Read the previous post for more details.
What about debugging?
I want to re-design the project to a single process model based on Spring. This article is really great and gave me a lot of ideas, but:
1. What about debugging? Is Aspectj debuggable with load time weaving?
2. I am not experienced in AOP (know the principles), so all the configuration is a bit hard to catch. I need an *easy* way to design new processes with exisiting Activities. This example does not look like easy and I think I would rather prefer Suresh's version of defining a process, since it's more intuitive and easier to grasp (although from the SW architectural point of view I understand the good ideas behind the Oleg's article).