Проблема с загрузчиком классов при вызове метода EJB через JMX в JBoss AS6 - PullRequest
1 голос
/ 20 июля 2011

В настоящее время я использую AS6.final, а Weld обновлен до 1.1.1.final. Класс EAR отключен. У меня есть синглтон EJB, который я зарегистрировал в JMX - класс EJB упакован в JAR внутри EAR. Когда я вызываю один из методов этого компонента через JMX-консоль, я получаю эту ошибку:


09:13:49,984 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/jmx-console].[HtmlAdaptor]] Servlet.service() for servlet HtmlAdaptor threw exception: java.lang.IllegalStateException: Singleton not set for BaseClas
sLoader@c68740c{vfs:///C:/jboss-6.0.0.Final/common/deploy/jmx-console.war}
        at org.jboss.weld.integration.provider.JBossSingletonProvider$EarSingleton.get(JBossSingletonProvider.java:59) [:6.0.0.Final]
        at org.jboss.weld.Container.instance(Container.java:58) [:2011-04-04 15:54]
        at org.jboss.weld.resolution.ResolvableBuilder.checkQualifier(ResolvableBuilder.java:209) [:2011-04-04 15:54]
        at org.jboss.weld.resolution.ResolvableBuilder.addQualifier(ResolvableBuilder.java:174) [:2011-04-04 15:54]
        at org.jboss.weld.resolution.ResolvableBuilder.addQualifiers(ResolvableBuilder.java:202) [:2011-04-04 15:54]
        at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:108) [:2011-04-04 15:54]
        at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:188) [:3.0.0.Final]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]
        at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]
        at org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation.invoke(InterceptorInvocation.java:72) [:2.0.0.CR1]
        at org.jboss.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:82) [:2.0.0.CR1]
        at org.jboss.interceptor.proxy.InterceptorMethodHandler.executeInterception(InterceptorMethodHandler.java:133) [:2.0.0.CR1]
        at org.jboss.interceptor.proxy.InterceptorMethodHandler.invoke(InterceptorMethodHandler.java:112) [:2.0.0.CR1]
        at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:65) [:2011-04-04 15:54]
        at uk.co.myApp.myService.service.org$jboss$weld$bean-jboss$classloader$id="vfs$$$$C$$jboss-6$0$0$Final$server$all$deploy$myService-ear-2011$1$2-SNAPSHOT$ear"-ManagedBean-uk$co$myApp$myService$service$MyServiceerDAO$@org$jboss$seam$transaction$
Transactional(value=REQUIRED)@org$jboss$seam$transaction$TransactionalInterceptorBinding()${uk$co$myApp$myService$service$MyServiceerDAO$jamJobTrackerDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$linkDAO$@javax$inject$Inject
()$$uk$co$myApp$myService$service$MyServiceerDAO$ruleDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$sliceDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$myServiceJobDAO$@javax$inject$Inject()$$}_$$_WeldSubclass.l
oadSliceInitialiseMyServiceCollections(org$jboss$weld$bean-jboss$classloader$id="vfs$$$$C$$jboss-6$0$0$Final$server$all$deploy$myService-ear-2011$1$2-SNAPSHOT$ear"-ManagedBean-uk$co$myApp$myService$service$MyServiceerDAO$@org$jboss$seam$transaction$Tr
ansactional(value=REQUIRED)@org$jboss$seam$transaction$TransactionalInterceptorBinding()${uk$co$myApp$myService$service$MyServiceerDAO$jamJobTrackerDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$linkDAO$@javax$inject$Inject()
$$uk$co$myApp$myService$service$MyServiceerDAO$ruleDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$sliceDAO$@javax$inject$Inject()$$uk$co$myApp$myService$service$MyServiceerDAO$myServiceJobDAO$@javax$inject$Inject()$$}_$$_WeldSubclass.jav
a)
        at uk.co.myApp.myService.service.MyServiceService.startCDIJob(MyServiceService.java:96) [:]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]
        at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]
        at org.gescobar.management.util.MBeanImpl.invoke(MBeanImpl.java:181) [:]
        at org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164) [:6.0.0.GA]
        at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:670) [:6.0.0.GA]
        at org.jboss.jmx.adaptor.control.Server.invokeOpByName(Server.java:258) [:]
        at org.jboss.jmx.adaptor.control.Server.invokeOp(Server.java:223) [:]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet$3.run(HtmlAdaptorServlet.java:380) [:]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet$3.run(HtmlAdaptorServlet.java:377) [:]
        at java.security.AccessController.doPrivileged(Native Method) [:1.6.0_07]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet.invokeOp(HtmlAdaptorServlet.java:376) [:]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet.invokeOp(HtmlAdaptorServlet.java:287) [:]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet.processRequest(HtmlAdaptorServlet.java:104) [:]
        at org.jboss.jmx.adaptor.html.HtmlAdaptorServlet.doPost(HtmlAdaptorServlet.java:86) [:]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [:1.0.0.Final]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [:1.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) [:6.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) [:6.0.0.Final]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [:6.0.0.Final]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) [:6.0.0.Final]
        at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181) [:6.0.0.Final]
        at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88) [:6.0.0.Final]
        at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100) [:6.0.0.Final]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) [:6.0.0.Final]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [:6.0.0.Final]
        at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) [:6.0.0.Final]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [:6.0.0.Final]
        at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53) [:6.0.0.Final]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [:6.0.0.Final]
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [:6.0.0.Final]
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654) [:6.0.0.Final]
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951) [:6.0.0.Final]
        at java.lang.Thread.run(Thread.java:619) [:1.6.0_07]

