We are using Message Driven Bean to
- get the message from a Queue
- process it
- and Produce the processed messages to a Queue
This question is regarding producing message from a Message Driven Bean
In the Sun Java System App Server 9.1 performance tunning guide's "Tuning Message-Driven Beans" section it is mentioned
http://docs.sun.com/app/docs/doc/819-3681/abebw?a=view
[u][b]Caution[/b][/u]:
Previous to version 8.1, it was possible to reuse a connection with a servlet or EJB component.That is, the servlet could call getConnection() in its init() method and then continually call getSession() for each servlet invocation. If you use JMS within a global transaction, that no longer works: [i]applications can only call getSession() once for each connection.[/i] After than, the connection must be closed (which doesn’t actually close the connection; it merely returns it to the pool). This is a general feature of portable J2EE 1.4 applications; the Sun Java System
Application Server enforces that restriction where previous (J2EE 1.3-based) application servers did not.
and also in the next paragraph "[u][b]Limit Use of JMS Connections[/b][/u]"
When designing an application that uses JMS connections make sure you use a methodology that sparingly uses connections, by either pooling them or using the same connection for multiple sessions.
[u][b]The above two seem contradictory[/b][/u].
In our scenario what would be the best suited option to produce a message from MDB:
1. create a static connection object from the QueueConnectionFactory in the ejbCreate() method
put a synchronised lock on it and use this in all the instances of the Bean to create QueueSession
instance level declarations
@Resource(mappedName = "jms/ConnectionFactory")
private QueueConnectionFactory queueConnectionFactory;
private static QueueConnection queueConnection = null;
private static Object lockCon = new Object();
private static Object lockSession = new Object();
in ejbCreate()
synchronized(lockCon){
if(queueConnection == null){
queueConnection = queueConnectionFactory.createQueueConnection();
queueConnection.start();
}
}
while producing the message on to the queue
synchronized(lockSession){
qSession = queueConnection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
}
[b]Advantage[/b]:
- we are just using one connection per application.
- recommended approach in the "Limit Use of JMS Connections" section
[b]Disadvantage[/b]:
- connection is not pooled and contradicts the caution statement.
- In this approach we see few of the messages getting orphaned on the "mq.sys.dmq" queue
- where and when do we close the connection as it is shared by all the instances.
2. create a new connection(non static) object from the QueueConnectionFactory in the ejbCreate() and close the connection in the ejbRemove()
[u][b]Advantage[/b][/u]:
- we do not get any orphaned messages on the "mq.sys.dmq" queue.
- appears to perform better than #1 approach
[u][b]Disadvantage[/b][/u]:
- the bean hangs on to the connection till its instance is created.So not a very efficient use of Connection Pooling
3. create a connection object in the onMessage() get a session out of it produce message and close the connection in the finally.
[b]Advantage[/b]:
- onMessage always gets a refreshed connection from the QueueConnectionFactory.
[b]Disadvantage[/b]:
- contradicts the statement in the "Limit Use of JMS Connections" block.
Please suggest what should be the best approach. we need lot of processing through put in this system.
[Message sent by forum member 'singhrvijay2007' (singhrvijay2007)]
http://forums.java.net/jive/thread.jspa?messageID=240497