【问题标题】:MQ JNDI exception if the qmanager jndi is defined in multiple tomcat context.xml如果在多个 tomcat context.xml 中定义了 qmanager jndi,则 MQ JNDI 异常
【发布时间】:2015-07-29 21:02:46
【问题描述】:

我在同一个 tomcat jvm 中部署了 2 个应用程序。每个应用程序都有自己的 context.xml: - app1.xml - app2.xml 在每个 app*.xml 中,我定义了 MQ jndi 资源:

<!-- JMS configuration FOR MQSeries - The connection factory -->
 <Resource
      name="jms/JMSQueueConnectionFactory"
      auth="Container"
      type="com.ibm.mq.jms.MQQueueConnectionFactory"
      factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
      description="JMS Queue Connection Factory for sending messages"
      CCDTURL="file:///apps/mqm_opt/creds/AMQCLCHL_XA.TAB"
      QMGR="***Example***QM01***Example***" UCP="Y"/>

我在任何一场战争中都没有 MQ 或 jms 罐子。它们位于 MQ 客户端安装上。然后我使用 catalina.properties 的 shared.loader 在类路径中添加:

shared.loader=${catalina.home}/shared/*.jar,/opt/mqm/java/lib/*.jar

每个应用程序在单独部署时都很好。但是当它们一起部署在同一个 jvm 中时,我在启动其中一个应用程序时得到一个空指针:

Jul 29, 2015 6:15:14 PM org.apache.naming.NamingContext lookup
WARNING: Unexpected exception resolving reference
java.lang.NullPointerException
        at com.ibm.msg.client.jms.internal.JmsFactoryFactoryImpl.getInstance(JmsFactoryFactoryImpl.java:169)
        at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.setProviderFactory(JmsConnectionFactoryImpl.java:176)
        at com.ibm.mq.jms.MQConnectionFactory.<init>(MQConnectionFactory.java:286)
        at com.ibm.mq.jms.MQQueueConnectionFactory.<init>(MQQueueConnectionFactory.java:76)
        at com.ibm.mq.jms.MQQueueConnectionFactoryFactory.getObjectInstance(MQQueueConnectionFactoryFactory.java:73)
        at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:141)
        at javax.naming.spi.NamingManager.getObjectInstance(Unknown Source)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:842)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
        at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
        at javax.naming.InitialContext.lookup(Unknown Source)
        at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
        at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
        at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
        at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
        at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
        at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
        at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)
        at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1545)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1483)

所以 app1 工作正常,但 app2 因上述异常而失败。我通常注意到这种错误是当我们遇到类加载问题时。但在这种情况下,我无法弄清楚问题出在哪里。任何线索都会有所帮助。

编辑:经过一些测试,我想,如果 tomcat 先加载 app1,那么这两个应用程序都可以正常工作。但是如果它选择 app2 那就有问题了。似乎 app2 正在使用错误的类加载器加载 MQ 类。不知道为什么。我已经检查了战争。它不包含 MQ 类。

【问题讨论】:

    标签: tomcat jms jndi ibm-mq spring-jms


    【解决方案1】:

    根据http://tomcat.apache.org/tomcat-8.0-doc/jndi-resources-howto.html#Using_resources 中的注释,我建议使用 TomCat 中的资源 应该沿着这些路线。

    <Resource name="jms/MyJMSCF" auth="Container"
              type="com.ibm.mq.jms.MQConnectionFactory"
              factory="org.apache.naming.factory.BeanFactory"
              hostName="my.host.name"
              transportType="1"/>  <!-- 1 means client mode -->
    

    MQConnectionFactory 应该是兼容的 bean 样式对象;有很多配置选项 - 完整的 JavaDoc 是 http://www-01.ibm.com/support/knowledgecenter/api/content/SSFKSJ_8.0.0/com.ibm.mq.javadoc.doc/WMQJMSClasses/com/ibm/mq/jms/MQConnectionFactory.html

    com.ibm.mq.jms.MQQueueConnectionFactoryFactory 对象仅由 JNDI 用于通过 javax.naming.Referencable 接口重新扩充对象存储。

    【讨论】:

    • 我不确定这如何解决上述问题。我正在使用tomcat7。另外,上面的配置是定义 IBM MQ 连接工厂的推荐方式。
    【解决方案2】:

    最后的编辑给了我线索。经过仔细检查,我意识到我在 app2.war 中打包了一些 MQ jar/类。这就是为什么当首先加载 app2.war 时,它会使用 WebApp2 类加载器加载,而 app1.war 无法访问此类。这就是 app1 无法加载的原因。 虽然 app1.war 没有任何 mq 类。因此,当 app1 首先加载时,MQ 类由两个应用程序都可以访问的系统类加载器加载。
    解决方案显然是从 app2.war 中删除 mq jar

    【讨论】:

      猜你喜欢
      • 2014-02-05
      • 2018-05-16
      • 1970-01-01
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多