Objective
This article talks about a simple design of asynchronous mechanism or framework,
That supports any/many asynchronous business process with a single message driven bean and one JMS destination (queue).
Background
Modern world systems not just works on request/response, there are business scenarios where you need an operation to be invoked/fired and then forgotten. This kind of fire and forgotten way of processing is called as asynchronous as the requestor doesn’t need to wait for a response immediately. To achieve the asynchronous behavior the well known approach is to use messaging system.
Traditional Approach
To achieve the asynchronous behavior using a messaging system, the general approach is to have a queue and a MDB where the asynchronous business processing logic is located. If there is another need in the application for a similar asynchronous processing, we tend to add more queues and MDB’s to achieve the same.
Reasoning Traditional Approach
Why do we need queue or MDB specific to a business process?
Why can’t it be a single generic queue and MDB and pull the business logic out of MDB and invoke them separately based on the configuration. Hope I have set the context for the further discussion.
Design Perspective
This design approach is to have a single queue which can take processing request for any business processes in the application, which needs asynchronous capability. We can have one Message Driven Bean (MDB) to invoke the appropriate business process as per the message header.

Class Diagram
Components of this framework are,
IAsynchronousBean
This is a simple interface having one method named “execute” which takes in Object as a parameter. All Business Logic that needs to be invoked asynchronously should implement this interface to achieve the asynchronous behaviour. This is a partial implementation of command pattern.
package org.asynchronos;
public interface IAsynchronousBean {
public void execute(Object obj);
}
AsynchronousVO
This is a simple Transfer Object which holds the message content or the input to the business logic and the fully qualified class name of the business logic which is an implementation of IAsynchronousBean interface.
package org.asynchronos;
import java.io.Serializable;
public class AsynchronousVO implements Serializable{
private Class asynchronousBeanClass;
private Object object;
public Class getAsynchronousBeanClass() {
return asynchronousBeanClass;
}
public void setAsynchronousBeanClass(Class asynchronousBeanClass) {
this.asynchronousBeanClass = asynchronousBeanClass;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
Note:
· setAsynchronousBeanClass() should be used to set the AynchronousBean Class Name where the actual Business logic is implemented.
· Sender of this message should wrap his entire message object into this TO and set the BusinessLogic that needs to be invoked as said in the previous point.
CommonAsynchronousMDB
This is a well known EJB spec Object, Message Driven Bean (MDB). This component is the core of our design as it acts as a Controller for the framework. Routing or invocation of appropriate Business logic happens inside the onMessage of this MDB based on configuration and message header information.
package org.asynchronos;
public class CommonAsynchronousMDB implements MessageListener,
MessageDrivenBean {
public void onMessage(javax.jms.Message message) {
if (message instanceof ObjectMessage) {
try {
AsynchronousVO asynchronousVO = (AsynchronousVO) message;
Class clazz = asynchronousVO.getAsynchronousBeanClass();
IAsynchronousBean iAsynchronousBean = (IAsynchronousBean) clazz.newInstance();
iAsynchronousBean.execute(asynchronousVO.getObject());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
System.out.println("Unknown Message format.....");
}
}
}
Note: In the MDB’S onMessage() actual intent of the request is found from the message header and the logic that needs to be invoked (using reflection).
Implementation Perspective
1. Sender should always send Object message containing AsynchronousVO Object which has the class reference of business that needs to be invoked, and the input to the business logic.
2. Create Class that implements IAsynchronousBean and implement the business logic that need to be executed asynchronously in the “execute” method.
3. CommonAsynchronousMDB receives the call with the AsynchronousVO as the part of Message header. This message is unwrapped and the appropriate business logic class is invoked (the execute method of the business class is called).
Conclusion
1. Reduces over head of having and marinating too many queues.
2. Reduces the number of MDB’s and maintainability.
3. This design provides better modularity as the actual logic is moved to a simple POJO class.
4. Simple design.
5. Easy to extend for more business process.
Download the source
2 comments:
Really good thinking.
Say if the framework said above is heavily used by more than one module or one projects, single Q will serve multiple applications or modules. Say I want to prioritize the messages,how can I do that.
As proposed Business logic can be moved out and we can make that in a plain java class. But serving multiple applications in a single Q, We need to do some enhancements there.
From the above architecture ,I see like
Many to Many is converted into One to One ( means that many Qs --> mdbs now it is one Q --> mdb for number of applications)
Can we do like one to many approach? There should be many Qs in runtime based on the parameter or Q name we should decide where to pick the message. Anyway framework is going to load the user's implementation class.So Business logic will be there I believe.
I implemented a similar solution. I preferred to implement a service capable to receive Asynch requests, enqueueing them, plus an MDB to manage service invocation, coded in two different EAR, so I can switch off them individually.
In my solution, the MDB integrates Spring to search for the service to invoke. By this way, it is capable to invoke any type of service provider (POJOs, WS, EJBs...)
Post a Comment