答案 0 :(得分:8)
我已就此事与Oracle联系:他们建议不要在无状态会话bean中缓存JMS连接。相反,应该按需获取连接并立即释放。这样做没有性能开销,因为连接句柄是实际物理连接的薄包装(参见Java EE连接器体系结构规范的6.4.3节)。您也可以参考glassfish邮件列表中的this thread来解决类似的问题。
答案 1 :(得分:3)
您的问题在于交易管理。将消息提交到JMS目标后,MDB会在其自己的事务中选择它。这成为一个问题,因为提交消息的会话bean尚未提交它的事务。现在,MDB正在尝试加载不存在的实体。
将提交代码分隔到它自己的类中,并使用bean管理的事务。
答案 2 :(得分:0)
我还遇到了回滚实体事务的JMS问题。我设法使用以下命令修复了新事务:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
在生成消息到队列的EJB上。
所以我的设计是这样的:
制片人:
@Stateless
@LocalBean
// Note here that a new transaction is required for this bean
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class ProducerBean {
@Resource(mappedName = "jms/theQueue")
private Queue theQueue;
@Inject
private JMSContext jmsContext;
private static final Logger logger = LoggerFactory.getLogger(ProducerBean.class);
public void event(TheEvent theEvent) {
// Place the message in the Queue
try {
jmsContext.createProducer().send(theQueue, theEvent);
logger.info("send event|eventName:{}", theEvent.getEventName());
} catch (Exception ex) {
logger.error("Could not send the event|eventName:{}|error:{}", theEvent.getEventName(), ex.getMessage());
}
}
}
我的消费者是这样的:
@MessageDriven(name = "TheConsumer", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/theQueue"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
})
public class TheConsumer implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(TheConsumer.class);
@Override
public void onMessage(Message message) {
try {
doSomething();
} catch (JMSException ex) {
logger.error("JMSException|could not retrieve the object from the message body - reason: {}", ex.getMessage());
}
}
}