Thursday, March 19, 2009

Messaging With GWT (AJAX)

"Writing web apps today is a tedious and error-prone process. Developers can spend 90% of their time working around browser quirks. In addition, building, reusing, and maintaining large JavaScript code bases and AJAX components can be difficult and fragile. Google Web Toolkit (GWT) eases this burden by allowing developers to quickly build and maintain complex yet highly performant JavaScript front-end applications in the Java programming language." --Quoted from "http://code.google.com/webtoolkit/".

Since version 6.x, Netbeans included plug-ins for GWT/AJAX web application development. This makes writing GWT/AJAX applications a pleasant experience. With just a few clicks, the required GWT/AJAX web application skeleton files are automatically created. A complete war file is also generated when the (GWT/AJAX) web application is successfully built. The Netbeans/GWT tutorial to create a GWT web application is fairly simple to follow:

http://www.netbeans.org/kb/60/web/quickstart-webapps-gwt.html

The GWT quick start guide is at the link here:

http://code.google.com/webtoolkit/

This article provides a simple (GWT/AJAX) code example to send/receive text messages from a browser. A JMS TextMessage sent to a specific (JMS) destination can be received by the AJAX script running in the browser. The example can be modified to receive GWT supported serializable objects. The example looks like (Figure 1) after launched. The text entered in the lower text area is sent to a queue ("myqueue") when the Send button is clicked. The text is then (concurrently) received from the same queue and displayed in the upper text area.










(Figure 1)

The example assumes that you know about 2% of GWT and 0.1% of AJAX. The 2% means you know how to create and write a Hello-World GWT application and how "GWT RPC" works. No AJAX knowledge is required. You do need to know Java and JMS.

The code example is created with Netbeans IDE 6.5 with GWT plug-ins. The example is divided into the following components. AJAX and HTML files generated from GWT compiler and Netbeans IDE are not included here.
  • Creating services (interfaces)
  • Implementing services (interfaces)
  • Making the service calls
1. Creating services.

The interface defined in GWTService allows AJAX clients to send/receive messages on the specified destination name.

GWTService.java

package com.em.gwt.client;
import com.google.gwt.user.client.rpc.RemoteService;

//RPC interface for client to send/receive messages from destination name "destName".

public interface GWTService extends RemoteService {

public String receive (String queueName) throws IllegalStateException;

public void send (String queueName, String msg);
}

GWTServiceAsync.java

package com.em.gwt.client;
import com.google.gwt.user.client.rpc.AsyncCallback;

public interface GWTServiceAsync {

public void receive (String queueName, AsyncCallback callback);
public abstract void send(String queueName, String msg, AsyncCallback asyncCallback);
}


2. Implementing services (interfaces).

The service is implemented with Open Message Queue. So you need to include imq.jar, jms.jar in the IDE project library.

GWTServiceImpl.java

/*
* GWTServiceImpl.java
*
* Created on March 17, 2009, 2:02 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package com.em.gwt.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.em.gwt.client.GWTService;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.ServletException;

/**
*
* An example GWT service implementation to receive messages from
* specified JMS destinations.
*/
public class GWTServiceImpl extends RemoteServiceServlet implements
GWTService {

private ConnectionFactory factory = null;
private Connection connection = null;

/**
* This is an example implementation. No connection pooling.
*/
@Override
public void init() throws ServletException {

try {
//get conn facory
factory = new com.sun.messaging.ConnectionFactory();

//create jms connection
connection = factory.createConnection();
//start the connection
connection.start();

log ("Connection started.");
} catch (Exception e) {
log (e.getMessage(), e);
throw new ServletException (e);
}

}

/**
* Receive a message from the specified queue destination name.
*
* The performance can be improved if the session/consumer
* are cached.
*
* @param qname the queue name.
* @return The body of the text message.
*
* @throws java.lang.IllegalStateException if any internal error occurred.
*/
public String receive (String qname) throws IllegalStateException {

String msg = null;
Session session = null;

try {
//create a session
session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//get the queue reference
Queue queue = session.createQueue(qname);
//create a consumer
MessageConsumer consumer = session.createConsumer(queue);

//receive with 10 seconds timeout
Message m = consumer.receive(10000);

//get the body of the message
if (m != null && m instanceof TextMessage) {
msg = ((TextMessage)m).getText();
}

} catch (Exception e) {
msg = e.getMessage();
throw new IllegalStateException (e);
} finally {
close(session);
}

return msg;
}

public void send (String qname, String msg) {

Session session = null;

try {
//create a session
session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//get the queue reference
Queue queue = session.createQueue(qname);
//create a consumer
MessageProducer producer = session.createProducer(queue);

TextMessage tm = session.createTextMessage();
tm.setText(msg);

producer.send(tm);

} catch (Exception e) {
throw new IllegalStateException (e);
} finally {
close(session);
}

return;
}

/**
* close the specified session.
* @param s the session to be closed.
*/
private void close (Session s) {
try {
s.close();
} catch (Exception e) {
log (e.getMessage(), e);
//throw new IllegalStateException (e);
}
}

/**
* close connection when servlet is destroyed.
*/
@Override
public void destroy() {

try {
this.connection.close();
} catch (Exception e) {
log (e.getMessage(), e);
}
}
}


3. Making service calls.

The entry point of the GWT client application. Each message received is updated in the TextArea.

maasEntryPoint.java

package com.em.gwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import java.util.Date;

public class maasEntryPoint implements EntryPoint {

private VerticalPanel vp = new VerticalPanel();

private TextArea recvTextArea = new TextArea();

private TextArea sendTextArea = new TextArea();

private Button btnSend = new Button("Send");

private Label recvLabel = new Label ("message received:");

private Label sendLabel = new Label ("message sent:");

private AsyncCallbackRecvImpl recvCallBack = new AsyncCallbackRecvImpl();
private AsyncCallbackSendImpl sendCallBack = new AsyncCallbackSendImpl();

private GWTServiceAsync service = null;

private static final String MYQUEUE = "myqueue";

/** Creates a new instance of maasEntryPoint */
public maasEntryPoint() {
}

/**
* The entry point method, called automatically by loading a module
* that declares an implementing class as an entry-point
*/
public void onModuleLoad() {

vp.add(recvLabel);

recvTextArea.setCharacterWidth(70);

vp.add(recvTextArea);

vp.add(sendTextArea);

btnSend.addClickListener(new SendBtnListener());

vp.add(btnSend);

vp.add(sendLabel);

RootPanel.get().add (vp);

service = getService();

receive();
}

private void receive() {
service.receive(MYQUEUE, recvCallBack);
}

public static GWTServiceAsync getService(){
// Create the client proxy. Note that although you are creating the
// service interface proper, you cast the result to the asynchronous
// version of
// the interface. The cast is always safe because the generated proxy
// implements the asynchronous interface automatically.
GWTServiceAsync service = (GWTServiceAsync) GWT.create(GWTService.class);
// Specify the URL at which our service implementation is running.
// Note that the target URL must reside on the same domain and port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "gwtservice";
endpoint.setServiceEntryPoint(moduleRelativeURL);
return service;
}

class AsyncCallbackRecvImpl implements AsyncCallback {

public void onFailure(Throwable caught) {
recvTextArea.setText("receive failed: " + caught.getMessage());

caught.printStackTrace();
}

public void onSuccess(Object result) {

if (result != null) {
recvTextArea.setText("Received msg = " + (String)result);
}

receive();
}

}

class AsyncCallbackSendImpl implements AsyncCallback {

public void onFailure(Throwable caught) {

sendLabel.setText(new Date() + ": send failed.");

caught.printStackTrace();
}

public void onSuccess(Object result) {

sendLabel.setText(new Date() + ", sent message = " + sendTextArea.getText());

}

}

class SendBtnListener implements ClickListener {

public void onClick(Widget sender) {
String msg = sendTextArea.getText();
if (msg == null || msg.isEmpty()) {
Window.alert("No message entered in send text area.");
} else {
service.send(MYQUEUE, msg, sendCallBack);
}
}

}

}