Метод предполагает открытие транзакции, как видно из трассировки. Однако я думаю, что общая ошибка связана с загрузкой классов (см. https://issues.jboss.org/browse/SEAMJMS-16);, вызвав метод через JMX-консоль в браузере, я делаю это «вне» приложения EAR, которое содержит класс EJB .

Я попытался указать загрузку классов в области (http://community.jboss.org/wiki/ClassLoadingConfiguration), добавив следующий код (с необходимыми изменениями синтаксиса между файлами) как в EAR jboss-app.xml, так и в jmx-console.war jboss-web.xml :

<class-loading java2ClassLoadingCompliance="false">
  <loader-repository>
     my.domain:archive=myapp-ear
     <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
  </loader-repository>
</class-loading>

Однако это никак не повлияло.

Меня отсылали к https://issues.jboss.org/browse/WELD-888, и я думаю, что смогу найти аналогичное решение; отключите изоляцию класса WAR для jmx-console.war, чтобы он мог видеть развернутые другие классы (изоляция класса EAR уже отключена).

http://community.jboss.org/wiki/UseJBossWebClassLoaderInJBoss5 дает 2 способа сделать это:

  1. Закомментируйте bean-компонент WarClassLoaderDeployer во всех / deployers / jbossweb.deployer / META-INF / war-deployers-jboss-beans.xml
  2. Добавить новый файл jboss-classloading в jmx-console.war / WEB-INF / со следующим содержимым:

    <?xml version="1.0" encoding="UTF-8"?>
    <classloading xmlns="urn:jboss:classloading:1.0"
        name="jmx-console.war"
        domain="DefaultDomain"
        parent-domain="Ignored"           
        export-all="NON_EMPTY"
        import-all="true">
    </classloading>
    

Я попробовал оба из них, отдельно, как с каталогом jmx-console.war в общем / deploy, так и в server / all / deploy - похоже, ни один из них не работает.

Даже помещение всех необходимых библиотек в jmx-console.war / WEB-INF / lib / не работает, так как он пытается снова развернуть EJB (по крайней мере, в Weld) при вызове JMX-консоли! В любом случае, это не было хорошим решением - каждый раз, когда вы развертываете, вам также придется обновлять библиотеку.

Итак ... есть идеи, как мне добиться видимости класса EAR для jmx-console.war? И на самом деле использовать это, чтобы сделать что-то значимое?

1 Ответ

0 голосов
/ 21 июля 2011

Сортировал это сейчас, благодаря Алесу Джастину на форуме JBoss.org (http://community.jboss.org/message/616328).

В основном мой регистрационный код вызывал единственный публичный метод, доступный для регистрации mbean, MBeanServer.registerMBean(Object object, ObjectName name). Это нене указывайте загрузчик классов, поэтому загрузчик классов, зарегистрированный с помощью bean-компонента в реестре JMX, имеет значение null.

Это означает, что когда вы вызываете метод для bean-компонента через консоль JMX в браузере, он возвращается кзагрузчик классов в вызывающем потоке - бесполезно, если вы пытаетесь сделать что-либо вовлеченное, так как у него не будет ни одного из ваших классов, следовательно, ошибка выше.

Алес указал мне на альтернативный способ регистрацииbean-компонент, который решает эту проблему и используется в сервисном коде JBoss. вместо из

DynamicMBean mBean = getMBeanFactory().createMBean(this);
MBeanServer mBeanServer = MBeanServerLocator.instance().getmBeanServer();
ObjectName name;
try {
    name = new ObjectName(jmxObjectName);
    mBeanServer.registerMBean(mBean, name);
}
catch (Throwable t) {
    log.error(String.format("Unable to register [%s] with JMX under [%s]:", serviceName, jmxObjectName), t);
}

Я сейчас использую

DynamicMBean mBean = getMBeanFactory().createMBean(this);
MBeanServer mBeanServer = MBeanServerLocator.instance().getmBeanServer();
ObjectName name;
try {
    name = new ObjectName(jmxObjectName);

    Map<String, Object> values = new HashMap<String, Object>();
    ClassLoader classLoader = this.getClass().getClassLoader();
    log.info(String.format("Registering to JMX with classLoader [%s]",classLoader.toString()));
    values.put(ServerConstants.CLASSLOADER, classLoader);

    mBeanServer.invoke(
        ObjectNameFactory.create(ServerConstants.MBEAN_REGISTRY), 
        "registerMBean", 
        new Object[] { mBean, name, values }, 
        new String[] { Object.class.getName(), ObjectName.class.getName(), Map.class.getName() }
    );
} catch (Throwable t) {
    log.error(String.format("Unable to register [%s] with JMX under [%s]:", serviceName, jmxObjectName), t);
}

Это принятос org.jboss.system.ServiceCreator.installPlainMBean(MBeanServer server, ObjectName objectName, ServiceMetaData metaData). Вы вызываете registerMBean для самого бина MbeanResgistry, кажется, и здесь вы можете передать загрузчик классов, который затем переключается на при вызове метода бинав браузере.

...