Icebreaker Icebreaker - 1 month ago 13
Java Question

Ideal way to set up a JMS connection so it auto reconnects

I'm currently programming a messenger service for durable subscriptions (it might end up being non durable we are still discussing that) and I was looking for some suggestions on how to handle a scenario where our server goes temporarily down for whatever reason and we need to resubscribe to the topic automatically. Here is sample code of how it connects:

public void DurableChatter(String broker, String username, String password)
{
javax.jms.MessageProducer publisher = null;
javax.jms.MessageConsumer subscriber = null;
javax.jms.Topic topic = null;

//Create a connection:
try{
javax.jms.ConnectionFactory factory;
factory = (new progress.message.jclient.ConnectionFactory (broker));
connection = factory.createConnection (username, password);

//Durable Subscriptions are indexed by username, clientID and subscription name
//It is a good proactice to set the clientID:
connection.setClientID(CLIENT_ID);
pubSession = connection.createSession(false,javax.jms.Session.AUTO_ACKNOWLEDGE);
subSession = connection.createSession(false,javax.jms.Session.AUTO_ACKNOWLEDGE);
}
catch (javax.jms.JMSException jmse){
System.err.println ("Error: Cannot connect to Broker - " + broker);
jmse.printStackTrace();
System.exit(1);
}

//Create Publisher and Durable Subscriber:
try{

topic = pubSession.createTopic(APP_TOPIC);
subscriber = subSession.createDurableSubscriber(topic, "SampleSubscription");
subscriber.setMessageListener(this);
publisher = pubSession.createProducer(topic);
connection.start();
}
catch (javax.jms.JMSException jmse){
System.out.println("Error: connection not started.");
jmse.printStackTrace();
System.exit(1);
}

//Wait for user input

try
{
System.out.println("Enter text to send as message and press enter.");
java.io.BufferedReader stdin =
new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
while (true)
{
String s = stdin.readLine();

if(s == null){
exit();
}
else if (s.length()>0)
{
try
{
javax.jms.TextMessage msg = pubSession.createTextMessage();
msg.setText(username + ": " + s);
//Publish the message persistantly:
publisher.send(
msg, //message
javax.jms.DeliveryMode.PERSISTENT, //publish persistantly
javax.jms.Message.DEFAULT_PRIORITY,//priority
MESSAGE_LIFESPAN); //Time to Live
}
catch (javax.jms.JMSException jmse){
System.err.println("Error publishing message:" + jmse.getMessage());
}
}
}
}
catch (java.io.IOException ioe)
{
ioe.printStackTrace();
}
}

Answer

how fast do you need failure detection to be? set up your protocol so that it guarantees every client is sent a message at least once a minute (you'll need to add some new "fluff" keepalive message to your communication protocol) - any client not receiving a keepalive message can safely assume the server is down and begin reconnecting.

ideally this sort of thing is best done with UDP broadcast and not JMS (for the overhead), but i assume if you have UDP broadcast as an option you'd use jgroups to do you cluster detecion/failover/rejoin for you.

Comments