The one problem that needs to be solved when exposing a JMS destination as a web service is reliability. How do we make sure that the web service client has successfully received the message. In other words how do we support distributed transaction. The following example demonstrates this.
Target is to expose a JMS topic called yahoonews as web service.
Step1. Create a durable subscriber with CLIENT acknowledge mode
public Class DurableSubscriber{
Context jndiContext = null;
TopicConnectionFactory topicConnectionFactory = null;
TopicConnection topicConnection = null;
TopicSession topicSession = null;
BasicTopic topic = null;
TopicSubscriber topicSubscriber = null;
public DurableSubscriber(){
try {
topicConnectionFactory = new com.sun.messaging.TopicConnectionFactory();
topicConnectionFactory.setProperty("imqBrokerHostName",brokerHost);
topicConnectionFactory.setProperty("imqBrokerHostPort",brokerPort);
topicConnection = (com.sun.messaging.jms.TopicConnection)
topicConnectionFactory.createTopicConnection();
topicConnection.setClientID("yahoouserid1001");
topicSession =
topicConnection.createTopicSession(false,
Session.CLIENT_ACKNOWLEDGE);
topic = (com.sun.messaging.BasicTopic)topicSession.createTopic("yahoonews");
} catch (Exception e) {
e.printStackTrace();
if (topicConnection != null) {
try {
topicConnection.close();
} catch (javax.jms.JMSException ee) {}
}
}
}// end constructor
public void startSubscriber(){
try {
topicConnection.stop();
topicSubscriber =
topicSession.createDurableSubscriber(topic,
"finanancialnewsSubscriber");
topicConnection.start();
} catch (javax.jms.JMSException e) {
System.err.println("Exception occurred: " +
e.toString());
}
}
public javax.jms.Message getMessage(int timeout) throws Exception{
javax.jms.Message m = topicSubscriber.receive(timeout);
return m;
}
}
Step2. Create a wrapper class that will exposed as web service using REST or SOAP.
The web service should have two functions getMessage and ackMessage.
The class should also store the message that needs to be acknowledged.
public class JMSWebService{
private static DurableSubscriber ds = new DurableSubscriber();
static{
ds.startSubscriber();
}
private javax.jms.Message ackMessage;
public String getMessage(){
if (ackMessage==null)
ackMessage = ds.getMessage(1000); // 1 sec blocking call to get messages
String str = ackMessage.getText();
return str;
}
public void ackMessage(){
if (ackMessage!=null)
ackMessage.acknowledge();
ackMessage = null;
}
}
In this example reliability is achieved by having the ackMessage service along with getMessage, the client has to call the ackMessage function to indicate that all is well at the client side and that the client has commited the transaction at his end. If the ackMessage call is never made and the client keeps calling the getMessage function the transaction will not be commited and so the same message is returned to the client.
No comments:
Post a Comment