【问题标题】:How to connect a Glassfish client to Glassfish JMS server when thread creation is not allowed?不允许创建线程时如何将 Glassfish 客户端连接到 Glassfish JMS 服务器?
【发布时间】:2012-06-01 15:31:35
【问题描述】:

我有一个应用程序,其中客户端组件在“托管”环境中运行(作为 Adob​​e InDesign 插件)。在这种“托管”环境中,似乎不可能在执行期间创建线程,而只能在应用程序启动时创建。

这个客户端组件通过 JNDI 和 RMI/IIOP 连接到 Glassfish 服务器,以执行各种 EJB 方法调用,所有这些都可以完美运行(除了一些在这里不重要的繁琐CORBA serialization issues)。我想让它也使用 JMS 连接,以执行一些主题阅读。我用来执行这些主题阅读的代码已经在单元测试中,确保它可以启动、阅读主题并执行所需的集成(这更像是一个集成测试而不是单元测试,但我必须确定我的应用程序通信层,不是吗?)。这段代码在单元测试中运行时可以完美运行。不幸的是,当从我的客户端组件(嵌入在 Indesign 中,并且无法创建线程)运行时,它会以 NullPointerException 以下方式失败:

29 mai 2012 18:07:22 com.sun.enterprise.connectors.ActiveRAFactory getActiveRA
INFO: Deployed RAR [ jmsra ] has inbound artifacts, but the runtime does not support it. Providing only outbound support 
29 mai 2012 18:07:22 org.hibernate.validator.util.Version <clinit>
INFO: Hibernate Validator 4.2.0.Final
29 mai 2012 18:07:24 com.sun.messaging.jms.ra.ResourceAdapter start
INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter: Version:  4.5  (Build 29-b) Compile:  Wed Feb  9 22:53:30 PST 2011
29 mai 2012 18:07:24 com.sun.messaging.jms.ra.ResourceAdapter start
INFO: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter starting: broker is EMBEDDED, connection mode is Direct
29 mai 2012 18:12:58 com.sun.messaging.jms.blc.LifecycleManagedBroker start
GRAVE: MQJMSRA_RA4001: start:Aborting:Exception starting EMBEDDED broker=java.lang.NullPointerException
29 mai 2012 18:12:58 com.sun.messaging.jms.blc.LifecycleManagedBroker start
INFO: SJSMQ LifecycleManagedBroker configuration=
    brokerInstanceName       =imqbroker
    brokerBindAddress        =null
    brokerPort               =7676
    brokerHomeDir            =C:\Java-ext\glassfish3\mq
    brokerLibDir             =C:\Java-ext\glassfish3\mq\lib
    brokerVarDir             =C:\Java-ext\glassfish3\glassfish\domains\autocat\imq
    brokerJavaDir            =C:\Program Files\Java\jdk1.6.0_30\jre
    brokerArgs               =null
    MasterBroker             =null
    brokerId                 =null
    adminUsername            =admin
    adminPassword            =<default>
    adminPassFile            =null
    ConnectionURL            =mq://localhost:7676/
    dbType                   =null
    dbProps                  ={}
    dsProps                  ={}
    useJNDIRmiServiceURL     =true
    useSSLJMXConnector       =true
    brokerEnableHA           =false
    clusterId                =null
    rmiRegistryPort          =7776
    startRmiRegistry         =true
    brokerStartTimeout       =  jmxServiceURL            =null
60000

29 mai 2012 18:12:58 com.sun.enterprise.connectors.ActiveOutboundResourceAdapter init
GRAVE: RAR6035 : Resource adapter start failed. 
javax.resource.spi.ResourceAdapterInternalException: MQJMSRA_RA4001: start:Aborting:Exception starting EMBEDDED broker=java.lang.NullPointerException
    at com.sun.messaging.jms.blc.LifecycleManagedBroker.start(LifecycleManagedBroker.java:458)
    at com.sun.messaging.jms.ra.ResourceAdapter.start(ResourceAdapter.java:380)
    at com.sun.enterprise.connectors.ActiveOutboundResourceAdapter.startResourceAdapter(ActiveOutboundResourceAdapter.java:182)
    at com.sun.enterprise.connectors.ActiveOutboundResourceAdapter.init(ActiveOutboundResourceAdapter.java:129)
    at com.sun.enterprise.connectors.ActiveRAFactory.instantiateActiveResourceAdapter(ActiveRAFactory.java:135)
    at com.sun.enterprise.connectors.ActiveRAFactory.createActiveResourceAdapter(ActiveRAFactory.java:106)
    at com.sun.enterprise.connectors.service.ResourceAdapterAdminServiceImpl.createActiveResourceAdapter(ResourceAdapterAdminServiceImpl.java:212)
    at com.sun.enterprise.connectors.ConnectorRuntime.createActiveResourceAdapter(ConnectorRuntime.java:379)
    at com.sun.enterprise.resource.naming.AdministeredObjectFactory.getObjectInstance(AdministeredObjectFactory.java:107)
    at javax.naming.spi.NamingManager.getObjectInstance(Unknown Source)
    at com.sun.enterprise.naming.impl.SerialContext.getObjectInstance(SerialContext.java:556)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:514)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at fr.perigee.autocat.indesign.remoting.jndi.jms.AdapterJMSListener.getConsumer(AdapterJMSListener.java:261)
    at fr.perigee.autocat.indesign.remoting.jndi.jms.AdapterJMSListener$AdapterJMSListenerRunnable.run(AdapterJMSListener.java:50)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
    at com.sun.messaging.jmq.jmsclient.runtime.impl.BrokerInstanceImpl.start(BrokerInstanceImpl.java:211)
    at com.sun.messaging.jms.blc.EmbeddedBrokerRunner.start(EmbeddedBrokerRunner.java:331)
    at com.sun.messaging.jms.blc.LifecycleManagedBroker.start(LifecycleManagedBroker.java:454)
    ... 24 more
