La búsqueda de JNDI para la JTA UserTransaction no está disponible para MBean Threads en WebSphere Application Server 7
-
27-10-2019 - |
Pregunta
Estoy tratando de invocar la lógica comercial a través de JMX (usando 'MBeans estándar') en una aplicación web en WebSphere Application Server 7 con JTA encendido y me gustaría saber por qué esta lógica comercial no puede ver la JTA UserTransaction cuando se invoca desde un Mbean (porque puede cuando se invoca a través de la interfaz de usuario de la aplicación web).
Cuando Hibernate intenta buscar la transacción de usuario a través de 'java: comp/userTransaction', se lanza la siguiente excepción:
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
Parece que este problema es más que un solo problema de configuración de hibernado: Hibernate está buscando la transacción de usuario en lo que IBM dice que es la ubicación correcta de usertransaction JNDI ('java: comp/userTransaction') - ver Este documento de Infocenter.
Además, puedo reproducir el problema en una aplicación web simple que tiene un MBean que hace la búsqueda:
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);
}
}
y un oyente de contexto que invoca la búsqueda durante el inicio y luego registra el 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);
}
}
La búsqueda en 'java: comp/userTransaction' tiene éxito durante la inicialización del contexto, pero falla (con un rastro de pila similar a la anterior) cuando se invoca a través de JMX, como así:
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
los 'Extender el sistema administrativo del servidor de aplicaciones de WebSphere con documento de MBeans' En el Infocenter de IBM sugiere que los MBeans estándar que se han probado en aplicaciones externas deberían funcionar.
IBM dice que la búsqueda de INSERTRANSACTION no está disponible para:
Frijoles empresariales CMT `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.base.doc/info/ae/cjta_glotran.html
Los granos asíncronos creados por EJBS `http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/asynchbeans/package- resumen.html? resultado de =%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 20
Disculpas por los enlaces no funcionales: soy un nuevo usuario y, por lo tanto, solo puedo publicar dos enlaces de trabajo.
¿Se dividen en cualquiera de estas categorías desde el punto de vista de IBM?
Curiosamente, el usuario de userTransaction parece estar disponible en la búsqueda de JNDI 'JTA/UserTransaction' y usarlo como una opción de respuesta parece funcionar, pero::
Was 7 anda Java Ee 5 que cumple con J2EE 1.3 'java: comp/userTransaction' es la ubicación JNDI especificada para el userTransaction- consulte la especificación J2EE 1.3 `http://java.sun.com/j2ee/j2ee-1_3-- FR-spec.pdf
El uso de una búsqueda de una versión anterior de la especificación EE parece una fuente potencial de otros errores, y podría estar abordando parte de mi problema: el hecho de que el hilo de mi MBean no está asociado con una aplicación podría causar otros problemas.
Otro punto a tener en cuenta es que la Transaction de User también está oculta a los subprocesos para el trabajo enviado desde el MBean al Gerente de Trabajo de la Aplicación (un Gerente de Trabajo de IBM), lo que podría ser porque está tratando ese trabajo como si fuera un Bean Async enviado por un EJB?
Las posibles explicaciones que me han ocurrido son:
Podría problemas con cómo IBM configuró MBean Threads en fue 7 y se asociaron con las solicitudes que registran los MBeans.
Puede haber algunas opciones de configuración adicionales para el registro de MBean que le haría saber que debería asociar al MBean con la aplicación que la registró. He probado varios enfoques alternativos, pero vi la misma excepción cada vez:
Registro de MBeans con Usercolaboradores y descriptores XML
Registrándolos con modelmbeaninfo
Registrándolos con el servicio de administración en lugar del mbeanserver
Mejorar el nombre de objeto para el MBean con propiedades adicionales (aplicación, J2EEApplication) en el registro
Puede haber algunas opciones de configuración adicionales para la solicitud del cliente JMX que lo haría saber que debería asociar la invocación de MBean con la aplicación apropiada. Esta publicación del foro sugiere que es posible configurar una aplicación cliente para tener acceso al contexto inicial: `http://www.ibm.com/developerworks/forums/thread.jspa?MessageId=14021995
Es posible que no se suponga que deba usar MBeans de esta manera, a pesar de las declaraciones de IBM que debería poder. Se ha sugerido que los EJB son la solución apropiada para este tipo de requisito.
Cualquier luz que se pueda arrojar sobre este problema sería muy apreciada.
Solución
Los MBeans se ejecutan en un hilo separado que su aplicación, por lo que no tienen acceso al contexto de nombres de aplicaciones en JNDI y, por lo tanto, no tienen acceso a su transacción de usuario.
Creo que su explicación potencial final es probablemente más precisa:
Es posible que no se suponga que deba usar MBeans de esta manera, a pesar de las declaraciones de IBM que debería poder. Se ha sugerido que los EJB son la solución apropiada para este tipo de requisito.
Los MBeans pueden no ser apropiados para este tipo de trabajo. Más bien, usar EJBS o un servicio web podría ser más apropiado.
Otros consejos
Tienes que configurar TransactionManagementType.BEAN
en la gestión de transacciones como así:
@TransactionManagement(TransactionManagementType.BEAN)