[
https://issues.jboss.org/browse/WFLY-9529?page=com.atlassian.jira.plugin....
]
Peter Schulz edited comment on WFLY-9529 at 2/13/19 5:58 AM:
-------------------------------------------------------------
Hi,
I just ran into the same issue and started digging further and found the answer in [Kohei
Nozaki's blog
post|https://nozaki.me/roller/kyle/entry/in-container-jms-consumer-producer]:
The bean which gets {{JMSContext}} injected *must be an EJB*, since the
"missing" component {{java:comp/TransactionSynchronizationRegistry}} is only
known inside the EJB wildfly-module.
{code:java}
import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.jms.BytesMessage;
import javax.jms.CompletionListener;
import javax.jms.DeliveryMode;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSProducer;
import javax.jms.Message;
import javax.jms.Queue;
import org.slf4j.Logger;
/**
* See
https://nozaki.me/roller/kyle/entry/in-container-jms-consumer-producer
*/
@Stateless
@LocalBean
public class MessageProducer {
@Inject
private Logger logger;
@Inject
@JMSConnectionFactory("java:/ConnectionFactory")
private JMSContext context;
@Resource(name = "java:/jms/queue/requestQueue")
private Queue queue;
private CompletionListener completionListener = new CompletionListener() {
@Override
public void onCompletion(Message message) {
logger.debug("delivered message");
}
@Override
public void onException(Message message, Exception exception) {
logger.warn("failed to deliver message", exception);
}
};
public void enqueue(Request request) {
try {
createProducer().send(queue, convert(request));
} catch (JMSException e) {
logger.error("failed to create message/convert request " + request,
e);
}
}
private JMSProducer createProducer() {
JMSProducer producer = context.createProducer();
producer.setJMSCorrelationID("SEQUENTIAL_REQUEST");
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
producer.setDisableMessageTimestamp(false);
producer.setDisableMessageID(false);
producer.setAsync(completionListener);
producer.setTimeToLive(0);
return producer;
}
private BytesMessage convert(Request request) throws JMSException {
// ...
}
}
{code}
was (Author: schulzp):
Hi,
I just ran into the same issue and started digging deeper:
The bean which gets {{JMSContext}} injected *must be an EJB*, since the
"missing" component {{java:comp/TransactionSynchronizationRegistry}} is only
known inside the EJB wildfly-module.
{code:java}
import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.jms.BytesMessage;
import javax.jms.CompletionListener;
import javax.jms.DeliveryMode;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSProducer;
import javax.jms.Message;
import javax.jms.Queue;
import org.slf4j.Logger;
/**
* See
https://nozaki.me/roller/kyle/entry/in-container-jms-consumer-producer
*/
@Stateless
@LocalBean
public class MessageProducer {
@Inject
private Logger logger;
@Inject
@JMSConnectionFactory("java:/ConnectionFactory")
private JMSContext context;
@Resource(name = "java:/jms/queue/requestQueue")
private Queue queue;
private CompletionListener completionListener = new CompletionListener() {
@Override
public void onCompletion(Message message) {
logger.debug("delivered message");
}
@Override
public void onException(Message message, Exception exception) {
logger.warn("failed to deliver message", exception);
}
};
public void enqueue(Request request) {
try {
createProducer().send(queue, convert(request));
} catch (JMSException e) {
logger.error("failed to create message/convert request " + request,
e);
}
}
private JMSProducer createProducer() {
JMSProducer producer = context.createProducer();
producer.setJMSCorrelationID("SEQUENTIAL_REQUEST");
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
producer.setDisableMessageTimestamp(false);
producer.setDisableMessageID(false);
producer.setAsync(completionListener);
producer.setTimeToLive(0);
return producer;
}
private BytesMessage convert(Request request) throws JMSException {
// ...
}
}
{code}
Using injected JMS in a background task/thread leads to
NameNotFoundException: java:comp/TransactionSynchronizationRegistry
---------------------------------------------------------------------------------------------------------------------------
Key: WFLY-9529
URL:
https://issues.jboss.org/browse/WFLY-9529
Project: WildFly
Issue Type: Bug
Components: CDI / Weld, JMS, Naming
Affects Versions: 14.0.1.Final, 10.1.0.Final, 11.0.0.Final, 12.0.0.Final,
13.0.0.Final
Environment: Running on Windows 10, Java 64-bit 1.8.0_131
Reporter: Scott Van Wart
Assignee: Eduardo Martins
Priority: Major
Labels: ActiveMQ, jms, transaction
Attachments: injected-jms.zip, injected-jms2.zip, wildfly-11-injected-jms.txt
If I try to use an @Injected JMSContext while executing within a background task
(ManagedExecutorService) or thread (ManagedThreadFactory), I get the attached stacktrace.
I've experienced this a number of times with Wildfly 10.1.0, including messages sent
in Infinispan's expiry task thread.
My original workaround was to submit an additional task on a separate thread to send the
message, then wait for it to complete. That seemed unreliable (sometimes it would still
produce NameNotFoundException). I've resorted to creating my own JMSContext by using
@Resource( lookup="java:/ConnectionFactory" ) and sending messages that way.
Both workarounds prevent the message sending logic from participating in any ongoing
transactions.
I'm also attaching a sample EAR project. It can be built with Maven. It creates a
background task that waits 3 seconds and then tries to send a JMS message in a new
transaction using an injected JMS context. I use the standalone-full.xml profile to run
it.
--
This message was sent by Atlassian Jira
(v7.12.1#712002)