Я пытаюсь вызвать бизнес-логику через JMX (используя «стандартные» MBeans) в веб-приложении в Websphere Application Server 7 с включенным JTA и хотела бы знать, почему эта бизнес-логика не может видеть пользовательскую транзакцию JTA, когда вызывается из 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
Эта проблема выглядит так, как будто это больше, чем просто проблема конфигурации hibernate - hibernate ищет UserTransaction в том, что, по словам IBM, является правильным расположением JNDI UserTransaction ('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 недоступен для:
Извините за неработающие ссылки - я новый пользователь и поэтому могу опубликовать только две рабочие ссылки.
Подпадают ли простые старые MBeans под одну из этих категорий с точки зрения 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), что может быть связано с тем, что он обрабатывает эту работу, как асинхронный компонент, представленный EJB?
Возможные объяснения, которые мне приходили в голову:
Могут возникнуть проблемы с тем, как IBM настраивает потоки MBean в WAS 7 и затем связывается с приложениями, которые регистрируют MBeans.
Могут быть некоторые дополнительные параметры конфигурации для регистрации MBean, которые позволят WAS знать, что он должен связать MBean с приложением, которое его зарегистрировало. Я пробовал несколько альтернативных подходов, но каждый раз видел одно и то же исключение:
Регистрация MBeans с помощью 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 являются подходящим решением для такого рода требований.
Любой свет, который можно пролить на эту проблему, был бы очень признателен.