Payara中从DLQ重发消息时触发javax.jms.IllegalStateException异常
问题:Payara中JMS事务Session提交时抛出非事务Session异常
我在使用Payara 5.2022.5开发,编写了从死信队列(DLQ)重发消息到主队列的代码,预期创建事务性Session并提交操作,但运行时抛出异常:javax.jms.IllegalStateException: MQJMSRA_DS4001: commit():Illegal for a non-transacted Session。
相关代码如下:
public void resubmitMessages(boolean resubmitAll) throws Exception { log.debug("DLQService: resubmitMessages()"); InitialContext ctx = null; QueueConnectionFactory connectionFactory; QueueConnection queueConn = null; try { ctx = new InitialContext(); connectionFactory = (QueueConnectionFactory) ctx.lookup("jms/ConnectionFactory"); queueConn = connectionFactory.createQueueConnection(); queueConn.start(); Session session = queueConn.createSession(true, Session.SESSION_TRANSACTED); assert session.getTransacted(); Queue clsQueue = (Queue) ctx.lookup("queue/main"); MessageProducer sender = session.createProducer(clsQueue); assert session.getTransacted(); Queue dlq = (Queue) ctx.lookup("queue/mq.sys.dmq"); MessageConsumer dlqConsumer = session.createConsumer(dlq); assert session.getTransacted(); Message message; while ((message = dlqConsumer.receive(1000)) != null) { try { log.debug("Processing: " + ((ObjectMessage) message).getObject()); assert session.getTransacted(); sender.send(message); assert session.getTransacted(); session.commit(); log.debug("resubmitted successfully to main queue from dlq"); } catch (Exception jmse) { log.error("Exception caught while resubmitting message to main queue", jmse); session.rollback(); throw jmse; } } } catch (Exception e) { log.error("Exception caught while sending message", e); throw e; } finally { cleanUp(ctx, queueConn); } }
完整栈追踪:
09 Nov 2024 08:26:39,160 ERROR [DLQService] Exception caught while resubmitting message to main queue javax.jms.IllegalStateException: MQJMSRA_DS4001: commit():Illegal for a non-transacted Session:sessionId=7622785546896845312 at com.sun.messaging.jms.ra.DirectSession._checkTransactedState(DirectSession.java:1015) ~[imqjmsra.jar:?] at com.sun.messaging.jms.ra.DirectSession.commit(DirectSession.java:242) ~[imqjmsra.jar:?] at com.crlcorp.cls.toxde.services.DLQService.resubmitMessages(DLQService.java:124) [toxde-ejb-7.1.3-SNAPSHOT_jar/:?] at com.crlcorp.cls.toxde.sessionbeans.ToxDataEntrySessionBean.resubmitDLQMessages(ToxDataEntrySessionBean.java:462) [toxde-ejb-7.1.3-SNAPSHOT_jar/:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_345] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_345] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_345] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_345] at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:588) [ejb-container.jar:?] at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:408) [ejb-container.jar:?] at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4835) [ejb-container.jar:?] at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:665) [ejb-container.jar:?] at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:834) [ejb-container.jar:?] at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:615) [ejb-container.jar:?] at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163) [ejb-container.jar:?] at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140) [ejb-container.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_345] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_345] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_345] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_345] at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:888) [ejb-container.jar:?] at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:833) [ejb-container.jar:?] at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:375) [ejb-container.jar:?] at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4807) [ejb-container.jar:?] at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4795) [ejb-container.jar:?] at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:205) [ejb-container.jar:?] at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:123) [ejb-container.jar:?] at com.sun.proxy.$Proxy408.resubmitDLQMessages(Unknown Source) [?:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_345] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_345] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_345] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_345] at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:229) [glassfish-corba-orb.jar:?] at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:140) [glassfish-corba-orb.jar:?] at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:226) [glassfish-corba-orb.jar:?] at com.crlcorp.cls.toxde.ejb._ToxDataEntryRemote_DynamicStub.resubmitDLQMessages(com/crlcorp/cls/toxde/ejb/_ToxDataEntryRemote_DynamicStub.java) [?:?] at com.crlcorp.cls.toxde.form.controller.DLQController.resubmitDLQMessages(DLQController.java:38) [DLQController.class:?] at com.crlcorp.cls.toxde.form.DLQForm.resubmitMessage(DLQForm.java:55) [DLQForm.class:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_345] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_345] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_345] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_345] at com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:160) [jakarta.el.jar:3.0.4.payara-p1] at com.sun.el.parser.AstValue.invoke(AstValue.java:261) [jakarta.el.jar:3.0.4.payara-p1] at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:237) [jakarta.el.jar:3.0.4.payara-p1] at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) [weld-osgi-bundle.jar:3.1.9.Final] at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-osgi-bundle.jar:3.1.9.Final] at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) [weld-osgi-bundle.jar:3.1.9.Final] at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-osgi-bundle.jar:3.1.9.Final] at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) [weld-osgi-bundle.jar:3.1.9.Final] at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-osgi-bundle.jar:3.1.9.Final] at com.sun.faces.application.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:66) [jakarta.faces.jar:2.3.14.payara-p3] at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63) [myfaces-all-1.1.1.jar:?] at javax.faces.component.UICommand.broadcast(UICommand.java:222) [jakarta.faces.jar:2.3.14.payara-p3] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:847) [jakarta.faces.jar:2.3.14.payara-p3] at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:1012) [jakarta.faces.jar:2.3.14.payara-p3] at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:55) [jakarta.faces.jar:2.3.14.payara-p3] at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:76) [jakarta.faces.jar:2.3.14.payara-p3] at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:177) [jakarta.faces.jar:2.3.14.payara-p3] at javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:707) [jakarta.faces.jar:2.3.14.payara-p3] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:451) [jakarta.faces.jar:2.3.14.payara-p3] at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1637) [web-core.jar:?] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:259) [web-core.jar:?] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:167) [web-core.jar:?] at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:757) [web-core.jar:?] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:577) [web-core.jar:?] at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) [web-glue.jar:?] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158) [web-core.jar:?] at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:372) [web-core.jar:?] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:239) [web-core.jar:?] at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:520) [kernel.jar:?] at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:217) [kernel.jar:?] at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:182) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:156) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:201) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:95) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:260) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:177) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:109) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:88) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:53) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:524) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:89) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:94) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:33) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:114) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:569) [nucleus-grizzly-all.jar:?] at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:549) [nucleus-grizzly-all.jar:?]
解决方案
核心原因
容器托管的JMS连接工厂会忽略手动设置的事务属性。由于代码运行在EJB容器中,默认情况下JMS连接会被纳入全局JTA事务管理,此时手动创建的事务Session会被容器强制转换为非事务Session,调用commit()自然会报错。
方法1:依赖容器管理事务,移除手动提交/回滚
既然容器已经接管JTA事务,无需手动调用commit()和rollback(),修改代码如下:
public void resubmitMessages(boolean resubmitAll) throws Exception { log.debug("DLQService: resubmitMessages()"); InitialContext ctx = null; QueueConnectionFactory connectionFactory; QueueConnection queueConn = null; try { ctx = new InitialContext(); connectionFactory = (QueueConnectionFactory) ctx.lookup("jms/ConnectionFactory"); queueConn = connectionFactory.createQueueConnection(); queueConn.start(); // 创建非事务Session,由容器管理JTA事务 Session session = queueConn.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue clsQueue = (Queue) ctx.lookup("queue/main"); MessageProducer sender = session.createProducer(clsQueue);
相关产品推荐
相关产品推荐