Wednesday, March 11, 2009

Messaging, a brief review

There are various semantics when the term messaging is used. Such as e-mail, which is primarily used for communication between people, is also referred to as messaging.

The term messaging discussed in this blog space is scoped as follows.

The scope.


Messaging is a communication model. It is usually made possible by a messaging system. A messaging system is commonly referred to as a message oriented middleware (MOM).

A messaging system provides API, messaging agents, and routing services to facilitate software components to create, send, receive, and read messages.

A major characteristic of messaging is to communicate asynchronously. This is in contrast to RPC or RMI style communications.

Software components that communicate with messaging style are usually distributed and loosely coupled. The communication parties (producers and consumers) are not required to be active (running) simultaneously. They are not required to know each other's existence or implementation. And they are not required to use the same communication protocol to send and receive messages.

Messaging can be categorized into two domains. Point-To-Point messaging domain and Publish-and-Subscribe messaging domain.

A destination within the Publish-and-Subscribe messaging domain is called a topic. A destination within the Point-To-Point domain is called a queue.

A topic is a destination from which all the attached subscribers will receive a copy for each message published to it.

A queue is a destination from which only one consumer will receive each message sent to it.

With messaging, software components communicate with each other through a destination. The communication parties only require to know the destination and the format of the message to communicate effectively.


Java Message Service (JMS)

In 1998, Sun and a majority of messaging vendors defined a set of Java API and message routing behavior for the above messaging scope. The JMS messaging service is commonly used by the corporate IT systems.

The JMS messaging service is also commonly used as the back-bone routing service for the Service-Oriented Architecture (SOA) implementation.

Almost all major messaging providers today support and implement the JMS specification.

For JMS, the communication protocols between messaging clients and a messaging provider are vendor dependent. JMS does not define protocols between JMS clients and a messaging provider. The JMS communication protocols are transparent to the applications but are not compatible among messaging providers.


The transition


As the programming environment has moved to the Internet, the messaging model is also evolving. The boundaries between enterprise messaging and the web are often required to be crossed.

Since 1999, there are specifications been developed to address and attempt to resolve messaging issues across the web and corporate boundaries. Such as ebxml messaging service (ebMS), WS-Reliability, and WS-ReliableMessaging . Each of the specification was based on SOAP and defined sophisticated rules for the messaging behavior, reliability, and security requirements.

But the level of complexity and compatibility issues were among the challenges for the mass adoption for these specifications and implementations.

With Software as a Service (SaaS) becomes a reality, the concept of Messaging as a Service (MaaS) is also a part of the transition.

The JMS messaging service are naturally adopted and served as the back-bone routing service for the implementation of a MaaS due to its solid foundation and widely availability.

As of today, the RESTful architectural style has become a popular design choice for the new generation of web services. It is thus a natural transition to present MaaS in a RESTful way. This makes it much simpler to participate in messaging for a web capable software component.

In the mean time, the cloud computing is also gaining its momentum. The combination of MaaS and cloud seems to be a good fit. The messaging in the cloud development is on-going. The pay-per-use messaging concept is becoming an alternative option to corporate IT and start-ups.

Wednesday, March 4, 2009

Stateless

The term "stateless" has been discussed a lot lately. It is about the stateless constraint imposed on the REST architectural style. In the famous dissertation of Fielding, section 5 (Representation Style Transfer), the stateless constraint stated as follows.

"communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client."
(http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)

And the benefits of statelessness "induces the properties of visibility, reliability, and scalability".

The benefits are not difficult to understand. But some consequences are also derived from the nature of statelessness.

One of the consequences of the stateless behavior is the "transient" server resource availability, such as a transaction. How can this stateless design be implemented such that it can fulfill the "web scalable" requirement? As some said, "just add another server and the system is automatically scaled".

For example, if a RESTful application client is in the middle of a transaction on server (A). But the next request was "load balanced" by a less-intelligent load-balancer to a different server (B). To achieve the claimed (stateless) benefit, the transaction processing must proceed as if the request were on the original server (A).

The previous article "Meet The Web, Part 2 (with transaction)" is a typical RESTful transaction scenario to face this challenge.

There are solutions to address the stateless implementation issues.

For example, the following are some possible solutions to handle the stateless nature for a "transient" resource (such as a transaction).
  1. Client includes accumulative information (including previous requests related to the transaction) in the request message.
  2. Mirror a resource state (such as a transaction) in all servers.
  3. Introduce a new (shared) service layer to handle the resource. Such as a transaction service, on a separate machine, to handle transactions. When a transactional request is received, the request is forwarded to the transaction service layer.
  4. Use an intelligent load-balancer.
There are other solutions not mentioned. So the issue is not due to "lack of solution" to implement a stateless behavior. The challenge is that, if attempts to change the existing system to fulfill the constraint, it takes efforts to redesign and rearrange the "guts" in the current design and implementation. And it also takes time to get adjusted to the new design style.

To provide a stateless solution for the case in "Meet The Web, Part 2 (with transaction)", the solution #4 above would probably be a logical choice. All transactional service requests are delegated to the shared transaction service layer. This would meet the stateless constraint challenge for the transient server resource availability. But changes would be required to rearrange the server/service implementation and move some portion of implementation to a separate location (transaction service layer).

When software development model moved from component (such as beans) to service (such as web services), the thinking and design patterns are also evolving. The concept of "software as a service" (SaaS) seems to fit into the RESTful architectural style nicely. And statelessness may likely become a popular "design pattern" for the coming generation of web services.

There are disadvantages about the stateless design as Fielding pointed out below. Especially the performance impact may not be easy to address. But that's the fun part for the fine engineers to resolve.

"Like most architectural choices, the stateless constraint reflects a design trade-off. The disadvantage is that it may decrease network performance by increasing the repetitive data (per-interaction overhead) sent in a series of requests, since that data cannot be left on the server in a shared context. In addition, placing the application state on the client-side reduces the server's control over consistent application behavior, since the application becomes dependent on the correct implementation of semantics across multiple client versions."

Monday, March 2, 2009

XML

Its an old topic. But watch out, it is just the beginning ...

1. The Got Milk Commercial


Imagine a Got Milk Commercial as follows.

"A grandma walking slowly in a super market with a shopping cart. Suddenly her cell phone rings. She pulls up the cell phone out of her pocket and flips the phone. The camera rooms in on the cell phone screen. It shows the message 'Got Milk?' with signature from the refrigerator."

