2

我正在尝试在打开 JTA 的 Websphere Application Server 7 中的 Web 应用程序中通过 JMX(使用“标准”MBeans)调用业务逻辑,并且想知道为什么从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 - 请参阅此信息中心文档

此外,我可以在一个简单的 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 信息中心中的“使用自定义 MBean 扩展 WebSphere Application Server 管理系统”文档表明,已经在 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 也隐藏到线程中——这可能是因为它将该工作视为由 EJB 提交的异步 bean?

我想到的可能解释是:

  • 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 是这种需求的合适解决方案。

任何可以解决这个问题的信息都将不胜感激。

4

2 回答 2

2

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

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

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

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

于 2011-12-01T15:44:32.607 回答
0

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

@TransactionManagement(TransactionManagementType.BEAN) 
于 2014-06-30T16:27:13.840 回答