我们的应用程序是一个在 Tomcat 中运行的 JAVA 后端应用程序。在较高级别上,它从 IBM MQ 读取输入,对其进行处理,将其保留在 ORACLE DB 中并将输出写入 MQ。这是一个分布式两阶段提交事务世界,Atomikos 充当事务管理器。我们使用 Spring JMS API。目前的设置是我们使用的是 JAVA 11,现在我们正在尝试将应用程序升级到 JAVA 17。
我们使用 org.springframework.jms.connection.CachingConnectionFactory 和 com.atomikos.jms.AtomikosConnectionFactoryBean 作为连接工厂 bean。对于 JAVA 11 中 MQ 消息的每次轮询,都会从 spring-jms jar 中的 org.springframework.jms.core.JmsTemplate.class 打印出以下日志。 “在 JMS 会话上执行回调:缓存的 JMS 会话:com.ibm.mq.jms.MQXAQueueSession@39f839d6”
使用的依赖项: com.ibm.mq.allclient - 7.5.0.0, spring-jms - 5.3.x, Atomikos - 5.0.8(免费版)
现在当我们升级到JAVA 17时,依赖项也升级到最新的兼容版本。
使用的依赖项: com.ibm.mq.jakarta.client - 9.4.0.0, spring-jms - 6.1.5, Atomikos - 6.0.0(免费版)
但是现在,升级后,我们得到的日志为, “在 JMS 会话上执行回调:缓存的 JMS 会话:缓存的 JMS 会话:null”
启用日志跟踪,我们得到,
org.springframework.jms.connection.CachingConnectionFactory - 返回缓存的会话:null org.springframework.jms.connection.CachingConnectionFactory - 找到模式 0 的缓存 JMS 会话:null 在 JMS 会话上执行回调:缓存的 JMS 会话:缓存的 JMS 会话:null org.springframework.jms.connection.CachingConnectionFactory - 找到目标 [queue:///XXXXX] 的缓存 JMS MessageConsumer:atomikosJmsMessageConsumerWrapper for com.ibm.mq.jakarta.jms.MQQueueReceiver@430eac26
我们不允许从本地计算机直接连接到测试队列管理器,因此调试机会有限,我们发现在 JAVA 11 版本的代码中,当我们迭代升级 com.ibm.mq.allclient jar 时,我们发现在 9.2.3.0 之前一切都很好,并且从 9.2.4.0 开始此缓存会话打印为 null 从 9.2.4.0 的更改日志中,我找不到任何可以引发此行为的具体内容,除非这里有 JAVA 17 升级。
谁能给我们一张清晰的图片吗?
更新:25/6/24
让我添加这个额外的信息。我也将 Tomcat 从 9 迁移到 10.1.x,其中包含 servlet 6,因此我必须将所有内容从 jakarta 迁移到 javax。
今天我启用了 IBM mq 客户端 jar 的跟踪,下面是发现的结果。我运行了两个版本的应用程序(当前版本和要升级的版本)
为了简单起见,我只提供重要的日志。 两个日志几乎相同,除了包名称差异和所有重要的突出显示部分之外,两个版本中都发生相同的异常。
应用程序升级版本的IBM MQ跟踪日志:
日志中的重要部分
c.i.m.jakarta.jms.MQXAQueueConnection - } createXAQueueSession() 返回 [null] c.i.m.jakarta.jms.MQXAQueueConnection } createXASession() 返回 [null]
c.i.m.c.w.v.base.internal.MQQueueManager ----+--- } errorOccurred(MQException)
c.i.m.c.w.v.base.internal.MQQueueManager(MQManagedObject) ----+--- ! getString(int,int)<throwIndex 2>, MQJE001: Completion Code '2', Reason '2067'. [com.ibm.mq.MQException]
c.i.m.c.w.v.jms.internal.MQXASession(MQSession) ----+- X <init>(MQConnection,MQQueueManager,boolean,int)<catchIndex 2>
MQJE001: Completion Code '2', Reason '2067'. [com.ibm.mq.MQException] at:
com.ibm.msg.client.jakarta.wmq.compat.base.internal.MQManagedObject.getString(MQManagedObject.java:337)
com.ibm.msg.client.jakarta.wmq.compat.base.internal.MQManagedObject.getAttributeString(MQManagedObject.java:248)
com.ibm.msg.client.jakarta.wmq.compat.jms.internal.MQSession.<init>(MQSession.java:494)
com.ibm.msg.client.jakarta.wmq.compat.jms.internal.MQXASession.<init>(MQXASession.java:128)
com.ibm.msg.client.jakarta.wmq.compat.jms.internal.MQXAConnection.createXASession(MQXAConnection.java:139)
com.ibm.msg.client.jakarta.jms.internal.JmsXAConnectionImpl.createXASession(JmsXAConnectionImpl.java:125)
com.ibm.msg.client.jakarta.jms.internal.JmsXAQueueConnectionImpl.createXAQueueSession(JmsXAQueueConnectionImpl.java:136)
com.ibm.mq.jakarta.jms.MQXAQueueConnection.createXAQueueSession(MQXAQueueConnection.java:87)
com.ibm.mq.jakarta.jms.MQXAQueueConnection.createXASession(MQXAQueueConnection.java:105)
com.atomikos.jms.internal.AtomikosJmsConnectionProxy.createSession(AtomikosJmsConnectionProxy.java:132)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
com.atomikos.util.DynamicProxySupport.callProxiedMethod(DynamicProxySupport.java:164)
com.atomikos.util.DynamicProxySupport.invoke(DynamicProxySupport.java:121)
jdk.proxy4/jdk.proxy4.$Proxy365.createSession(Unknown Source)
org.springframework.jms.connection.SingleConnectionFactory.createSession(SingleConnectionFactory.java:525)
org.springframework.jms.connection.CachingConnectionFactory.getSession(CachingConnectionFactory.java:263)
org.springframework.jms.connection.SingleConnectionFactory$SharedConnectionInvocationHandler.invoke(SingleConnectionFactory.java:705)
jdk.proxy4/jdk.proxy4.$Proxy366.createSession(Unknown Source)
org.springframework.jms.support.JmsAccessor.createSession(JmsAccessor.java:228)
org.springframework.jms.core.JmsTemplate.access$100(JmsTemplate.java:93)
org.springframework.jms.core.JmsTemplate$JmsTemplateResourceFactory.createSession(JmsTemplate.java:1214)
org.springframework.jms.connection.ConnectionFactoryUtils.doGetTransactionalSession(ConnectionFactoryUtils.java:327)
org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:514)
org.springframework.jms.core.JmsTemplate.receiveSelected(JmsTemplate.java:773)
org.springframework.jms.core.JmsTemplate.receive(JmsTemplate.java:749)
com.util.io.jms.JmsTemplateImpl.access$201(JmsTemplateImpl.java:38)
com.util.io.jms.JmsTemplateImpl$5.doAction(JmsTemplateImpl.java:239)
com.util.io.jms.JmsTemplateImpl.executeJmsActionHandler(JmsTemplateImpl.java:348)
com.util.io.jms.JmsTemplateImpl.receive(JmsTemplateImpl.java:229)
com.util.io.jms.JMSInputSource.read(JMSInputSource.java:111)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:392)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
jdk.proxy4/jdk.proxy4.$Proxy361.read(Unknown Source)
com.workflow.SimpleMessageSource.supplyMessage(SimpleMessageSource.java:74)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:392)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
jdk.proxy4/jdk.proxy4.$Proxy362.supplyMessage(Unknown Source)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216)
jdk.proxy4/jdk.proxy4.$Proxy343.getNextMessage(Unknown Source)
jdk.internal.reflect.GeneratedMethodAccessor149.invoke(Unknown Source)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216)
jdk.proxy4/jdk.proxy4.$Proxy343.getNextMessage(Unknown Source)
jdk.internal.reflect.GeneratedMethodAccessor149.invoke(Unknown Source)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:568)
org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:281)
org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:265)
org.springframework.integration.endpoint.MethodInvokingMessageSource.doReceive(MethodInvokingMessageSource.java:113)
org.springframework.integration.endpoint.AbstractMessageSource.receive(AbstractMessageSource.java:142)
org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:212)
org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:443)
org.springframework.integration.endpoint.AbstractPollingEndpoint.pollForMessage(AbstractPollingEndpoint.java:412)
org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$4(AbstractPollingEndpoint.java:348)
org.springframework.integration.util.ErrorHandlingTaskExecutor.lambda$execute$0(ErrorHandlingTaskExecutor.java:57)
org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:55)
org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$5(AbstractPollingEndpoint.java:341)
org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:96)
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
java.base/java.lang.Thread.run(Thread.java:842)
Object ClassLoader = ParallelWebappClassLoader^M
context: <projName>^M
delegate: false^M
----------> Parent Classloader:^M
java.net.URLClassLoader@710726a3^M
[25/06/24 05:15:08.862.0Y] 00000002 CurrentThread ClassLoader = ParallelWebappClassLoader^M
context: <projName>^M
delegate: false^M
----------> Parent Classloader:^M
java.net.URLClassLoader@710726a3^M
c.i.m.c.j.w.c.jms.internal.MQXASession ----+- d Setting QSGName to null <null>
c.i.m.c.j.w.c.jms.internal.MQXASession ----+- d QSGName set to null <null>
c.i.m.c.j.w.c.jms.internal.MQXASession(MQSession) ----+ } <init>(MQConnection,MQQueueManager,boolean,int)
c.i.m.c.j.w.c.jms.internal.MQXASession ----+ { <init>(MQConnection,MQQueueManager,MQSession,JmqiXAResource) [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXAConnection@6320ee8a] [c.i.m.c.jakarta.wmq.compat.base.internal.MQQueueManager@2906bf91] [c.i.m.c.jakarta.wmq.compat.jms.internal.MQSession@6320ee8a] [c.i.mq.jmqi.JmqiXAResource@75b8f7c0]
c.i.m.c.j.w.c.jms.internal.MQXASession(MQSession) ----+- d setQM(MQQueueManager) setter [c.i.m.c.jakarta.wmq.compat.base.internal.MQQueueManager@2906bf91]
c.i.m.c.j.w.c.jms.internal.MQXASession ----+- d com.ibm.msg.client.jakarta.wmq.compat.jms.internal.MQXASession [Set MQXASession resolved variables to those within the session]
c.i.m.c.j.w.c.jms.internal.MQXASession ----+ } <init>(MQConnection,MQQueueManager,MQSession,JmqiXAResource)
c.i.m.c.j.w.c.jms.internal.MQXASession(WMQPropertyContext) ----+ d setPropertyContext(JmsPropertyContext) setter <as-before>
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsPropertyContextImpl) ----+ d setProviderPropertyContext(JmsPropertyContext) setter [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXASession@23d0b7d0]
c.i.m.c.j.w.c.jms.internal.MQXASession(MQSession) ----+ d setDistTransactionMode(int) setter [1(0x1)]
c.i.m.c.j.w.c.jms.internal.MQXAConnection ---- } createXASession(JmsPropertyContext) returns [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXASession@23d0b7d0]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) ---- d setProviderSession(ProviderSession) setter [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXASession@23d0b7d0]
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl(JmsXAConnectionImpl) --- } createXASession() returns <as-before>
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl -- } createXAQueueSession() returns <as-before>
c.i.m.jakarta.jms.MQXAQueueSession(MQSession) -- d setDelegate(JmsSession) setter <as-before>
c.i.m.jakarta.jms.MQXAQueueConnection - } createXAQueueSession() returns [null]
c.i.m.jakarta.jms.MQXAQueueConnection } createXASession() returns [null]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsXASessionImpl) { getXAResource()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) - { checkNotClosed()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) - } checkNotClosed()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) - d getProviderSession() getter [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXASession@23d0b7d0]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsXASessionImpl) - d getProviderXASession() getter [c.i.m.c.jakarta.wmq.compat.jms.internal.MQXASession@23d0b7d0]
c.i.m.c.j.w.c.jms.internal.MQXASession - d getXAResource() getter [c.i.mq.jmqi.JmqiXAResource@75b8f7c0]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsXASessionImpl) } getXAResource() returns [c.i.mq.jmqi.JmqiXAResource@75b8f7c0]
c.i.m.jakarta.jms.MQXAQueueSession(MQXASession) d getXAResource() getter [c.i.mq.jmqi.JmqiXAResource@75b8f7c0]
c.i.m.jakarta.jms.MQXAQueueConnection(MQConnection) { start()
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl(JmsConnectionImpl) - { start()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- { enableMessageReferenceProcessing()
c.i.m.c.j.w.c.jms.internal.MQXASession --- d com.ibm.msg.client.jakarta.wmq.compat.jms.internal.MQSession enableMessageReferenceProcessing() [Message reference processing is always enabled when using MQ messaging provider migration mode, so there is nothing to do here]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- } enableMessageReferenceProcessing()
c.i.m.c.j.w.c.jms.internal.MQXAConnection(MQConnection) -- { start()
c.i.m.c.j.w.c.jms.internal.MQXAConnection(MQConnection) --- { notifyBrowsers()
c.i.m.c.j.w.c.jms.internal.MQXAConnection ---- d notifying 0 browsers of state STARTED <null>
c.i.m.c.j.w.c.jms.internal.MQXAConnection(MQConnection) --- } notifyBrowsers()
c.i.m.c.j.w.c.jms.internal.MQXAConnection(MQConnection) -- } start()
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl(JmsConnectionImpl) -- { fixClientID()
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl(JmsConnectionImpl) -- } fixClientID()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- { start()
c.i.m.c.j.jms.internal.JmsSessionImpl$ReentrantDoubleLock --- { getExclusiveLock()
c.i.m.c.j.jms.internal.JmsSessionImpl$ReentrantDoubleLock --- } getExclusiveLock()
c.i.m.c.j.w.c.jms.internal.MQXASession --- { start()
c.i.m.c.j.w.c.jms.internal.MQXASession(MQSession) ---- { start()
c.i.m.c.j.w.c.jms.internal.MQXASession(MQSession) ---- } start()
c.i.m.c.j.w.c.jms.internal.MQSession ---- { start()
c.i.m.c.j.w.c.jms.internal.MQSession ---- } start()
c.i.m.c.j.w.c.jms.internal.MQXASession --- } start()
c.i.m.c.j.jms.internal.State --- d setState(int) setter [1(0x1)]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) --- f start()
c.i.m.c.j.jms.internal.JmsSessionImpl$ReentrantDoubleLock --- { unlockExclusiveLock()
c.i.m.c.j.jms.internal.JmsSessionImpl$ReentrantDoubleLock --- } unlockExclusiveLock()
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- } start()
c.i.m.c.j.jms.internal.State -- d setState(int) setter [1(0x1)]
c.i.m.c.j.jms.internal.JmsXAQueueConnectionImpl(JmsConnectionImpl) - } start()
c.i.m.jakarta.jms.MQXAQueueConnection(MQConnection) } start()
c.i.m.jakarta.jms.MQXAQueueSession(MQSession) { createQueue(String) [XXXXX]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) - { createQueue(String) [XXXXX]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- { checkSynchronousUsage(String) [createQueue]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) --- d isAsync() getter [false]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- } checkSynchronousUsage(String)
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- { checkQueueDomain(String) [createQueue]
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- } checkQueueDomain(String)
c.i.m.c.j.jms.internal.JmsXAQueueSessionImpl(JmsSessionImpl) -- d isAsync() getter [false]
但是当前版本应用程序的突出显示日志如下所示。
c.i.mq.jms.MQXAQueueConnection - } createXAQueueSession() 返回 [c.i.mq.jms.MQXAQueueSession@69526d8f] c.i.mq.jms.MQXAQueueConnection } createXASession() 返回 [c.i.mq.jms.MQXAQueueSession@69526d8f]
这个对象似乎正是在应用程序日志中打印出来的对象。
在 JMS 会话上执行回调:缓存的 JMS 会话:com.ibm.mq.jms.MQXAQueueSession@69526d8f
如上所述,这种差异不会导致读取或写入消息时出现任何问题,但我们永远不知道它会在生产中带来什么。
当我们将 SVRCONN 通道的 SHARECNV 属性从 0 更改为默认值 10 时,事情按预期进行。但不确定原因和背景。