【问题标题】:The JNDI lookup for the JTA UserTransaction is not available to MBean threads in Websphere Application Server 7JTA UserTransaction 的 JNDI 查找对 Websphere Application Server 7 中的 MBean 线程不可用
【发布时间】:2011-12-01 15:08:48
【问题描述】:

我正在尝试在打开 JTA 的 Websphere Application Server 7 中的 Web 应用程序中通过 JMX(使用“标准”MBeans)调用业务逻辑,我想知道为什么这个业务逻辑在什么时候看不到 JTA UserTransaction从 MBean 调用(因为它可以在通过 Web 应用程序的 UI 调用时)。

当 hibernate 尝试通过 'java:comp/UserTransaction' 查找 UserTransaction 时,会抛出以下异常:

org.hibernate.TransactionException: Could not find UserTransaction in JNDI [java:comp/UserTransaction]
    at org.hibernate.transaction.JTATransactionFactory.getUserTransaction(JTATransactionFactory.java:173)
    at org.hibernate.transaction.JTATransactionFactory.createTransaction(JTATransactionFactory.java:149)

    ...

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:600)
    at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:105)
    at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:39)
    at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:220)
    at com.sun.jmx.mbeanserver.PerInterface.getAttribute(PerInterface.java:77)
    at com.sun.jmx.mbeanserver.MBeanSupport.getAttribute(MBeanSupport.java:228)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:678)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:650)
    at com.ibm.ws.management.AdminServiceImpl.getAttribute(AdminServiceImpl.java:853)
    at com.ibm.ws.management.remote.AdminServiceForwarder.getAttribute(AdminServiceForwarder.java:270)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1415)
    at javax.management.remote.rmi.RMIConnectionImpl.access$200(RMIConnectionImpl.java:84)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1276)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1371)
    at javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:612)
    at javax.management.remote.rmi._RMIConnectionImpl_Tie.getAttribute(_RMIConnectionImpl_Tie.java:578)
    at javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(_RMIConnectionImpl_Tie.java:98)
    at com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:622)
    at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:475)
    at com.ibm.rmi.iiop.ORB.process(ORB.java:513)
    at com.ibm.CORBA.iiop.ORB.process(ORB.java:1574)
    at com.ibm.rmi.iiop.Connection.respondTo(Connection.java:2841)
    at com.ibm.rmi.iiop.Connection.doWork(Connection.java:2714)
    at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:63)
    at com.ibm.ejs.oa.pool.PooledThread.run(ThreadPool.java:118)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1563)
Caused by: javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component.  This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request.  Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application.  Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name "comp/UserTransaction" not found in context "java:".]
    at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:428)
    at com.ibm.ws.naming.java.javaURLContextImpl.lookup(javaURLContextImpl.java:399)
    at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:214)
    at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:154)
    at javax.naming.InitialContext.lookup(InitialContext.java:455)
    at org.hibernate.transaction.JTATransactionFactory.getUserTransaction(JTATransactionFactory.java:163)
    ... 53 more
Caused by: javax.naming.NameNotFoundException: Name "comp/UserTransaction" not found in context "java:".
    at com.ibm.ws.naming.ipbase.NameSpace.lookupInternal(NameSpace.java:1178)
    at com.ibm.ws.naming.ipbase.NameSpace.lookup(NameSpace.java:1095)
    at com.ibm.ws.naming.urlbase.UrlContextImpl.lookup(UrlContextImpl.java:1233)
    at com.ibm.ws.naming.java.javaURLContextImpl.lookup(javaURLContextImpl.java:395)
    ... 57 more

这个问题看起来不仅仅是一个休眠配置问题 - hibernate 正在 IBM 所说的正确的 UserTransaction JNDI 位置('java:comp/UserTransaction')寻找 UserTransaction - 请参阅this infocenter document

此外,我可以在一个简单的 Web 应用程序中重现该问题,该应用程序具有执行查找的 MBean:

public class JTALookup extends NotificationBroadcasterSupport implements JTALookupMBean {
  Log log = LogFactory.getLog(JTALookup.class);