Caused by: java.lang.NullPointerException
    at com.sun.messaging.jmq.jmsserver.data.TransactionList.<init>(TransactionList.java:182)
    at com.sun.messaging.jmq.jmsserver.Broker._start(Broker.java:1170)
    at com.sun.messaging.jmq.jmsserver.Broker.start(Broker.java:456)
    at com.sun.messaging.jmq.jmsserver.BrokerProcess.start(BrokerProcess.java:164)
    at com.sun.messaging.jmq.jmsserver.DirectBrokerProcess.start(DirectBrokerProcess.java:92)
    at com.sun.messaging.jmq.jmsclient.runtime.impl.BrokerInstanceImpl.start(BrokerInstanceImpl.java:206)
    ... 26 more

从我目前发现的情况来看,客户端代码获得了到 JMS 服务器的连接(连接到 mq://localhost://7676),但随后无法启动 TransactionList。未编译的源代码(感谢 Jad!)表明它在那里失败了:

    /* 182*/Globals.getClusterManager().addEventListener(((ClusterListener) (this)));

尝试调试时,我还发现我的客户端无法启动org.glassfish.enterprise.iiop.util.S1ASThreadPoolManager,因为同样无法创建线程。

我猜有些地方出了问题,但是什么?我不知道。

那么,我如何告诉 glassfish 客户端环境线程只能从我的个人线程池(在应用程序启动时创建)中获取,而不是尝试创建自己的线程池并惨遭失败?

【问题讨论】:

    标签: java glassfish client jms threadpool


    【解决方案1】:

    短版

    我使用 maven 部署了我的应用程序,忘记了 Glassfish 的 jms-core.jar,因为它是 gf-client-module.jarruntime 依赖项,而我的 maven 构建只复制了 compile 依赖项.修复 maven 构建解决了这个问题。

    加长版

    长版更像是一个关于恐惧、眼泪和鲜血的故事。

    那个 clusterManager 是怎么变成 null 的?

    由于我最初遇到与 TransactionList 关联的 ClusterManager 的问题,因此我尝试查看 com.sun.messaging.jmq.jmsserver.Globals 代码是如何初始化的。我发现它是在一个恰当地称为Globals#initCLusterManager(MQAddress) 的方法中,它使用各种类参数(包括一个Properties 对象)加载了一个将由我的应用程序使用的ClusterManager。什么 ?集群管理器?在客户端代码中?那是什么鬼(稍后会详细介绍)?

    无论如何,ClusterManager 已加载,但之后设置为 null(主要是由于在集群配置中使用了环回地址 - 再一次,在 JMS 客户端 中非常奇怪)......所以看起来它的初始化方式显然不是解决错误的正确途径,这让我感到困惑。

    测试通过了怎么办,生产代码还是有bug?

    正如我在问题中所说,我有一个测试,它(据我了解)完全相同。测试总是成功,生产总是失败。所以那里肯定有什么不同,不是吗?

    所以我对我做了一些新的事情:我在Globals#initClusterManager 代码中放置了一个断点,并尝试使用两种代码来达到它:生产和测试。有人可能会猜到,在 prod 中达到了断点,但在 test 中没有!因此,我将断点移到了我已经知道会到达的某个地方:ActiveRAFactory#getActiveRA(ConnectorDescriptor, String) ...(哦等等,不,我没有把它放在那里,但是我放置断点的地方告诉了我在哪里执行路径变得不同的是那个方法调用,所以我最后把断点放在那里)。

    有了这个断点,我立刻注意到了一些奇怪的事情:对

    的调用
        Collection<ActiveResourceAdapter> activeRAs =  activeRAHabitat.getAllByContract(ActiveResourceAdapter.class);
    

    根据我在测试或生产中的事实返回不同的结果:我在测试中的列表中有 4 个元素(包括 ActiveJmsResourceAdapter),但在生产中只有 3 个。

    不同的 ResourceAdapter,但为什么?

    然后我很困惑:然后我倾向于责怪Glassfish HK2,除了being an IoC container I didn't yet know之外没有其他原因......结果我错了,哦所以错了!

    启示来自 Eclipse 调试器中的表达式 eval:我输入为表达式

    com.sun.enterprise.connectors.jms.system.ActiveJmsResourceAdapter.class
    

    我得到的只是一个 ClassNotFoundException ...等等...一个 ClassNotFoundException ?这门课在jms-core.jar 吗?我很确定 jar 在我的生产文件夹中,不是吗? ... 不 ? ?

    该死的!

    原来maven-dependency-plugin 我用来复制该文件夹中的 jars 使用 copy-dependencies 和配置为“编译”的 includeScope

    简单解决方案的疯狂错误

    所以我向复制依赖项添加了另一个执行,配置为 incldueScope“运行时”,一切正常。

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 2011-01-29
      • 2016-02-08
      • 1970-01-01
      • 2014-06-07
      相关资源
      最近更新 更多