It is a got milk commercial. But it also shows that we have entered the era of mass messaging. Every device with a network pulse can and wanted to communicate with each other effectively. The grandma's cell phone detected itself is in the super market, so it sends a message (through some messaging service) back home to the refrigerator. A few seconds later, the refrigerator sends back a message with the "Got Milk?" message.

What does the above has anything to do with XML? And why does the weird looking data format so attractive to almost every industry to store, present, and exchange information with it?

In short, it is due to the claimed (and accepted) advantage -- simple, open, extensible, and interoperable.

The message format in exchange for the Got Milk Commercial above is likely to be in the XML format.

So it would be politically incorrect to not stress the importance of considering XML as the packaging mechanism in the web messaging environment. Such as when exchanging messages in "Messaging in the Cloud" environment, the message itself would be more "open" if each message is packaged in the XML format.

"XML provides a basic syntax that can be used to share information between different kinds of computers, different applications, and different organizations without needing to pass through many layers of conversion."
-- wikipedia (http://en.wikipedia.org/wiki/XML).

XML has been widely used for the web. Such as HTML pages, RSS , and the Atom Syndication Format, etc.

For messaging in web environment, restful or not, XML should be evaluated and considered as the message packaging format until a better mechanism is developed.


2. Security Revisited.

In the previous article Security Made Easy, we showed some Java API to sign and encrypt a piece of data. We did not address how the pieces of information should be packaged. By now, you probably have thought about how the information can be packaged.

A high level rule is to have all the security information (message meta data), such as algorithms, parameters, secret key, signature value, encoding rule (for signature and encrypted data), etc. set as the child elements of the "header" element of the message.

And the encrypted (and encoded) data be set as a child element of the message "body" element of the message.

The "piece of data" to be signed and encrypted can (should) be isolated into a byte[] to avoid any XML canonicalization issues.

Specifications for XML signature and encryption are developed for quite sometime. But in practice, you may choose to define some simple elements as mentioned above to avoid issues (such as canonicalization) described at the links below.

http://en.wikipedia.org/wiki/XML_Signature
http://www.cs.auckland.ac.nz/~pgut001/pubs/xmlsec.txt


3. Base64 Encoding.

The XML signature or encryption output is often produced as a byte[]. The byte[] requires to be encoded before it is set as the value of an XML element. Base64 encoding/decoding is often used to "translate" a byte[] into a String and vice versa.

Java does not provide a public/supported implementation. The following are links to source code from JXTA.

Base64Encoding for Java:
https://jxta-jxse.dev.java.net/source/browse/jxta-jxse/trunk/impl/src/net/jxta/impl/util/BASE64OutputStream.java
https://jxta-jxse.dev.java.net/source/browse/jxta-jxse/trunk/impl/src/net/jxta/impl/util/BASE64InputStream.java


4. Summary.

XML provides the mechanism to package a message into a self-contained message. When a message is self-contained, the message can travel through "the cloud" without losing any required information to process the content of the message.

A self-contained message can live much longer than one that's not.

Monday, February 23, 2009

Security Made Easy

This article introduces some Java security API usage and provides simple solutions and code samples to solve common messaging security issues. These issues are becoming more important when programming in the web/cloud environment.

The first thing many of us would think of when talking about communication security is to use SSL/TLS/HTTPS technology. And in deed, this probably is the most popular mechanism used in today's enterprise and web applications.

The SSL/HTTPS provides a secure communication channel to authenticate the server and/or client (if client also presents its own certificate). If successfully connected (authenticated), the information (messages) transmission in between the two communication parties can not be read (privacy) or modified (integrity).

The technology is well established today. Tutorials and code samples can be obtained from many related books or articles. So we will not repeat the topic here. For example, the following link provides useful references for Java in this topic.

http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html


As the messaging providers move to the web (or cloud), SSL/HTTPS may not be enough to address all the security requirements. For example, messages received by a service may be stored in a file or a database until consumed (or removed at a later time).

The information may be compromised, if not protected, while it is stored at the persistent storage.

The rest of the article addresses the issue with a famous "Bob and Alice" security example as described below:

Bob wanted to send a secret message to Alice with the following criteria.
  • Alice can validate that the message is authentic (authored by Bob).
  • Alice can validate that the message is not tampered (while persisted in store).
  • Only Bob and Alice can understand (decrypt) the content of the message.
A simple solution for the above requirement is to use the public-key infrastructure and a hybrid cryptosystem.
(http://en.wikipedia.org/wiki/Hybrid_cryptosystem)

Before a message is sent, Bob does the following to sign and encrypt the message.
  • Generate a SecretKey (symmetric key) and encrypt the message with the SecretKey. The encrypted message is a byte[] (encryptedMessage).
  • Sign the (clear) message with Bob's private key. The signature is a byte[] (messageSignatureFromBob).
  • Encrypt the secret key with Alice's public key. The encrypted secret key is a byte[] (encryptedSecretKey).
The BOLD information above are to be sent to Alice as the "Secured Message". In other words, the message to be sent contains at least the three components: (encryptedMessage), (messageSignatureFromBob), and (encryptedSecretKey).

When a "Secured Message" is received, Alice does the following to verify the signature and decrypt the message.
  • Decrypt the encryptedSecretKey with Alice's private key. Alice reconstructs the SecretKey after the key is decrypted.
  • Decrypt the encryptedMessage with the reconstructed SecretKey.
  • Verify the messageSignatureFromBob with Bob's public key.
The following Java code samples exercised the above Alice/Bob message exchange scenario.

0. Certificate configurations. Bob and Alice each has its own certificate (and its own private key). Bob and Alice also obtained each other's certificate in their keystore.

Below are examples to create a self-signed certificate, import, and export certificates.

0.1 Example to create a self-signed certificate for bob.

keytool -genkeypair -dname "cn=bob, ou=em, o=em, c=us" -alias bob -keyalg RSA -keypass bobpass -keystore /keystores/bob/keystore -storepass bobpass -validity 180
Note: The -keyalg option is used because the default uses DSA algorithm,
but the DSA key algorithm is not supported in Sun's JDK 1.6.x Cipher implementation.

0.2 Example to export bob's certificate:

keytool -exportcert -alias bob -keystore /keystores/bob/keystore -file bob.cer
0.3 Example to import Alice's certificate into Bob's keystore:

keytool -keystore /keystores/bob/keystore -importcert -file alice.cer -storepass bobpass

Alice would do similar certificate setups as Bob's configurations above.

Link to Java keytool usage:
http://java.sun.com/javase/6/docs/technotes/tools/windows/keytool.html


1. Bob does the following to generate the SecretKey, sign the message, and encrypt the message.

1.1 Obtain Alice's public key.

private static final String BobKeyStorePath = "/keystores/bob/keystore";

//get bob's keystore password
byte[] bobpass = getBobPasword();

//create key store instance
java.security.KeyStore bobKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
java.io.FileInputStream fis = new java.io.FileInputStream(BobKeyStorePath);

//load the key store
bobKeyStore.load(fis, bobpass);

//get alice's certificate
Certificate aliceCert= bobKeyStore.getCertificate("alice");

//get alice's public key
java.security.PublicKey alicePublicKey = aliceCert.getPublicKey();

1.2 Generate a secret key (symmetric key)

//generate a secret key with triple-DES algorithm
javax.crypto.KeyGenerator keygen = KeyGenerator.getInstance("DESede");

//this is used to encrypt msg
javax.crypto.SecretKey secretKey = keygen.generateKey();

1.3 Encrypt the SecretKey with Alice's public key.

//get a new cipher instance with RSA as the transformation name
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, alicePublicKey);

//this is the encrypted secret key
byte[] encryptedSecretKey = cipher.doFinal(secretKey.getEncoded());

1.4 Sign the message.

The signature process is to ensure that a message received by Alice was indeed sent by Bob. The signature also serves the purpose that Bob can not deny that he did not send the message.

//get bob's private key entry
KeyStore.PasswordProtection kp = new KeyStore.PasswordProtection (bobpass);
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) bobKeyStore.getEntry("bob", kp);

