对于Websphere Application Server 7中的MBean线程来说,JTA UserTransact



我试图通过JMX(使用'标准' MBean)在Websphere application Server 7的web应用程序中调用业务逻辑,JTA打开,并想知道为什么这个业务逻辑在从MBean调用时不能看到JTA UserTransaction(因为它可以通过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配置问题—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 Enterprise beans ' 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的线程与应用程序不关联的事实可能导致其他问题。

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

我想到的可能的解释是:

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

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

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

对于这个问题能提供任何线索,我将不胜感激。

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

我认为你最后可能的解释可能是最准确的:

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

mbean可能不适合这种类型的工作。相反,使用ejb或web服务可能更合适。

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

@TransactionManagement(TransactionManagementType.BEAN) 

最新更新