  /**
   * {@inheritDoc}
   * @see JTALookupMBean#lookupUserTransaction()
   */
  @Override
  public void lookupUserTransaction() {
    try {
      log.info("Attempting 'java:comp/UserTransaction' lookup");
      Object usrTxn = new InitialContext().lookup("java:comp/UserTransaction");
      log.info("Successfully looked up 'java:comp/UserTransaction' [" + usrTxn + "]." );
    } catch (NamingException e) {
      log.info("'java:comp/UserTransaction' lookup failed");
      throw new RuntimeException("Failed to lookup JTA user transaction", e);
    }
  }

还有一个上下文监听器,它在启动期间调用查找,然后注册 MBean:

public void contextInitialized(ServletContextEvent sce) {

    log.info("Initialising context");

    JTALookup jtaLookup = new JTALookup();
    jtaLookup.lookupUserTransaction(); // This succeeds
    log.info("Looked up JTA transaction");

    MBeanServer mbServer = AdminServiceFactory.getMBeanFactory().getMBeanServer();
    log.info("Got MBeanServer");

    try {
      mbServer.registerMBean(jtaLookup, new ObjectName("webJTALookupStub:type=JTALookup"));
      log.info("Registered dummy MBean");
    } catch (Exception e) {
      log.info("Failed to register dummy MBean");
      throw new RuntimeException("Failed to register dummy MBean", e);
    }
}

在上下文初始化期间查找“java:comp/UserTransaction”成功,但在通过 jmx 调用时失败(与上面类似的堆栈跟踪),如下所示:

public static void main(String[] args) {

    JMXServiceURL url = new JMXServiceURL(
        "service:jmx:rmi://" + "your.server.name.co.uk" + ":" + "2809" + "/jndi/JMXConnector"
    );

    Hashtable<String, Object> env = new Hashtable<String, Object>();
    env.put(Context.PROVIDER_URL, "corbaloc:iiop:gbbldd66.sys.chp.co.uk:2809/WsnAdminNameService");
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");

    // Establish the JMX connection.
    JMXConnector jmxc = JMXConnectorFactory.connect(url, env);

    // Get the MBean server connection instance.
    MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

    ObjectName mbeanName = new ObjectName("webJTALookupStub:type=JTALookup");

    JTALookupMBean mBean = JMX.newMBeanProxy(mbsc, mbeanName, JTALookupMBean.class, true);

    mBean.lookupUserTransaction(); // This fails

IBM 信息中心的'Extending the WebSphere Application Server administrative system with custom MBeans' document 表明已经在WAS 之外的应用程序中测试过的标准MBean 应该可以正常工作。

IBM 声明 UserTransaction 查找不适用于:

  • CMT 企业 bean `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.base.doc/info/aes/ae /cjta_glotran.html

  • 由 EJB 创建的异步 Bean `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/ websphere/asynchbeans/package-summary.html?resultof=%22%61%73%79%6e%63%68%62%65%61%6e%22%20%22%75%73%65%72%74 %72%61%6e%73%61%63%74%69%6f%6e%22%20%22%75%73%65%72%74%72%61%6e%73%61%63%74 %22%20

对非功能链接致歉 - 我是新用户,因此只能发布两个工作链接。

从 IBM 的角度来看,普通的旧 MBean 是否属于这些类别?

有趣的是,UserTransaction 似乎在 JNDI 查找“jta/UserTransaction”上可用,并且将其用作后备选项似乎可行 - 但是:

  • WAS 7 与 Java EE 5 兼容,从 J2EE 1.3 开始,“java:comp/UserTransaction”是 UserTransaction 的指定 JNDI 位置 - 请参阅 J2EE 1.3 规范 `http://java.sun.com/ j2ee/j2ee-1_3-fr-spec.pdf

  • 使用来自早期版本的 EE 规范的查找似乎是其他错误的潜在来源,并且可能只是解决了我的部分问题 - WAS 认为我的 MBean 的线程与应用程序无关的事实可能会导致其他问题。

还有一点需要注意的是,对于从 MBean 提交到应用程序的工作管理器(IBM 工作管理器)的工作,UserTransaction 也隐藏到线程中 - 这可能是因为它将工作视为由提交的异步 bean一个 EJB?

我想到的可能解释是:

  • IBM 如何在 WAS 7 中设置 MBean 线程并随后与注册 MBean 的应用程序关联可能存在问题。

  • MBean 注册可能有一些额外的配置选项,可以让 WAS 知道它应该将 MBean 与注册它的应用程序相关联。我尝试了几种替代方法,但每次都看到相同的异常:

    • 使用 UserCollaborators 和 xml 描述符注册 MBean

    • 使用 ModelMBeanInfo 注册它们

    • 将它们注册到 AdminService 而不是 MBeanServer

    • 在注册时使用附加属性(Application、J2EEApplication)增强 MBean 的 ObjectName

  • 对于 jmx 客户端请求,可能有一些额外的配置选项可以让 WAS 知道它应该将 MBean 调用与适当的应用程序相关联。此论坛帖子建议可以配置客户端应用程序以访问初始上下文:`http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14021995

  • 我可能不应该尝试以这种方式使用 MBean - 尽管 IBM 声明我应该能够这样做。有人建议 EJB 是此类需求的合适解决方案。

任何可以解决这个问题的线索将不胜感激。

【问题讨论】:

    标签: jmx jta websphere-7 mbeans


    【解决方案1】:

    MBean 在与您的应用程序不同的线程上运行,因此它们无权访问 JNDI 中的应用程序命名上下文,因此它们无权访问您的 UserTransaction。

    我认为您最终可能的解释可能是最准确的:

    我可能不应该尝试以这种方式使用 MBean - 尽管 IBM 声明我应该能够这样做。有人建议 EJB 是此类需求的合适解决方案。

    MBeans 可能不适合这种类型的工作。相反,使用 EJB 或 Web 服务可能更合适。

    【讨论】:

    • 感谢雪莱,这是我害怕听到的答案。有趣的是,当 JTA 关闭时(以及当我使用较旧的 JNDI 查找时),这种方法似乎有效。
    • 如果我正确阅读了您的描述,您可以使用“jta/UserTransaction”而不是“java:comp/UserTransaction”来查找它吗?如果是这样,前者可能是服务器中任何地方可用的全局事务,而后者则在您的应用程序命名上下文中。这可以解释为什么您可以从 MBean 访问它;全局命名上下文可用,但您应用的命名上下文不可用。
    • 这是正确的解读——我可以通过“jta/UserTransaction”查看全局事务。问题是为什么 IBM 通过这个名称公开了全局事务,以及它是否可以安全使用。也许它可以支持 J2EE 1.2 及更低版本的遗留应用程序?在这种情况下使用它可能是安全的。或者它可能存在于 WAS 内部的功能中——在这种情况下使用它似乎是不可取的。
    • 这是正确的答案 - WAS 中的 MBean 线程无法使用某些资源。 global transactions 信息中心页面现在指定“只有 BMT 企业 bean、应用程序客户端组件和 Web 组件可以使用 Java Transaction API (JTA) UserTransaction 接口”
    【解决方案2】:

    您必须像这样在 transactionManagement 上设置TransactionManagementType.BEAN

    @TransactionManagement(TransactionManagementType.BEAN) 
    

    【讨论】:

    • 这个和原帖是同一个版本吗?
    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多