Dashboard > JJGuidelines > Home > Appendix B - Guidelines Rules > B.4. JMS rules
JJGuidelines Log In | Sign Up   View a printable version of the current page.
B.4. JMS rules
Added by Alexander Bollaert, last edited by Alexander Bollaert on Jan 15, 2007  (view change)

JMS rules

Overview

Table B.4. JMS rules

Rules
JMS_001: Do Not Use A Vendor Specific Class
JMS_002: Do Not Hard Code An Initial Context Factory
JMS_003: Do Not Hard Code A Provider URL
JMS_004: Do Not Hard Code A Connection Factory Name For JNDI Lookup
JMS_005: Do Not Hard Code A Destination Name For JNDI Lookup
JMS_006: Use JNDI Lookups To Get A Connection Factory Or Destination
JMS_007: Close A Resource When It's No Longer Needed
JMS_008: Always Close Resources In The Correct Order
JMS_009: Do Not Produce A Message In A Transaction And Rely On It To Be Consumed Before The End Of The Transaction
JMS_010: Do Not Rely On JMS To Deliver Message In The Same Order As They Were Sent
JMS_011: Start A Producer Connection After Start A Consumer
JMS_012: Use A separate Transactional Session For transactional Messages And A Non-transactional Session For Non-transactional Messages
JMS_013: Set An Optimal Message Time To Live
JMS_014: Choose A Correct Message Type
JMS_015: Do Not Receive Messages Asynchronously In A Web Component, A Session Bean Or An Entity Bean
JMS_016: Do Not Use JMS Sessions In A Multi-threaded Context

JMS_001: Do Not Use A Vendor Specific Class

If you want your code to be vendor independent, you should not use vendor specific classes. You should only use classes from the javax.jms package.

WRONG

QueueConnectionFactory queueConnectionFactory = new progress.message.jclient.QueueConnectionFactory();

JMS_002: Do Not Hard Code An Initial Context Factory

Don't hard code the initial context factory class name when connecting to the server. It is better to store the initial context factory class name in an external configuration file that is read when the connection must be created..

WRONG

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
        "weblogic.jndi.WLInitialContextFactory");
// ...
InitialContext ctx = new InitialContext(env);

JMS_003: Do Not Hard Code A Provider URL

Don't hard code the provider URL when connecting to the server. It is better store the provider URL in an external configuration file that is read when the connection must be created.

WRONG

Hashtable env = new Hashtable();
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
// ...
InitialContext ctx = new InitialContext(env);

JMS_004: Do Not Hard Code A Connection Factory Name For JNDI Lookup

Don't hard code the connection factory name for a JNDI lookup. It is better to store the connection factory name in an external configuration file that is read when the JNDI lookup must take place.

WRONG

InitialContext ctx = new InitialContext(env);
QueueConnectionFactory qconFactory = (QueueConnectionFactory) ctx.lookup("jms/FooQueueConnectionFactory");

JMS_005: Do Not Hard Code A Destination Name For JNDI Lookup

Don't hard code the destination name for a JNDI lookup. It is better to store the destination name in an external configuration file that is read when the JNDI lookup must take place.

WRONG

InitialContext ctx = new InitialContext(env);
Queue queue = (Queue) ctx.lookup("jms/FooQueue");

JMS_006: Use JNDI Lookups To Get A Connection Factory Or Destination

Never instantiate connection factories or destinations yourself. This would be an automatic violation of rule

WRONG

QueueConnectionFactory queueConnectionFactory = new progress.message.jclient.QueueConnectionFactory();

JMS_007: Close A Resource When It's No Longer Needed

All JMS resources (Connection, Session, Producer, Consumer) must be closed when they are no longer used.
Always close you resources in a finally clause of a try block. See rule

WRONG

private void doWrongClose(QueueConnectionFactory qconFactory, InitialContext ctx) throws JMSException, NamingException {
	QueueConnection qcon = null;
	QueueSession qsession = null;
	QueueSender qsender = null;
	qcon = qconFactory.createQueueConnection();
	Queue queue = (Queue) ctx.lookup("jms/FooQueue");
	qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	qsender = qsession.createSender(queue);
	// ...
}

RIGHT

private void doRightClose(QueueConnectionFactory qconFactory, InitialContext ctx) throws JMSException, NamingException {
	QueueConnection qcon = null;
	QueueSession qsession = null;
	QueueSender qsender = null;
	try {
	        qcon = qconFactory.createQueueConnection();
	        Queue queue = (Queue) ctx.lookup("jms/FooQueue");
	        qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	        qsender = qsession.createSender(queue);
	        // ...
	} finally {
	        if (qsender != null) {
	        qsender.close();
	        }
	        if (qsession != null) {
	        qsession.close();
	        }
	        if (qcon != null) {
	        qcon.close();
	        }
	}
}

JMS_008: Always Close Resources In The Correct Order

The JMS resources must be closed in the correct order:

  1. Producer or Consumer
  2. Session
  3. Connection

See rule [JAC_O68: 3. 4. Java Coding Conventions Rules#JAC_068

JMS_009: Do Not Produce A Message In A Transaction And Rely On It To Be Consumed Before The End Of The Transaction

Sending messages in a transaction is possible. It is important to realize that these messages will not be seen by consumers until the transaction is committed. This means that it is impossible to process replies on the sent messages within the original transaction.

JMS_010: Do Not Rely On JMS To Deliver Message In The Same Order As They Were Sent

When using different JMS sessions for producing and consuming messages, JMS doesn???t guarantee that messages are delivered to the consumer in the same order as they were produced.

If an application wants to consume messages in the same order as they were produced, a sequence number could be attached to each message. Instead of putting them on a JMS destination, they could be stored in a database table. The consumer could then read the messages from the table and sort them by the sequence number, in order to process them in the initial order.

JMS_011: Start A Producer Connection After Start A Consumer

If you start a connection before starting the consumer, then the messages have to wait in the JMS server. This is an unnecessary overhead, so first start consumers and then start the producer connection.

JMS_012: Use A separate Transactional Session For transactional Messages And A Non-transactional Session For Non-transactional Messages

If you want to send 100 messages, and only 10 of them in a transaction, it is better to use a transactional session to send the transactional messages and a non-transactional session to send the non-transactional messages.

JMS_013: Set An Optimal Message Time To Live

Choose an optimal value for the time to live property of a message, to avoid unnecessary memory overhead. By default a message never expires.

JMS_014: Choose A Correct Message Type

The message size depends on the type of message you choose which in turn has an impact on the performance.

JMS_015: Do Not Receive Messages Asynchronously In A Web Component, A Session Bean Or An Entity Bean

Web, session or entity components should only consume messages synchronously using the MessageConsumer???s receive methods, because they are driven by synchronous request-reply protocols, not asynchronous messages.

JMS_016: Do Not Use JMS Sessions In A Multi-threaded Context

JMS sessions were designed for single-threaded use. This is also true for all object created by the session, like producers and consumers.

If a client desires to have one thread producing messages while another thread asynchronously consumes messages at the same time, the client should use a separate session for its producing thread.

It is also forbidden to attempt to combine both synchronous and asynchronous message receiving in the same session. Either the session is dedicated to the thread of control used for delivery to message listeners or it is dedicated to a thread of control initiated by client code.

It is allowed however, to combine producing and consuming messages in the same thread.

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Hosted by JavaLobby
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.5 Build:#520 Jun 27, 2006) - Bug/feature request - Contact Administrators