JMS队列资源在无状态bean中

时间:2016-02-24 19:46:54

标签: jms ejb-3.1 java-ee-7

我有以下无状态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);
}

我的问题是:这种行为有望吗?如果是这样,任何人都可以向我解释错误发生的原因,或者将我指向网络上的资源吗?

1 个答案:

答案 0 :(得分:1)

使用@PostConstruct注释的方法在未指定的事务上下文中运行。现在,JMS规范中有这样的描述:

  

4.4.1关闭会话由于提供程序可能代表JVM外部的会话分配一些资源,因此客户端应在关闭时关闭它们。   他们不需要。最终依靠垃圾收集   回收这些资源可能不够及时。同样如此   会话创建的MessageProducers和MessageConsumers。

因此,在@PostConstruct方法中的事务可能在执行此类方法之后结束,并且正在使用的类型事务管理是容器的事务管理时,在post构造之后关闭会话是非常合适的。