Поиск JNDI для пользовательской транзакции JTA недоступен для потоков MBean в Websphere Application Server 7.

Я пытаюсь вызвать бизнес-логику через 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-компоненты являются подходящим решением для такого рода требований.

Мы будем очень признательны за любой свет, который можно пролить на эту проблему.


person Joseph MacFarlane    schedule 01.12.2011    source источник


Ответы (2)


MBeans запускаются в отдельном потоке, чем ваше приложение, поэтому у них нет доступа к контексту именования приложений в JNDI, и, следовательно, у них нет доступа к вашему UserTransaction.

Я думаю, что ваше окончательное возможное объяснение, вероятно, наиболее точно:

Возможно, мне просто не следовало пытаться использовать MBeans таким образом - несмотря на заявления IBM о том, что я должен уметь это делать. Было высказано предположение, что EJB-компоненты являются подходящим решением для такого рода требований.

MBean-компоненты могут не подходить для этого типа работы. Скорее, может быть более подходящим использование EJB или веб-службы.

person shelley    schedule 01.12.2011
comment
Спасибо за это, Шелли, это ответ, который я боялся услышать. Забавно, что этот подход, похоже, работает, когда JTA выключен (и когда я использую старый поиск JNDI). - person Joseph MacFarlane; 01.12.2011
comment
Если я правильно читаю ваше описание, вы можете найти его с помощью jta / UserTransaction, а не java: comp / UserTransaction? Если это так, то первая, скорее всего, глобальная транзакция, доступная где угодно на сервере, тогда как вторая находится в контексте именования вашего приложения. Это могло бы объяснить, почему вы можете получить к нему доступ из вашего MBean; глобальный контекст именования доступен, но контекст именования вашего приложения - нет. - person shelley; 01.12.2011
comment
Это правильное чтение - я могу посмотреть глобальную транзакцию через jta / UserTransaction. Вопрос в том, почему IBM раскрыла глобальную транзакцию через это имя и безопасно ли его использовать. Может быть, он нужен для поддержки устаревших приложений на J2EE 1.2 и ниже? В этом случае это может быть безопасно. Или он может использоваться для внутренних функций WAS - в этом случае использование его кажется нецелесообразным. - person Joseph MacFarlane; 01.12.2011
comment
Это правильный ответ - некоторые ресурсы недоступны потокам MBean в WAS. глобальные транзакции теперь указано, что 'только корпоративные компоненты BMT, клиентские компоненты приложений и веб-компоненты могут использовать интерфейс UserTransaction API транзакций Java (JTA). ' - person Joseph MacFarlane; 16.01.2012

Вы должны установить TransactionManagementType.BEAN в transactionManagement следующим образом:

@TransactionManagement(TransactionManagementType.BEAN) 
person user3791059    schedule 30.06.2014
comment
Это та же версия, что и исходный пост? - person Alexandre Santos; 30.06.2014