|Message Driven Beans consume messages from predefined JMS Topics or Queues. Applications that may need to utilize several Message Driven Beans to handle various messages are faced with a problem of defining a number of JMS destinations and implementing different MDBs to listen to them. This may cause the Application Server to be cluttered with a variety of JMS resources and MDB deployments that perform potentially similar operations.
A solution to this issue can be the Message Driven Bean Proxy pattern. It should be applied to the situations where multiple message types need to be processed by an application and MDBs consuming them may or may not access shared business logic components to complete their work. MDBs performing highly specialized tasks, processing large amounts of data, or desiring to meet very high performance criteria should be excluded. The solution establishes a single application-wide MDB listening to a JMS Topic or Queue as a proxy for the specific operations that need to be performed in response to the message arrival. In this scenario, a single MDB will be responsible for handling all the messages for an application. The decision what functionality to execute will be based on the message properties assigned to it by the sender.
A factory pattern can be utilized to encapsulate the decision making process. When a message is received by the MDB, a factory mechanism is called to create a specific class that will perform all the necessary message handling. The factory class -- Message Handling Factory -- is responsible for instantiating the correct processing class -- Message Handling Class. Each message type should have a corresponding Message Handling Class that performs necessary operations.
When implementing the MDB Proxy pattern, the client sending a JMS message needs to set message properties with specific data uniquely identifying the message. The Message Handling Factory can decide which Message Handling Class to create based on these properties. Message properties are set and extracted through methods exposed in the JMS Message interface. Each Message Handling Class should contain the logic specific to the particular message type that it is processing. They, however, should not implement any business logic but instead call appropriate methods of business logic components. See Message Driven Bean Strategy pattern for more information. This approach limits the proxy MDB's job to creating a Message Handling Factory, instantiating a new Message Handling Class through it and passing the received message to the class for processing.
This pattern eliminates the need for creating multiple JMS destinations and MDB implementations for an application and establishes a common message handling framework. When a new message type is created, the only thing that needs to be done is develop a new instance of the Message Handling Class and update Message Handling Factory logic. This, however, introduces a need to re-deploy and re-test the proxy Bean but this operation should be more efficient than deploying and testing a new Message Driven Bean. A single JMS destination and MDB per application concept may create performance issues but a good load balancing or clustering technique can remedy the situation.
|1 replies in this thread||Reply|
|Message Driven Bean Proxy|
|Posted By: Gal Binyamini on December 14, 2001 in response to this message.|
|As usual, Leo posts and I argue :)
First of all, I'll make a note about sharable business logic (SBL from here on) which sets the context of my argument.
Suppose I'm developing a bogus bookstore application. I would consider the following to be SBL (the list is not exhaustive):
- update order status
- update inventory status
- find pending orders for a specific item (for items we don't have in the inventory).
Suppose I'm implementing the bogus backend using MDBs. When a message comes in from the inventory saying a new item is available again, I may want to:
1. update the inventory status
2. find all the orders for this item that were pending for it.
3. update as many of them as I can (as now the item is available).
I do not view this chain of operations as SBL. It is the algorithm of a very specific application, my bogus backend application. I see no sense in putting this code in a component. Components should be used to compose applications such as this, not to contain the application in themselves. So in this case, I would put this code in the MDB (perhaps by delegating to a seperate class, but not to a seperate component).
My argument is that the scope of the pattern is ill-defined, and that the pattern fails to address it.
I see two elements in the scope:
- The first, and more heavily discussed element involves the problem of having "too many" topics and MDB deployments. The pattern claims it's own implementation would be more efficient, put less load on the app server, etc. The pattern does this by using JMS as a "flat namespace" and nest it's own namespace inside JMS using message properties. If this approach was so efficient, why wouldn't the JMS provider use it? And how is it that the message handlers created by the factory will be more effiient than MDBs? Why do MDBs strike you as something so heavy and difficuilt to maintain? The message handlers in the pattern are just MDBs stripped of the pooling capabilities. The application server manages pool's the MDBs and uses LRU caching, hit-counting schemes, etc to manage them efficiently. Why do you think you will do a better job?
I think that in fact, no matter how well we implement the caching of these message handlers, we will still end up with a less efficient and scalable application. Here are just a couple of reasons (there are more, but I think these two make the point):
1. The JMS server will handle the routing better than you possibly can. For instance, in a cluster, if you used JMS facilities only nodes that need a specific message would get it. With your implementation, all nodes will recieve all messages, because the JMS server doesn't know anything about who needs what.
2. If just one of your MDBs needs durable subscription, it will have to subscribe durably for the big topic. This means that all messages will be stored up for your MDB, instead of just the important durable ones. It also means that a failure in a single MDB can cause all the system's messages to stack up.
Aside from this, I also doubt even incredibly expirienced programmers could implement the caching as well as the app server (see note below about specific cases). There are also threading issues that an MDB programmer cannot control that may cause additional efficiency problems (I can list specific if anyone is interested).
Reasons such as the ones above are one of the motivations behind the current design of JMS, which provides it's own namespace rather than let you make your own (although it may seem simple enog