【发布时间】: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