I am using Java Enterprise (3.1) with Glassfish. I have two seperate EARs which are communicating synchronously via JMS. More specifically:
EAR1 uses JMS messaging to tell EAR2 what to do. EAR1 starts to listen for an answer from EAR2 (QueueReceiver.receive). EAR2 receives the message and does some processing accordingly and then sends a JMS message back to EAR1 with the output.
All this works fine. Until I get this exception:
[#|2011-05-10T15:05:27.382+0200|WARNING|glassfish3.1|javax.enterprise.resource.resourceadapter.com.sun.enterprise.connectors|_ThreadID=90;_ThreadName=Thread-1;|RAR5117 : Failed to obtain/create connection from connection pool [ jms/QueueConnectionFactory ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections.|#]
So it seems like the container doesnt reuse MDBs. Instead it creates new ones until I reach the limit. I know the reason for this is because the MDBs in EAR2 are using JMS to send back the results. My guess is that there are still some resources allocated in the MDB instance which causes the behaviour.
If I just use the MDBs to print out the message received I can continue sending messages all day long, so it is definately related to the JMS connection.
I have been at this for two days now, so if anyone cares to offer some help, it would be greatly appreciated.
this code works all day long:
package xxx;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName="destinationType",
propertyValue="javax.jms.Queue")
}, mappedName = "AssociationQueue1")
public class AssociationMDB implements MessageListener {
@Override
public void onMessage(Message arg0) {
MapMessage msg = (MapMessage)arg0;
String source = null;
String target = null;
try {
source = msg.getString("source");
target = msg.getString("target");
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println(source + " " + target);
}
}
While this one doesnt:
package xxx;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName="destinationType",
propertyValue="javax.jms.Queue")
}, mappedName = "AssociationQueue1")
public class AssociationMDB implements MessageListener {
@Override
public void onMessage(Message arg0) {
Logger logger = Logger.getLogger(this.getClass().getSimpleName());
QueueConnection qConnect = null;
QueueSession qSession = null;
QueueSender qSender = null;
try {
InitialContext context = new InitialContext();
Queue responseQ = (Queue)context.lookup("AssociationQueue2");
QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("jms/QueueConnectionFactory");
qConnect = factory.createQueueConnection();
qSession = qConnect.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
qConnect.start();
qSender = qSession.createSender(responseQ);
TextMessage answer = qSession.createTextMessage();
answer.setText("hey");
qSender.send(answer);
logger.info("message sent");
}
catch (JMSException jmse) {
jmse.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
finally {
try {
if(qSender != null) {
qSender.close();
logger.info("cleaning qSender");
}
if(qSession != null) {
qSession.close();
logger.info("cleaning qSession");
}
if(qConnect != null) {
qConnect.close();
logger.info("cleaning qConnect");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
(I have also tried using newer more fancy EJB stuff like notations and so but didnt work either...)
Sebastian