JSP UserTransaction的JNDI查找不适用于Websphere Application Server 7中的MBean线程

时间:2011-12-01 15:08:48

标签: jmx jta websphere-7 mbeans

我试图通过JMX调用业务逻辑(使用'标准' MBean),在开启JTA的Websphere Application Server 7中的Web应用程序中,并且想知道为什么这个业务逻辑可以& #39;在从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位置的UserTransaction(' java:comp / 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 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 /包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%1207%6E%22%20%22%75%73%65%72%74%72%61%6E%73%61%63%74 %22%20

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

从IBM的角度来看,普通的旧MBean是否属于这两类中的任何一类?

有趣的是,UserTransaction似乎可用于JNDI查找&#39; jta / UserTransaction&#39;并使用它作为后备选项似乎工作 - 但是:

  • WAS 7符合Java EE 5,自J2EE 1.3&#39; java:comp / UserTransaction&#39;是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 invokation与相应的应用程序相关联。该论坛帖子表明,可以配置客户端应用程序以访问初始上下文:http://www.ibm.com/developerworks/forums/thread.jspa?messageID = 14021995

    < / LI>
  • 我可能不应该尝试以这种方式使用MBean - 尽管我应该能够做IBM的陈述。有人建议EJB是适合这种要求的解决方案。

非常感谢能解决这个问题的任何亮点。

2 个答案:

答案 0 :(得分:2)

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

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

  

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

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

答案 1 :(得分:0)

您必须在transactionManagement上设置TransactionManagementType.BEAN,如下所示:

@TransactionManagement(TransactionManagementType.BEAN)