//get bob's private key
java.security.PrivateKey bobPrivateKey = pkEntry.getPrivateKey();

//get a signature object for bob
java.security.Signature bobSignature = Signature.getInstance("SHA1withDSA");

//initialize the signature object with bob's private key,
//it is now ready to use
bobSignature.initSign(bobPrivateKey);

//message to be sent to Alice
String message = "message to Alice";

//encode the clear message with "utf8" encoding
byte[] data = message.getBytes("utf8");

//update data to signed by bob's signature object
bobSignature.update(data);

//sign the data.
byte[] messageSignatureFromBob = bobSignature.sign();

1.5. Encrypt the message using the secret key generated.

//get a cipher object with triple-DES algorithm
Cipher cipher = Cipher.getInstance("DESede");

//initialize the cipher object with geberated secret key (symmetric key)
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

//encrypt the message
byte[] encryptedMessage = cipher.doFinal(data);


2. Alice does the following to verify the signature, decrypt the SecretKey, and decrypt the message.

2.1 Obtain Alice's private key.

private static final String AliceKeyStorePath = "/keystores/alice/keystore";
//get alice's keystore password
byte[] alicepass = getAlicePasword();

//create key store instance
java.security.KeyStore aliceKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
java.io.FileInputStream fis = new java.io.FileInputStream(AliceKeyStorePath);

//load the key store
aliceKeyStore.load(fis, alicepass);

//get alice private key entry
KeyStore.PasswordProtection kp = new KeyStore.PasswordProtection (alicepass);
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) aliceKeyStore.getEntry("alice", kp);

//get alice's private key
java.security.PrivateKey alicePrivateKey = pkEntry.getPrivateKey();

2.2 Decrypt the SecretKey with alice's private key.

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, alicePrivateKey);

//this is to be sent to receiver along with the encrypted msg
byte[] encodedSecretKey = cipher.doFinal(encryptedSecretKey);

//build the key
SecretKey secretKey= new SecretKeySpec (encodedSecretKey, "DESede") ;

2.3 Decrypt the message with the SecretKey.

//decrypt data
Cipher cipher2 = Cipher.getInstance("DESede");
cipher2.init(Cipher.DECRYPT_MODE, secretKey);

//decrypt message
byte[] data = cipher2.doFinal(encryptedMessage );

String message = new String (data, "utf8");


2.4 Verify signature with Bob's public key.

//get Bob's certificate
Certificate certificate = aliceKeyStore.getCertificate("bob");

//get bob's public key
PublicKey publicKey = certificate.getPublicKey();

//get signature object instance
java.security.Signature signature = Signature.getInstance("SHA1withDSA");

//initialize with bob's public key
signature.initVerify(publicKey);

//update with data obtained in 2.2 (decrypted message)
signature.update(data);

//returns true if the signature is valid
boolean isValidSignature = signature.verify(messageSignatureFromBob );

Tuesday, February 17, 2009

Meet The Web, Part 2 (with transaction)

In the previous article "Meet The Web, RESTfully ", we introduced a conceptual model for a RESTful messaging service. In this article, we extended the interface and service to make a group of messaging operations in a transaction possible.

In the RESTful messaging service , the URLs to identify the message services are as follows.

http://www.effectivemessaging.com/jms/production/queue/destination_name
http://www.effectivemessaging.com/jms/consumption/queue/destination_name

Each HTTP protocol interaction (request-response) for the above service is essentially equivalent to a complete transaction. A client application examines the HTTP response code to verify if a message production or consumption request is successful.

At most one message can be in doubt (message in question) when a system failure occurred. In other word, when the application is unable to verify the HTTP response code from the response message, the status of the request is unknown.

This behavior is somewhat similar to a JMS application with a non-transacted (AUTO-ACKNOWLEDGE) JMS session. At most one message's status could be in question (unknown) when a system or network failure occurred.

In order to group a series of operations in a transaction, we define a set of "transacted protocols" to "link" these operations in a transaction.

The "transacted protocols" make it possible to commit or rollback a set of operations performed on the RESTful message service.

A conceptual implementation is described in the second section of this article.


1. Transacted protocols for the message service web interface.

The protocols includes setting the boundaries for a transaction (transaction demarcation). An unique TransactionID is created by the message service when a new transaction is created (START). Each operation in the transaction is then tagged with the TransactionID.

Applications may COMMIT a transaction after setting the END boundary. Applications may ROLLBACK a transaction if the transaction state is after START and before COMMIT.

1.0 Start a new transaction.

An application sends a HTTP request message to start a new transaction. If the request is accepted, a new TransactionID is set in the HTTP response message body and returned to the application.

URL:
http://www.effectivemessaging.com/transactions

Example request message:

----------------------------------------
POST /transactions HTTP/1.1
(other headers omitted)

TXCOMMAND=START
------------------------------------

The HTTP response message body contains a transaction ID generated by the message service.

Example response message:

--------------------------------------
HTTP/1.1 200 OK
(other headers omitted)

TransactionID=12345(UUID)
------------------------------------------

1.1 Produce and consume messages in a transaction.

The associated transaction ID is set in the HTTP header for the HTTP request message.

URL to send a message in the current transaction:
http://www.effectivemessaging.com/jms/production/queue/destination_name

Example request message:

-------------------------------------------------------------------------
POST /jms/production/queue/myQueue HTTP/1.1
Content-Type: text/plain;charset=UTF-8
User-Agent: Java/1.6.0_07
Host: localhost:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 10
TransactionID: 12345 (uuid)

HelloWorld
--------------------------------------------------------------------------

Example response message:

--------------------------------------------------------------------------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=UTF-8
Content-Length: 0
Date: Mon, 02 Feb 2009 21:59:58 GMT
TransactionID: 12345 (uuid)
---------------------------------------------------------------------------

URL to receive a message in the current transaction:
http://www.effectivemessaging.com/jms/consumption/queue/destination_name


Example consumption request message:

---------------------------------------------------------------------------
POST /jms/consumption/queue/myQueue/ HTTP/1.1
Content-Type: text/plain;charset=UTF-8
User-Agent: Java/1.6.0_07
Host: localhost:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 0
TransactionID: 12345 (uuid)
---------------------------------------------------------------------------

Example consumption response message:

-----------------------------------------------------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=UTF-8
Content-Length: 11
Date: Mon, 02 Feb 2009 23:04:05 GMT
TransactionID: 12345 (uuid)

HelloWorld
-----------------------------------------------------

1.2 End a transaction.

http://www.effectivemessaging.com/trasnactions/12345(uuid)

Example request message:

-----------------------------------------------------
POST /transactions/12345(uuid) HTTP/1.1
(other headers omitted)
TransactionID: 12345 (uuid)

TXCOMMAND=END
-----------------------------------------

Example response message:

----------------------------------------------
HTTP/1.1 200 OK
(other headers omitted)
TransactionID: 12345 (uuid)
----------------------------------------------

1.3 Commit a transaction.

http://www.effectivemessaging.com/trasnactions/12345(uuid)

Example request message:

-----------------------------------------------
POST /transactions/12345(uuid) HTTP/1.1
(other headers omitted)
TransactionID: 12345 (uuid)

TXCOMMAND=COMMIT
------------------------------------------------

Example response message:

-----------------------------------------------
HTTP/1.1 200 OK
(other headers omitted)
TransactionID: 12345 (uuid)
-----------------------------------------------

1.4 Rollback a transaction.

http://www.effectivemessaging.com/trasnactions/12345(uuid)

Example request message:

-------------------------------------------------
POST /transactions/12345(uuid) HTTP/1.1
(other headers omitted)
TransactionID: 12345 (uuid)

TXCOMMAND=ROLLBACK
-------------------------------------------------

Example response message:

-------------------------------------------------
HTTP/1.1 200 OK
(other headers omitted)
TransactionID: 12345 (uuid)
-------------------------------------------


2. Conceptual transacted message service implementation.

The transacted protocols can be easily implemented (validated) if the RESTful messaging service is backed by a (JMS) service.

Upon received a transaction START request, the message service implementation can create a transaction object and an associated (JMS) transacted session. The transaction object contains the TransactionID as its look-up key and has a reference to the (JMS) transacted session.

The TransactionID is set in the HTTP START response message body and returned to the application.

For each sub-sequential transacted send/receive request (tagged with TransactionID), the message service delegate the request to the (JMS) transacted session associated with the transacted object. The transacted session is used to send and rereive transacted messages on behalf of the request.

The END protocol is defined here to make the interface uniform and extensible in the future (such as two-phase commit protocol support). It is also used to set the END transaction boundary precisely.

For a COMMIT/ROLLBACK request, the message service delegate the request to the JMS transacted session. The transaction is thus committed or rollback via Session.commit() or Session.rollback() if the request is validated.

Wednesday, February 11, 2009

Messaging In The Cloud

As Larry Ellison put it, "Software is a fashion business". Cloud computing is one of the hottest topics in the computer industry recently. As software developers that live with messaging, we would be "out of fashion" if we do not join the party in time.

With the concept of SaaS (Software As A Service) materialize, it is a natural evolution for many applications (software services) to be "hosted" in the "cloud". And also naturally, this includes the messaging services.

If you are new to the cloud computing terminology, here is a definition from wikipedia.

"Cloud computing is Internet ("cloud") based development and use of computer technology ("computing"), whereby dynamically scalable virtualised resources are provided as a service over the Internet." -- quoted from wikipedia:

http://en.wikipedia.org/wiki/Cloud_computing

In the previous article, the RESTful style of messaging had set the stage for the messaging service to be deployed in the cloud. The article titled "Meet The Web, RESTfully" discussed building a conceptual model for "messaging as a service":

