I have two EJBs, which are described in one ejb-jar.xml. The first one is stateless bean and puts a message in WebSpheres message queue with manually created connection.
@Remote({ Producer.class })
public class ProducerImpl implements Producer, Serializable {
@Override
public boolean send(ObjectNode json) {
try {
Connection connection = queueCF.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage();
message.setText(json.toString());
producer.send(message);
return true;
} catch (JMSException e) {
sysLog.log(...);
return false;
}
}
}
The second one is MDB and reads from that queue.
public class Consumer implements MessageListener {
@Override
public void onMessage (Message message) {
try {
sendToUrl((TextMessage)message);
} catch (JMSException | IOException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
}
}
The ejb-jar.xml looks like this (some env-entry stuff is omitted):
<enterprise-beans>
<session>
<ejb-name>Producer</ejb-name>
<ejb-class>com.example.jms.ProducerImpl</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jms/queue</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<res-ref-name>jms/connectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
<message-driven>
<ejb-name>Consumer</ejb-name>
<mapped-name>jms/queue</mapped-name>
<ejb-class>com.example.Consumer</ejb-class>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationLookup</activation-config-property-name>
<activation-config-property-value>jms/lookup</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
</enterprise-beans>
The issue is that reading from queue exists in the same transaction as writing. Why do I think so? I just tried to call the Producer and it hadn't returned until the Consumer::onMessage had been finished.
I tried to mark Consumer::onMessage with different transaction propagation (NotSupported, RequiresNew, etc) and to make Consumer transaction type "Bean". But everything changed nothing.
So, the question is: can I read from queue within totally separate transaction, so that Producer wouldn't wait for Consumer?