我有以下无状态bean
@Local(MessageDispatcher.class)
@Stateless
public class MessageDispatcherImpl implements MessageDispatcher {
private static final Logger log = LoggerFactory.getLogger(MessageDispatcher.class);
@Resource(name = "java:/jms/queue/outgoing")
private Queue outgoingQueue;
@Inject
private JMSContext jms;
private JMSProducer jmsProducer;
@PostConstruct
public void postConstruct() {
log.info("Initializing message dispatcher");
jmsProducer = jms.createProducer();
}
@Override
public void publishToJms(Message message) throws JMSException {
jmsProducer.send(outgoingQueue, message);
}
}
它负责为其他bean提供将消息发布到特定队列的能力。它不需要在呼叫期间保持其状态,也不需要保持对话状态"与客户,因此选择无状态豆。
但是,当调用方法publishToJms
时,我得到以下运行时错误:
ERROR [org.jboss.as.ejb3.invocation] (MQTT Call: xyz) WFLYEJB0034: EJB Invocation failed on component MessageDispatcherImpl for method public default void com.xyz.MessageDispatcherImpl.publishToJms(java.lang.String,byte[]) throws javax.jms.JMSException: javax.ejb.EJBException: javax.jms.IllegalStateRuntimeException: The session is closed
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:187)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:277)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:327)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636)
at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195)
at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73)
at com.togather.messaging.mqtt.MqttToJmsBridge$$$view8.publishToJms(Unknown Source)
at com.togather.messaging.mqtt.impl.TogatherMqttClientImpl.read(TogatherMqttClientImpl.java:150)
at com.togather.messaging.mqtt.impl.TogatherMqttClientImpl.messageArrived(TogatherMqttClientImpl.java:188)
at org.eclipse.paho.client.mqttv3.internal.CommsCallback.handleMessage(CommsCallback.java:354)
at org.eclipse.paho.client.mqttv3.internal.CommsCallback.run(CommsCallback.java:162)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.jms.IllegalStateRuntimeException: The session is closed
at org.apache.activemq.artemis.jms.client.JmsExceptionUtils.convertToRuntimeException(JmsExceptionUtils.java:59)
at org.apache.activemq.artemis.jms.client.ActiveMQJMSContext.createObjectMessage(ActiveMQJMSContext.java:302)
at org.apache.activemq.artemis.jms.client.ActiveMQJMSProducer.send(ActiveMQJMSProducer.java:196)
at com.togather.messaging.mqtt.impl.MqttToJmsBridgeImpl.publishToJms(MqttToJmsBridgeImpl.java:61)
at com.togather.messaging.mqtt.MqttToJmsBridge.publishToJms(MqttToJmsBridge.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82)
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93)
at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:73)
at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(PooledInstanceInterceptor.java:51)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275)
... 38 more
Caused by: javax.jms.IllegalStateException: The session is closed
at org.apache.activemq.artemis.ra.ActiveMQRASession.getSessionInternal(ActiveMQRASession.java:1575)
at org.apache.activemq.artemis.ra.ActiveMQRASession.createObjectMessage(ActiveMQRASession.java:234)
at org.apache.activemq.artemis.jms.client.ActiveMQJMSContext.createObjectMessage(ActiveMQJMSContext.java:299)
... 70 more
我发现解决这个错误的两倍:
首先是制作bean stateful
。
第二种方法是稍微改变方法publishToJms
,以便每次都设置jmsProducer
,就像那样
public void publishToJms(MqttBridgeMessage bridgeMessage) throws JMSException {
JMSProducer jmsProducer = jms.createProducer();
jmsProducer.send(mqttIncomingMessageBridgeQueue, bridgeMessage);
}
我的问题是:这种行为有望吗?如果是这样,任何人都可以向我解释错误发生的原因,或者将我指向网络上的资源吗?
答案 0 :(得分:1)
使用@PostConstruct
注释的方法在未指定的事务上下文中运行。现在,JMS规范中有这样的描述:
4.4.1关闭会话由于提供程序可能代表JVM外部的会话分配一些资源,因此客户端应在关闭时关闭它们。 他们不需要。最终依靠垃圾收集 回收这些资源可能不够及时。同样如此 会话创建的MessageProducers和MessageConsumers。
因此,在@PostConstruct
方法中的事务可能在执行此类方法之后结束,并且正在使用的类型事务管理是容器的事务管理时,在post构造之后关闭会话是非常合适的。