(http://effectivemessaging.blogspot.com/2009/02/meet-web-restfully.html)

To enable the "messaging as a service" and deploy the service in the cloud, the (cloud) service provider would require to implement and deploy the message service in the provider's infrastructure.

Conceptually, the cloud service provider would provide the following services.
  • Cloud infrastructure. This includes hardware, operating systems, and required application stacks to host services.
  • Messaging service implementation. The services are available to the service consumer (authenticated and authorized) with public URIs. The service implementation may (optionally) include JMS message service as the back-end routing service.

The "cloud" concept could change the messaging development process in the corporate IT in a very fundamental way. The following issues are usually required to be included in the design and deployment for a messaging system.
  • Hardware issues.
  • Messaging server/service installation, configuration, upgrade, and maintenance issues.
  • Cluster and Highly-availability issues.
  • Scalability issues.
These issues are now owned by the cloud service provider if used.

IT software developers can simply use the new "web" API (such as the RESTful API mentioned in the previous article) to solve the messaging requirement between applications. The cloud service provider is responsible to have the messaging service "be available and be available all the time"!

This probably sounds too good to be true. And of course there are concerns with the new model:
  • The control (ownership) of the data (messages).
  • The security issues. Such as authentication, authorization, integrity, and privacy.
  • Is pay-per-use model right for you?
The control of the data issue is usually classified as business (corporate lawyer) issues. We will leave it to be solved by the business people.

The security issues can be resolved in the current available technology. Client applications could use https, certificates, and cryptographic libraries to resolve the mentioned security issues. The cloud service provider is also likely to have a security group to address the security concerns.

Messaging in the cloud is an attractive alternative for many scenarios. Such as for some start-ups and independent developers. New applications could be developed, tested and deployed immediately without all the up front hardware and software cost.

Potential cloud service providers or current messaging providers may roll out different levels of messaging service in the near future. In the mean while, Amazon already provides the "Simple Queue Service" (Amazon SQS) that address some of the "queue" messaging requirements.

In the end, it comes to the big question. Is the pay-per-use model right for you?

Monday, February 9, 2009

Meet The Web, RESTfully

This article introduces web interfaces to the JMS message services.

JMS has become a de facto reliable message service for the enterprise applications. As the train of applications has moved to the web, it is a natural requirement for the messaging service to be reachable from web applications. Or as a matter of fact, from any http capable applications.

A popular web interface is the RESTful style API. This article discusses the message service web interface in the context of the RESTful style API.

The "Representational state transfer (REST) is a style of software architecture for distributed hypermedia systems such as the World Wide Web." (Quoted from wikipedia) If you are new to the REST terminology, here is a link to a nice introduction to what it is.

http://en.wikipedia.org/wiki/Representational_State_Transfer

An usage example for the interface is to have AJAX applications (running in a browser) to send or receive messages to the message service. Another usage example of the interface is to have C# applications talk to Python applications asynchronously.

There are commercial (MOM) products that provide the interface and implementation. At the time of this writing, most of the implementation are in the transition to a more mature states. The following are some of the examples.

Apache Active MQ introduced a (accidental) RESTful API to its messaging service:
http://activemq.apache.org/rest.html

The recent release (MQ4.3) of Sun Java Message Queue introduced a more comprehensive web API and implementation:
https://mq.dev.java.net/4.3-content/ums/umsIntro.html


The following section presents a conceptual model (design and implementation overview) of a RESTful messaging service. This can be used as a reference to implement a simple RESTful message service to interface with your favorite messaging provider. The contents presented here assumed that the reader is familiar with basic HTTP protocol and JavaServlet Technology.

The model can be divided into two separate components. The first component is the interface (URI and protocol) to the service. The second component is the service implementation. Each component is elaborated in more details below.

1. The interface to the message service.

A RESTful MOM interface can be (naturally) modeled around Destinations. A destination is a resource that applications used to send or receive messages.

1.1 URL and protocol to send a message.

A message production service URI used to send messages to a destination can be designed as follows.

http://www.effectivemessaging.com/jms/production/queue/destination_name/

where "queue" in the URI identifies that the destination is a queue domain.
where "destination_name" is the name of the JMS destination in the messaging system.

For example, the following represents a protocol (interface) to send a message to the destination "myQueue" in the queue domain.

http://www.effectivemessaging.com/jms/production/queue/myQueue/

The HTTP method POST MAY be used for the "message production" protocol message.

The body of the HTTP message is the message body to be sent to the destination.

The "Content-Type" can be used to specify the content of the message.

The HTTP response status code is used to indicate the status of the request service.

An example protocol interaction (HTTP request-response message) to send a "HelloWorld" to destination "myQueue" would look like this:

----------------- HTTP Request ------------------
POST /jms/production/queue/myQueue/ HTTP/1.1
Content-Type: text/plain;charset=UTF-8
User-Agent: Java/1.6.0_07
Host: localhost:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 10

HelloWorld

----------------- HTTP Response ---------------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=UTF-8
Content-Length: 0
Date: Mon, 02 Feb 2009 21:59:58 GMT
-----------------------------------------------------

1.2. URL and protocol to receive a message.

A message consumption service used to receive messages from a destination can be designed as follows.

http://www.effectivemessaging.com/jms/consumption/queue/destination_name/

where "queue" in the URI identifies that the destination is a queue domain.
where "destination_name" is the name of the JMS destination in the messaging system.

For example, the following represents a protocol (interface) to receive a message from the destination "myQueue" in the queue domain.

http://www.effectivemessaging.com/jms/consumption/queue/myQueue/

The HTTP method POST MAY be used for the "receive" protocol message.

The received message body is set in the body of the HTTP response message.

The response message "Content-Type" can be used to specify the content of the response message.

The HTTP response status code is used to indicate the status of the request service.

An example protocol interaction (HTTP request-response message) to receive a message from destination "myQueue" would look like this:

----------------- HTTP Request --------------
POST /jms/consumption/queue/myQueue/ HTTP/1.1
Content-Type: text/plain;charset=UTF-8
User-Agent: Java/1.6.0_07
Host: localhost:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 0

----------------- HTTP Response ---------------
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=UTF-8
Content-Length: 11
Date: Mon, 02 Feb 2009 23:04:05 GMT

HelloWorld
---------------------------------------------------

2. Message Service Implementation.

One simple and straight forward implementation for the above service is to use the Java Servlet techonology. A servlet can be deployed in a container (such as Tomcat) to provide the send and receive services.

When the servlet is invoked, it obtains the service type (send or receive), destination domain (queue or topic), and destination name from the request URI. Theservlet then performs the messaging service on behalf of the request. The servelet may use cached Connections. The JMS Session/Producer/Consumer objects are created (or obtained if cached) to perform the requested services.

An appropriate status code and message body are returned to the client in the HTTP response message.

A special thanks to Keith Babo and Frank Kieviet at Sun Microsystems, Inc. for their input to the content of this article.






Friday, February 6, 2009

MDB Illustrated

In the previous article, we briefed the skeleton of a MDB. In this article, we describes a conceptional model to illustrate how MDB works inside a container.

A container is loosely referred to an application server in this article. The functions performed by a container mentioned below includes those done by a resource adapter and messaging provider.

When a MDB is deployed in a container, the container located two JMS resources that each MDB must be associated with.
  • The ConnectionFactory that the container uses to create a connection to the messaging server.
  • The Destination that the MDB is interested in receiving messages from the messaging server.
The container creates a connection (if none is available) to the messaging server based on the allocated ConnectionFactory. If the connection was acquired/created successfully, the container then creates a message consumer (on behalf of the MDB) on the destination associated with the MDB. The container is now ready to deliver messages to the MDB instances.

The container constructs a MDB instance with the following sequence.
  • Invokes the MDB class'es newInstance() method to obtain a new instance.
  • Injects resources to the instance,if any. For example, injects MessageDrivenContext if declared.
  • Invokes the PostConstruct method, if any.
When a message arrives (received by the container on behalf of the MDB), the container delivers/dispatches the message as follows.
  • Get an available MDB instance (or create a new one if none is available) from the instance pool.
  • Allocate a thread from the thread pool (to execute the MDB instance).
  • Start the allocated thread to deliver the message with the following sequence.
    1. Start a new transaction if the MDB uses a container-managed transaction (default).
    2. Invoke the onMessage(Message m) method.
    3. Acknowledge/commit the transaction when onMessage() returns.
    4. Return the current thread and MDB instance back to their own pools.
At any point in time, there could be multiple instances been executed concurrently per MDB class. The maximum concurrent instances are usually configured during deployment. The container executes each MDB instance with one thread at a time.

The container calls an MDB instance's PreDestroy method, if any, before it destroys the instance.

Thursday, February 5, 2009

MDB in 3 minutes

This article introduces basic JMS Message Driven Bean (MDB) design that uses EJB 3.0 API (Java EE 5).

A MDB (EJB 3.0 API) class can be constructed with the following skeleton.

1. Implement the javax.jms.MessageListener interface.

2. Annotated with the MessageDriven annotation.

3. Include supported dependency injection annotation (optional).

The following is a "functional" MDB code example.

--------------------------------------------------------------
package emessaging.mdb;

import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;

@MessageDriven(mappedName = "jms/myMDBQ")
public class HelloWorldMDBBean implements MessageListener {

public HelloWorldMDBBean() {
}

public void onMessage(Message message) {
System.out.println("*** received message: " + message);
}

}

-----------------------------------------------------------------------------------

When deployed in a container that supports Java EE 5, the above MDB receives messages on destination with the JNDI loop up name "jms/myMDBQ". This MDB uses the container-managed transaction (default). Transaction and message acknowledgment are automatically handled by the container for each message delivered to aMDB instance (onMesage() invocation).

In order to have the above code working properly, the following resources are also required to be configured for the target container (and/or the messaging server).

  • A JNDI Destination object must be created with look up name "jms/myMDBQ".
  • The JMS destination resource associated with "jms/myMDBQ" must be created on the messaging server.
  • A JNDI ConnectionFactory object may required be created and associated with the MDB.

The ConnectionFactory and Destination objects are heavily vendor dependent. After they are configured, the information may also need to be packaged along with the MDB code and then deployed to a target container (app server).

It is an inhumanity process to configure/package the administrated objects/MDB without using a (vendor) supported IDE/tool.

At the time of this writing, the IDE/tools have been improved over the years and are reasonably useful for all major vendors.

For example, the above example can be constructed/deployed/tested with netbeans IDE without dealing with the details of the notorious Java EE configuration syntax.

If you are not comfortable with this example, here is a link to get familiar with the basics.

http://java.sun.com/javaee/5/docs/tutorial/doc/bnbpk.html

In order to be comfortable with the MDBs, you would probably like to know what happened "under the hood". In the coming article, we will introduce the details of how it works.

Tuesday, February 3, 2009

Unidentified Message Producer

The JMS Session is the factory to create message producers. When creating a message producer, the Session's create producer method parameter specifies a Destination object to be associated with the producer created.

The method in the Session API to create a message producer is as follows.
MessageProducer createProducer(Destination destination) throws JMSException;
If a non-null destination is specified in the parameter, the created message producer is called an identified message producer. An identified message producer is used when a producer always produces messages to the same destination during the life time of the producer object.

If a null destination is specified in the parameter, the created message producer is called an unidentified message producer. An unidentified message producer is used when a producer is used to produce messages to more than one destinations. For example, the following is an example to use an unidentified message producer. The send method in the code snippet sends a message to a queue or topic destination. The JMS objects are initialize (in the init() method) before the send method is invoked.

/**
* Initialize JMS objects.
*
* @throws JMSException
*/
public void init() throws JMSException {

//get an instance of JMS connection factory.
ConnectionFactory factory = EMFactory.getConnectionFactory();

//create a connection
conn = factory.createConnection();

//create a session
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

//create a message producer on the destination
producer = session.createProducer(null);

myTopic = session.createTopic("myTopic");

myQueue = session.createQueue("myQueue");
}

/**
* The send example method sends a message to a queue or topic based
* on the specified boolean parameter.
*
* @param sendToTopic true if the message is to be sent to topic
* destination. Otherwise, the message is sent to a queue destination.
*
* @param text The text message to be set in the text message.
*
* @throws JMSException if any internal error occurred.
*/
public void send(boolean sendToTopic, String text) throws JMSException {

// destination
Destination dest = null;

// create a queue instance
if (sendToTopic) {
dest = myTopic;
} else {
dest = myQueue;
}

// create a text message
TextMessage m = session.createTextMessage(text);

System.out.println("sending message to destination:\n " + dest);

// send the ping message
producer.send(dest, m);
}


An unidentified message producer is often used as a cached producer. Applications would get an instance of an unidentified message producer object from its cache implementation before sending a message. In this scenario, it is required to synchronize the usage of a cached producer. The messaging service behavior is undefined if a session (producer object) usage is not synchronized.

JMS ExceptionListener

The JMS API JavaDoc specified the ExceptionListener interface behavior as follows.

"If a JMS provider detects a serious problem with a Connection object, it informs the Connection object's ExceptionListener, if one has been registered. It does this by calling the listener's onException method, passing it a JMSException argument describing the problem.

An exception listener allows a client to be notified of a problem asynchronously. Some connections only consume messages, so they would have no other way to learn that their connection has failed.

A JMS provider should attempt to resolve connection problems itself before it notifies the client of them."

In practice, when an exception listener is called, the connection is broken and the JMS service is no longer available for the connection.

An ExceptionListener can be used for the following purposes.

1. This is the only standard API that a JMS message listener can be notified of a connection problem. When it is called, the JMS service is no longer available. An application can, at a minimum, log the problem and clean up its resources. Application can also notify any interest parties that needs to be notified of such a problem.

2. An application can, if necessary, implement its own simple high-availability functionality when an ExceptionListener is used. If an application is designed with a clean initialization setup, it would be feasible to reinitialize the JMS objects when the exception listener is called. The reinitialization process can even include (re)connecting to a list of pre-configured messaging servers. This simple JMS service-availability feature can be implemented with just a little effort.

An ExceptionListener should always be used in a JMS application, this is especially true for an application with only asynchronous message consumers.




Monday, February 2, 2009

JMS Reliability

This article revisited the JMS reliability and looked at the API provided parameters and their implications.

The JMS provides APIs to specify reliability for message producers and message consumers. The reliability consists of two separate contracts:
  • the contract between a producer and the messaging provider.
  • the contract between a consumer and the messaging provider.
The two contracts are essentially independent to each other. A message producer has no control over how a message is consumed and acknowledged. Similarly, a message consumer has no control over how messages are produced to a destination from which they are consumed.

To achieve end-to-end reliability, an application should be aware of both contracts and choose an appropriate configuration fits the application. The end-to-end reliability means the same message is produced exactly once and be received by a consumer exactly once.

1. Producing message reliably.

A message producer can specify the following parameters when producing a message to a destination. These parameters can affect message reliability if not used properly.
  • time-to-live
  • delivery-mode
  • message-priority
1.1 Time-To-Live.

The API Javadoc says as follows for the MessageProducer's setTimeToLive() API.

"Sets the default length of time in milliseconds from its dispatch time that a produced message should be retained by the message system."

For time-to-live to work reliably, a messaging provider may require to synchronize the clock among the messaging server and the messaging client runtime (applications). The implementation is vendor dependent and a vendor may choose not to synchronize the clock and assume this is a user's responsibility.

Applications should always use the default time-to-live value (0, never expire) if clock synchronization can not be guaranteed. Messages could be expired unexpected if clocks are not synchronized between client(s) and the messaging server(s).

1.2 Message Priority

Below is quoted from JMS API JavaDoc.

"The JMS API defines ten levels of priority value, with 0 as the lowest priority and 9 as the highest. Clients should consider priorities 0-4 as gradations of normal priority and priorities 5-9 as gradations of expedited priority. Priority is set to 4 by default."

In practice, the message priority should be treated as a hint only. Setting a high priority for a message may not guarantee the message be delivered before a lower priority message sent earlier. There are many factors may affect this. For example, a previous sent message (with lower priority) may already in transition to be delivered to a consumer. A high priority message produced at a later time may not be jump ahead and deliver to a consumer in a predictable way. The behavior is vendor dependent and should be used with caution.

1.3 Delivery Mode.

An application should produce non-persistent messages only if messages are allowed to be lost when a system failed (hardware or software).

An application should use a transacted session to produce persistent messages for maximum reliability. When Session.commit() is called, a messaging provider SHOULD sync the produced messages to its persistent repository to avoid message loss should a system failure occurred. It is consider a messaging provider's bug if a sync operation is not enforced when commit() returned successfully.

2. Consuming message reliably.

This section assumes that messages were produced reliably to a destination as discussed in the above section.

Message consumption reliability are controlled by the session acknowledge mode or if a transacted session is used.

A message lost is defined as follows.

"A message was produced reliably to a destination as per JMS specification (such as sending a persistent message to a queue in a transacted session) but was never seen by the message consumer attached to the same destination."

The reliability for various session acknowledge modes are discussed as follows.

2.1 asynchronous consumption (message listener) with auto-acknowledge session.

At most one message can be redelivered when a system failure occurred. No messages can be lost when a system failure occurred.

2.2 synchronous consumption with auto-acknowledge session.

According to the JMS reference implementation, at most one message can be lost when a system failure occurred.

2.3 dups-ok-acknowledge.

Multiple messages could be redelivered when a system failure occurred. At most one message could be lost for a synchronous receive consumer.

2.4 client-acknowledge session.

Messages consumed but not acknowledged are re-delivered when a system failure occurred. No messages can be lost when a system failure occurred.

2.5 transacted session.

Message consumed but not committed are re-delivered when a system failure occurred. No messages can be lost when a system failure occurred.

For a standard JMS implementation, transacted session and client-acknowledged session could have the same reliability. But when applications are deployed in a system with a highly-available feature, a transacted session could receive a better reliability due to the possibility that the provider may implement a 2-phase commit protocol for a transacted session. In this case, there would be less possibility for any message redelivery in a transacted session.









Saturday, January 31, 2009

MessageListener Exception Handling.

This article talks about exception handling inside a message listener's onMessage() method:

public void onMessage(Message message);

The asynchronous API does not allow an application to throw any checked exception, and the JMS API JavaDoc specification says as follows.

"It is a client programming error for a MessageListener to throw an exception."

The above statement basically tells the JMS messaging providers to handle the (runtime) exception thrown from a message listener in their own way (undefined).

Below are some of possibilities that a messaging provider can do when received an exception thrown from the onMessage() method.

  • Set the message redelivery flag to true and redelivery the message to the message listener. The number of times a provider will attempt to redeliver a message is undefined.
  • Send the message to the provider defined dead-message-queue and continue delivering the next message.
  • Stopped message delivery to the listener.

While a messaging provider may define and specify the behavior, an application should avoid tying with a specific vendor whenever possible. It would be probably a better choice to resolve application's business logic precisely and not rely a messaging provider to guess an error from the application.

An application may consider to define and configure an error queue. An error queue is a destination used to store messages that an application can not process. When a message listener encounters an exception while processing a message, the application could send the "trouble message" to the error queue. The application can then acknowledge and continue processing the next message delivered from the messaging provider. This ensures that messages continue to flow with a predicted behavior.

Messages in the error queue can be replayed at a later time to help identifying the root cause of the exception.

A runtime exception thrown from a message listener could cause unpredictable behavior from a messaging provider and thus should be avoided. A good programming practice is to handle any possible exceptions that could be generated from within the message listener.

Friday, January 30, 2009

JMS Synchronous Message Consumption

A JMS message consumer can consume messages synchronously by calling one of the MessageConsumer's receive() methods:
  • receive()
  • receive (long timeout)
  • receiveNoWait();
Calling receive() or receive (0) will block until there is a message available. This is the easiest form to receive a message synchronously. The only disadvantage is that the application thread is blocked indefinitely.

Receive with timeout and receiveNoWait are the two alternative API to consume messages synchronously. But applications should be aware of the intended contract and behavior of the APIs. Applications may not function reliably or consistently if they are not used properly.

1. receive (long timeout)

The JMS API JavaDoc for the API is quoted as follows.

"Receives the next message that arrives within the specified timeout interval.

This call blocks until a message arrives, the timeout expires, or this message consumer is closed. A timeout of zero never expires, and the call blocks indefinitely."

One important thing to note is the timeout value. This is the maximum wait time that the application should be expecting to wait. The call returns immediately if there is a message available. The call may block up to the specified timeout value if no message is available.

Some books and articles provide misleading examples that would cause the application behaves inconsistently. For example, the following code used a timeout value of one milli second that is likely to cause the application's behavior in-deterministic.

//create a queue instance
dest = session.createQueue(destName);

//create a message consumer to receive messages on dest.
MessageConsumer consumer = session.createConsumer(dest);

//tell the connection I am ready to receive the reply
conn.start();

//receive a message with the max timeout of 1 milli second.
Message rm = consumer.receive(1);

if (rm == null) {
System.out.println ("\n No message is received:\n ");
} else {
System.out.println ("\n Message received: " + rm);
}

The above code is likely to result in a null value be returned for the receive(1) call even if there is a message on the destination. The reason is that the timer may start from the moment receive method is called, and the timeout value is also reached immediately. If there is no message available within one milli second to the application, the API returns a null value. (The message may be still in network transition from the server to the message consumer.)

Even though different messaging vendors may internally implement in a different way, it is always a good practice to code defensively.

Application should always assume the timer starts when receive(timeout) is called, and a null value is returned if timeout expired before a message is available, if any.

A good practice to use timed synchronous receive is to consider the following suggestions.
  • specify a "reasonable" max timeout value whenever possible.
  • the receive (timeout) call should always be revisited (call again) if a small timeout value is specified.
  • a small timeout value in a loop could possibly cause tight cpu loop if no other wait/sleep in the loop.
  • avoid (re)creating a new synchronous message consumer for each receive (timeout) call.
The following is an example to use the timed receive API.

//create a queue instance
dest = session.createQueue(destName);

//create a message consumer to receive messages on dest.
MessageConsumer consumer = session.createConsumer(dest);

//tell the connection I am ready to receive the reply
conn.start();

while ( !done ) {
//receive a message with the max timeout of 3 seconds.
Message rm = consumer.receive(3000);
//process business login
...
}


2. receiveNoWait().

The behavior of this API is similar to the timed receive API with a small timeout value. The programming practice should follow the above suggestions to ensure reliable messaging behavior.

Thursday, January 29, 2009

JMS Request-Response Messaging

JMS applications are often used to create event-driven style applications where an application creates a message listener and just continues on its own business. When a message arrives, the message listener's onMessage(Message m) method is called and the message is passed to the application as the method's parameter.

There are occasions when applications require using a request-response style messaging. A message producer sends a message containing a request and waits for the message consumer to respond. The producer determines its subsequent actions based on the response message.

The JMS API provides two simple classes, QueueRequestor and TopicRequestor, that are useful for implementing the request-response style messaging. However, these classes only provide an API that blocks on waiting for the response message until the response message is received. An application could block and "hang" if the response message never arrives.

This article introduces a simple mechanism to implement request-response style messaging with a timed wait on the response message. A TemporaryDestination (refers to a TemporaryQueue or a TemporaryTopic) can be used as the mechanism to implement this requirement.

A TemporaryDestination has the following characteristics.

  • It is created from the Session or its subclass. It is a destination object that does not require using the administrator's utility.
  • It has the lifetime of the connection in which it was created.
  • It is (in practice) set in a message using the Message.setJMSReplyTo() API.
  • It is (in practice) obtained using the Message.getJMSReplyTo() API.
  • It can only be consumed by the same connection that created it.

The following example uses a TemporaryQueue mechanism to implement a Ping utility. The Ping utility can be used to check if a queue message listener is active.

The example consists of three components.

1. The Ping message.

A simple ping message is defined as follows so that the message listener can tell that it received a ping message (not a business message).

A Ping Message is a Message type that contains a boolean property named "emessaging_ping_message" with its value set to true.


2. The message listener.

When a listener receives a ping message, it simply sends a ping reply to the temporary topic obtained from the ping message.

The pseudo code looks like this:

onMessage (Message msg) {
if (msg == PingMessage) {

//get the destination instance where the ping reply is to be sent.
Destination dest = msg.getJMSReplyTo();

//create a producer instance
producer = session.createProducer(dest);

//create ping reply message
Message pingReply = session.createMessage();
pingReply.setBooleanProperty(EMPing.PING_MESSAGE_REPLY, true);


producer.send(pingReply);
} else {
process_msg;
}
}


3. The Ping program.

This is a simple JMS application that sends a message to a destination and expects a response from the consumer (message listener).

The pseudo code looks like this:
//create a message producer on the destination
MessageProducer producer = session.createProducer(dest);

//create a ping message
Message m = session.createMessage();
//set ping message property
m.setBooleanProperty(PING_MESSAGE, true);

//create a temporary destination
TemporaryTopic respDest = session.createTemporaryTopic();

//set destination for the ping_reply message
m.setJMSReplyTo(respDest);

//create a message consumer to receive the ping_reply message
//This statement must be in front of the send statement
MessageConsumer consumer = session.createConsumer(respDest);

//tell the connection I am ready to receive the reply
conn.start();

//send the ping message
producer.send(m);

//receive ping reply message with max timeout 10 seconds.
Message rm = consumer.receive(10000);

if (rm == null) {
System.out.println ("\nlistener on destination is non-responsive:\n ");
} else {
System.out.println ("\nlistener on destination is alive.");
}


The complete code example is attached to this article.