无状态 bean 中的 JMS 队列资源
JMS queue resource in a stateless bean
我有以下无状态 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 提供将消息发布到特定队列的能力。它不需要跨调用保持其状态,也不需要与客户端保持 "conversational state",因此选择无状态 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.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.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.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
我找到了解决此错误的两种方法:
首先是做beanstateful
.
第二个是稍微改变方法 publishToJms
每次都实例化 jmsProducer
,就像那样
public void publishToJms(MqttBridgeMessage bridgeMessage) throws JMSException {
JMSProducer jmsProducer = jms.createProducer();
jmsProducer.send(mqttIncomingMessageBridgeQueue, bridgeMessage);
}
我的问题是:这种行为是预期的吗?如果是这样,任何人都可以向我解释错误发生的原因,或者指向网络上的资源吗?
在未指定的事务上下文中用 @PostConstruct
运行 注释的方法。现在,JMS 规范中有这样的描述:
4.4.1 Closing a Session Since a provider may allocate some resources on behalf of a session outside the JVM, clients should close them when
they are not needed. Relying on garbage collection to eventually
reclaim these resources may not be timely enough. The same is true for
the MessageProducers and MessageConsumers created by a session.
因此,在 post 构造之后关闭会话是非常合适的,因为 @PostConstruct
方法中的事务可能会在此类方法执行后结束,并且正在使用的类型事务管理是容器的。
我有以下无状态 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 提供将消息发布到特定队列的能力。它不需要跨调用保持其状态,也不需要与客户端保持 "conversational state",因此选择无状态 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.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.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.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
我找到了解决此错误的两种方法:
首先是做beanstateful
.
第二个是稍微改变方法 publishToJms
每次都实例化 jmsProducer
,就像那样
public void publishToJms(MqttBridgeMessage bridgeMessage) throws JMSException {
JMSProducer jmsProducer = jms.createProducer();
jmsProducer.send(mqttIncomingMessageBridgeQueue, bridgeMessage);
}
我的问题是:这种行为是预期的吗?如果是这样,任何人都可以向我解释错误发生的原因,或者指向网络上的资源吗?
在未指定的事务上下文中用 @PostConstruct
运行 注释的方法。现在,JMS 规范中有这样的描述:
4.4.1 Closing a Session Since a provider may allocate some resources on behalf of a session outside the JVM, clients should close them when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough. The same is true for the MessageProducers and MessageConsumers created by a session.
因此,在 post 构造之后关闭会话是非常合适的,因为 @PostConstruct
方法中的事务可能会在此类方法执行后结束,并且正在使用的类型事务管理是容器的。