Я пытаюсь вызвать бизнес-логику через JMX (используя «стандартные» MBeans) в веб-приложении на Websphere Application Server 7 с включенным JTA, и хотел бы знать, почему эта бизнес-логика не может видеть JTA UserTransaction при вызове из MBean (потому что он может быть вызван через пользовательский интерфейс веб-приложения).
Когда hibernate пытается найти UserTransaction через 'java: comp / 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
Эта проблема выглядит так, будто это больше, чем просто проблема конфигурации гибернации - спящий режим ищет UserTransaction в том месте, которое, по мнению IBM, является правильным расположением UserTransaction JNDI ('java: comp / UserTransaction') - см. этот документ информационного центра < / а>.
Более того, я могу воспроизвести проблему в простом веб-приложении с 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
'Расширение административной системы WebSphere Application Server с помощью специального документа MBeans' в информационном центре IBM предполагает, что стандартные MBean-компоненты, которые были протестированы в приложениях вне WAS, должны просто работать.
IBM заявляет, что поиск UserTransaction недоступен для:
Компоненты CMT Enterprise `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.base.doc/info/aes/ae/cjta_glotran.html
Асинхронные компоненты, созданные EJB, 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
Приносим извинения за нефункциональные ссылки - я новый пользователь и могу разместить только две рабочие ссылки.
Попадают ли старые добрые MBean-компоненты в какую-либо из этих категорий с точки зрения IBM?
Интересно, что UserTransaction, похоже, доступен в поиске JNDI 'jta / UserTransaction', и использование его в качестве запасного варианта, похоже, работает, но:
WAS 7 совместим с Java EE 5, а в J2EE 1.3 'java: comp / UserTransaction' - это указанное JNDI-расположение для UserTransaction - см. Спецификацию J2EE 1.3 http://java.sun.com/j2ee/j2ee-1_3- fr-spec.pdf
Использование поиска из более ранней версии спецификации EE кажется потенциальным источником других ошибок и, возможно, решает только часть моей проблемы - тот факт, что WAS считает, что мой поток MBean не связан с приложением, может вызвать другие проблемы.
Еще один момент, который следует отметить, заключается в том, что UserTransaction также скрыт для потоков для работы, отправленной из MBean в диспетчер работы приложения (диспетчер работы IBM) - что может быть связано с тем, что он обрабатывает эту работу как асинхронный bean-компонент, отправленный EJB?
Возможные объяснения, которые мне пришли в голову:
Могут возникнуть проблемы с тем, как IBM настраивает потоки MBean в WAS 7 и связывает их с приложениями, которые регистрируют MBean.
Могут быть некоторые дополнительные параметры конфигурации для регистрации MBean, которые позволят WAS узнать, что он должен связать MBean с приложением, которое его зарегистрировало. Я пробовал несколько альтернативных подходов, но каждый раз видел одно и то же исключение:
Регистрация MBean-компонентов с помощью UserCollaborators и xml-дескрипторов
Регистрация их в ModelMBeanInfo
Регистрация их с помощью AdminService, а не MBeanServer
Улучшение ObjectName для MBean-компонента дополнительными свойствами (Application, J2EEApplication) при регистрации
Могут быть некоторые дополнительные параметры конфигурации для запроса клиента jmx, которые позволят WAS узнать, что он должен связать вызов MBean с соответствующим приложением. В этом сообщении на форуме предлагается настроить клиентское приложение для доступа к начальному контексту: http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14021995
Возможно, мне просто не следовало пытаться использовать MBeans таким образом - несмотря на заявления IBM о том, что я должен уметь это делать. Было высказано предположение, что EJB-компоненты являются подходящим решением для такого рода требований.
Мы будем очень признательны за любой свет, который можно пролить на эту проблему.