Friday, August 17, 2007

JMS design and analysis

(1) Design Pattern: Publish Subscription

1 Producer -----(1 Message) ---> Topic (Destination) ----> K Consumers
K Producers ----(K Messages) ---> Topic (Destination) ---> K Consumers

(2) Service Reliability: Message Reliability:

With normal topic subscription, only active consumers subscribed
to the topic will receive messages.

With durable subscriptions, the inactive consumers are ensured
to receive the message as subsequently becomes active.

Intuitively, the topic does not hold the messages it receives
unless it has inactive consumers with durable subscriptions.

Hence, durable subscription is the service reliability practice

(3) Best Practice-1: Development with Unified Domain Model

Even though the domain-specific interfaces (Queue, Topic)
are backward supported for legacy purposes, The best development
practice is to use the Unified Domain Interface,
which transparently support P-P, Pub-Sub Models.


(4) Best Practice-2: Use Administered Object Store

The connection factory is recommended to create and reconfigured
with the administration tools. Admin objects such as ConnectionFactory
is then placed in an Administered Object Store. It decouples JMS application
code and portable among different JMS providers.



(5) Best Practice-3: J2EE Client By Resource Annotation

Use @Resource and no exception handing in J2EE 1.5 as best
practices.

(5) Code Segment: to show message life cycle

Use Unified Domain createConnection method is in javax.jms.ConnectionFactory

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:///amberroad:/sun_mq_admin_objects");
Context ctx = new InitialContext(env);
String CF_LOOKUP_NAME = "ARConnectionFactory";
ConnectionFactory arFactory = (ConnectionFactory) ctx.lookup
(CF_LOOKUP_NAME);
String DEST_LOOKUP_NAME = "ARTopic";
Destination arTopic = (Destination) ctx.lookup(DEST_LOOKUP_NAME);



Connection arConnection = null;
Session arsession = null;
try {
arConnection = myFactory.createConnection("amberroad", "amberroad");
arConnection.setExceptionListener(this);
arsession = arConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer arProducer = arSession.createProducer(arTopic);
String arSelector = "/* Text of selector here */";
MessageConsumer
arConsumer = arSession.createDurableSubscriber(arTopic, "arConsumer", arSelector, true);
TextMessage arMsg = mySession.createTextMessage();
arMsg.setText("AmberRoad Test");
// at message level specification
arMsg.setJMSReplyTo(replyDest);
arMsg.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
arMsg.setDisableMessageTimestamp(9L);
arMsg.setJMSPriority(Message.DEFAULT_PRIORITY);
arMsg.setJMSExpiration(1000L);
arProducer.send(arTopic, arMsg);

// if it is not at message level, at producer level specification

arProducer.send(arDest, arMsg, DeliveryMode.PERSISTENT, 9, 1000);


// if set up async listener

ARMessageListener arListener = new ARMessageListener();
arConsumer.setMessageListener(arListener);


// blocking receiver
arConnection.start();
Message inMsg = arConsumer.receiveNoWait(); // distributed apps

outMsg.clearBody();// consumer does
--------------------

arConnection.stop(); // in case to suspend messaging

finally{

mySession.unsubscribe("arConsumer");
arConnection.close();

}

Note


(1) for the publish/subscribe domain to create durable topic subscriptions,
a client identifier arrangement is done by configuring the client runtime
to provide a unique client identifier automatically for each JMS application.

(2) For message consumption, with auto-acknowledge mode, the Message Queue
client runtime immediately sends a client acknowledgment for each message
it delivers to the message consumer; it then blocks waiting for a return
broker acknowledgment confirming that the broker has received the client
acknowledgment. It leaves JMS application code free.


(3) For message producers, the broker’s acknowledgment behavior
depends on the message’s delivery mode defined in Message Header.
The broker acknowledges the receipt of persistent messages for persistent messages
but not of non persistent ones; It is not configurable by the client.




For Receiving Messages Asynchronously



public class ARMessageListener implements MessageListener
{
public void onMessage (Message inMsg) throws JMSException
{
Destination replyDest = inMsg.getJMSReplyTo();
long timeStamp = inMsg.getLongProperty("JMSXRcvTimestamp");
Enumeration propNames = inMsg.getPropertyNames();
String eachName;
Object eachValue;

while ( propNames.hasMoreElements() )
{
eachName = propNames.nextElement();
eachValue = inMsg.getObjectProperty(eachName);

}
String textBody = inMsg.getText();

}
}

No comments: