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.