Tuesday, September 7, 2010

Best Coding Practices for connecting to JMS (PUBLISHER)–


Best Coding Practices for connecting to JMS (PUBLISHER)–

1.        Connect to DS, save the initial context and create a connection factory object–

The first step is to connect to DS. For this,

·        use a single comma separated list of urls to connect to primary as well as backupservers.
Eg: For Production use,
abc001.xyz.com:2566,abc002.xyz.com:2566,abc004.xyz.com:2569
·        Do not use TryBackupOnFailure since it is not supported by 7.5 jar files.
·        Do not use secondary list of urls.
·        Keep the value of connectionTimeout as 240000 (2 mins).
·        Save the context.
·        Get Topic Connection Factory using the context.

Eg:

Properties env = new Properties();
env.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,initialcontextfactory);                
env.setProperty(javax.naming.Context.PROVIDER_URL, commaseparatedurl);
env.setProperty(javax.naming.Context.SECURITY_PRINCIPAL, username);
env.setProperty(javax.naming.Context.SECURITY_CREDENTIALS, password);
env.put("com.sonicsw.jndi.mfcontext.connectTimeout", connectionTimeout);
ctx = new javax.naming.directory.InitialDirContext(env);
factory = (TopicConnectionFactory) ctx.lookup(connectionFactory);

2.        If there is an issue connecting to DS, use saved connection factory object to connect to DS –

ObjectInputStream ois=null;
        FileInputStream fis=null;
        try
        {                        
            fis = new FileInputStream("connection_factory.sjo");
                        ois = new ObjectInputStream(fis);                                                    
                factory = (progress.message.jclient.TopicConnectionFactory)ois.readObject();        
        }
        catch(Exception e)
        {
                factory = null;
        }
        finally
        {
                if(ois != null)
                {
                        try
                        {
                                ois.close();
                        } catch (IOException e)
                        {
                                e.printStackTrace();
                        }
                }
        }

3.        If no issue found in connecting to DS and connection factory object is successfully created, save it for later use –

FileOutputStream fos=null;
        ObjectOutputStream oos=null;
        try
        {
                if (factory != null) // If ConnectionFactory is null, read it from file.
                    {
                                    fos = new FileOutputStream("connection_factory.sjo");                                    
                        oos = new ObjectOutputStream(fos);                        
                        oos.writeObject(factory);                                                
                }
        }
        catch (Exception e)
        {}
        finally
        {
                if(oos != null)
                {
                        try
                        {
                                oos.close();
                        } catch (IOException e)
                        {
                                e.printStackTrace();
                        }
                }
        }

4.        Create a connection with broker using Topic/Queue connection factory.

·        Creating a connection –

While creating a connection, first check if topic connection factory object is null or not.

If it is null, reconnect to DS, else, connect to Broker.

Eg:
if(factory == null)
{
Connect to DS;
}
else
{
        factory.setConnectID("App-Pub"); // Set connect ID
        connection = factory.createTopicConnection(username, password);
}        

Do proper exception handling while connecting to broker and if there is an exception found during connecting to Broker, retry connecting for a specified period of time (after a specified time interval) and if not able to connect, reconnect to DS.

·        Setting the connect id –

It determines whether the broker allows multiple connections to be established using a single username/ConnectID combination.

·        To allow only one connection, provide a valid connectID.
·        To allow unlimited connections, use null as the connectID.


5.        Create a session using connection.

If connection is created successfully, create a session.

Eg:

if (connection != null)
{
session = connection.createTopicSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
}

Use the value of the parameters passed in createTopicSession as per application requirement.

6.        Create a topic (destination) -

If  session is not null, create a topic.

Eg:

if (session != null)
{                                
pubTopic = session.createTopic(topicName);
}

7.        Create a publisher -

If session is not null, create a publisher.

        Eg:

if (session != null)
        {
                Publisher = session.createProducer(pubTopic);
                System.out.println("Publisher Created.");                                
        }

8.        Create a message to be published.

This is very specific to the application. However, define all the properties of message at this time carefully.

Eg:

DeliveryMode of the message – Persistent/Non-persistent
Priority of the message
Life of the message.

9.        Start the connection.

connection.start();

10.        At the end (before exiting), close the publisher, topic, session and connection

if(publisher != null)
        {                
                publisher.close();
        }
        if(session != null)
        {
                session.close();
        }
       
if(connection != null)
        {
                connection.stop(); // stop the connection before closing it.
                connection.close();
        }

Write the close sequence in a finally block so that it executes always and close all the objects and avoid obsolete/orphan/excessive objects.

11. Do proper Exception Handling in all the codes written above.

Apart from these, following items need to be taken care of –

1)        Handle all the exceptions in a proper way and log each exception with the stacktrace.
2)        Every time you try to reconnect to broker, check for the connection factory context. Connect to DS only if the context is not available or is null.
3)        Keep connection logic separate from application logic. This will ensure that the connection logic can easily be debug in case of any issue.
4)        Take thread dumps at the time of issue so that it becomes easier to investigate and find the root cause.

PS – Please note that the code snippets listed above are not fully qualified codes. They are provided just to serve as samples. Also, the functionality of the code can be changed on the basis of personalized requirements (Eg: value of connectionTimeout, deciding the amount and number of times you want your application to try to reconnect to DS/Broker in case of an issue.)

No comments:

Post a Comment