JMS Reliablity Mechanisms-Message persistence in JMS

We have discussed the fundamentals of JMS API. We already discussed the various messaging domains as well as message consumption modes. In this section we are discussing the messaging reliability mechanisms in JMS. Here in this chapter we are going to discuss the way by which reliability in messaging is ensuring by using message persistence.

Message Persistence in JMS

In applications  those uses Java Messaging API it is very much needed to ensure the reliable delivery of message between clients.Message persistence in JMS provides a way to ensure this.

JMS provides two delivery modes

1)Persistent delivery mode This is the default  delivery node. If we use this delivery mode, then it forces the JMS provider to take extra care to avoid the lose of a  message   if a provider failure occurs . If a provider failure occurs , then the message will be persisted . When the provider comes up the message will be delivered. This ensures  reliable message delivery.

2)Non-Persistent delivery mode– If we specify the delivery mode as non-persistent then the provider is not taking extra effort to persist the message if a provider failure occurs.

How we specify the delivery mode ?

In code we can specify the delivery mode in either of the two options:

1)By using the setDeliveryMode(int value) method of MessageProducer interface . For persistent delivery mode , the integer argument should be  2  (DeliveryMode.PERSISTENT) .For non-persistent delivery mode , the integer argument should be 1 (DeliveryMode.NON_PERSISTENT) .

2)We can use the overloaded      send() or publish() method instead of send() or publish() methods.The second argument in the method call specifies the delivery mode.

Remember , if are not specifying the delivery mode , then by default the mode will be persistent.

Message Persistence in JMS -An Example

We have two clients. First client is sending a text message to the second client. We are using OpenJMS as service provider.Before running the example , the openJMS should be configured and workspace should be ready as mentioned earlier. Don’t forget to include the necessary dependencies as discussed there . We are analyzing the  output in both the delivery modes  , so that it is possible to understand the difference.In both examples we are using Point-to-Point messaging domain.

case 1)Persistent delivery mode

FirstClient.java

import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class FirstClient {
Context context = null;
ConnectionFactory factory = null;
Connection connection = null;
Destination destination = null;
Session session = null;
MessageProducer producer = null;

public FirstClient() {

}

public void sendMessage() {

Properties initialProperties = new Properties();

initialProperties.put(InitialContext.INITIAL_CONTEXT_FACTORY,

“org.exolab.jms.jndi.InitialContextFactory”);

initialProperties.put(InitialContext.PROVIDER_URL,

“tcp://localhost:3035”);

try {

context = new InitialContext(initialProperties);
factory = (ConnectionFactory) context.lookup(“ConnectionFactory”);
destination = (Destination) context.lookup(“queue1”);
connection = factory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
connection.start();
TextMessage message = session.createTextMessage();
message.setText(“Hello …This is a sample message”);
producer.send(message);
System.out.println(“Sent: ” + message.getText());

} catch (JMSException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}

if (context != null) {
try {
context.close();
} catch (NamingException ex) {
ex.printStackTrace();
}
}

if (connection != null) {
try {
connection.close();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
FirstClient firstClient = new FirstClient();
firstClient.sendMessage();
}

}

 

After creating MessageProducer object itself , the delivery mode is specified. Here it is persistent.

SecondClient.java

import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class SecondClient {

Context context = null;
ConnectionFactory factory = null;
Connection connection = null;
Destination destination = null;
Session session = null;
MessageConsumer consumer = null;

public SecondClient() {

}

public void receiveMessage() {

Properties initialProperties = new Properties();
initialProperties.put(InitialContext.INITIAL_CONTEXT_FACTORY,

“org.exolab.jms.jndi.InitialContextFactory”);
initialProperties.put(InitialContext.PROVIDER_URL,

“tcp://localhost:3035”);

try {

context = new InitialContext(initialProperties);
factory = (ConnectionFactory) context.lookup(“ConnectionFactory”);
destination = (Destination) context.lookup(“queue1”);
connection = factory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(destination);
connection.start();
Message message = consumer.receive();
if (message instanceof TextMessage) {
TextMessage text = (TextMessage) message;
System.out.println(“Message is : ” + text.getText());
}

} catch (JMSException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}

if (context != null) {
try {
context.close();
} catch (NamingException ex) {
ex.printStackTrace();
}
}

if (connection != null) {
try {
connection.close();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
SecondClient secondClient = new SecondClient();
secondClient.receiveMessage();
}

}

 

Output

After starting the openJMS as mentioned earlier, run the FirstClient.

output of FirstClient.java

Sent: Hello …This is a sample message

java.When it exits itself  , stop the OpenJMS by calling the shutdown script from %OPENJMS_HOME%/bin.

Then start the OpenJMS by calling startup script from %OPENJMS_HOME%/bin

Now run the SecondClient.java

Output of SecondClient.java

Message is : Hello …This is a sample message

So even after the shutdown of JMS provider, the message was reliably delivered to receiving client.

case 2)Non-Persistent delivery mode

Use producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT) in  FirstClient.java. Then run the FirstClient.java. The output of FirstClient.java will be same as that of the above case. Now call the shutdown script from %OPENJMS_HOME%/bin. Then start the openJMS by calling startup script from %OPENJMS_HOME%/bin.

Now run the SecondClient.java.

The output will be a blank screen. That means the message was not persisted when we shut down the JMS provider.

Conclusion

From the above discussion it is clear that by specifying the message delivery mode as persistent, it is possible to ensure reliable delivery of messages.