2015-12-03 15 views
8

Beim Versuch, ein Ohr zu entfalten, erhalten wir das berüchtigte WELD-001408 (siehe unten für StackTrace).Warum gibt es einen WELD-001408, auch wenn der BeanManager den EJB kennt?

Problem: Es scheint, dass WELD eine EJB über @Inject nicht in eine CDI-gesteuerte Bean (! = @ManagedBean) in einer lib/shared.jar injizieren kann. Warum ist das? Gibt es einen Standard, der besagt, dass dies nicht funktionieren soll?

UPDATE ich auch eine ejb-jar.xml an der betreffenden Stelle hatte ...

UPDATE2: habe ich eine minimale versin auf github

Zuerst das Setup - mein Forschung/Ergebnisse und detailliertere Fragen am Ende:

Wir verwenden derzeit Glassfish 4.1 => Weld 2.2.2.Final, aber der Fehler ist die gleiche Payara mit 4.1.1.154 => Weld 2.2.16.Final, auch Java EE 7

Aufbau des Ohres

sample.ear 
├── a-ejb.jar (contains AEjb.java + beans.xml + ejb-jar.xml) 
├── b-ejb.jar (contains AnotherCdiIManagedBeanPojo.java + DummyEjb.java + beans.xml) 
├── lib 
| └── shared.jar (contains ACdiManagedBeanPojo.java, AnotherCdiDependency.java + beans.xml) 
└── META-INF 
    └── application.xml (...) 

Im shared.jar ist es

public class ACdiManagedBeanPojo { 
    @Inject 
    private AEjb aEjb; 

    @Inject 
    private AnotherCdiDependency anotherCdiDependency;   
} 

AEjb ist ein EJB wohnhaft in der a-ejb.jar

@javax.ejb.Singleton 
@javax.ejb.LocalBean 
@javax.enterprise.context.ApplicationScoped 
public class AEjb {} 

AnotherCdiDependency ist eine weitere Pojo im shared.jar

public class AnotherCdiDependency {} 

Die folgenden Klasse besteht in b-ejb.jar

public class AnotherCdiManagedBeanPojo { 
    @Inject 
    private AEjb aEjb; 
} 

beans.xml (CDI 1,1)

<beans bean-discovery-mode="all" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"> 
</beans> 

ejb-jar.xml

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" 
     version="3.1"> 
    <enterprise-beans> 
     <session> 
      <ejb-name>AEjb</ejb-name> 
      <ejb-class>com.xxx.ejb.AEjb</ejb-class> 
      <session-type>Singleton</session-type> 
     </session> 
    </enterprise-beans> 
</ejb-jar> 

stacktrace

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type AEjb with qualifiers @Default 
    at injection point [BackedAnnotatedField] @Inject @Default private com.managed.pojo.ACdiManagedBeanPojo.aEjb 
    at com.managed.pojo.ACdiManagedBeanPojo.aEjb(ACdiManagedBeanPojo.java:0) 

    at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:370) 
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:291) 
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134) 
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:165) 
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:529) 
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:515) 
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:490) 
    at org.jboss.weld.bootstrap.WeldStartup.validateBeans(WeldStartup.java:419) 
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:90) 
    at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:225) 
    at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131) 
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:328) 
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:496) 
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219) 
    at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:539) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:535) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:360) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:534) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:565) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:557) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:360) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1300(CommandRunnerImpl.java:109) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846) 
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722) 
    at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:253) 
    at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:231) 
    at org.glassfish.admin.rest.utils.ResourceUtil.runCommand(ResourceUtil.java:275) 
    at org.glassfish.admin.rest.resources.TemplateListOfResource.createResource(TemplateListOfResource.java:133) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171) 
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:387) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:331) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:103) 
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297) 
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254) 
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028) 
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:365) 
    at org.glassfish.admin.rest.adapter.RestAdapter$2.service(RestAdapter.java:316) 
    at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:179) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167) 
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201) 
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175) 
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235) 
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) 
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284) 
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201) 
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133) 
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112) 
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) 
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561) 
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112) 
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117) 
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56) 
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137) 
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565) 
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545) 
    at java.lang.Thread.run(Thread.java:745) 
]] 

Forschung und Erkenntnisse

  • Debuggen Validator.validateInjectionPointForDeploymentProblems() Ich sah, dass die BeanManager von lib/shared.jar die Instanz von AEjb hatte in seiner Enterprise Beans Kollektion. Zu keinem Zeitpunkt wird diese Sammlung zum Nachschlagen von Abhängigkeiten verwendet.
  • Die Injektion von keiner EJB-Klassen (wie AnotherCdiDependency) arbeitet in den Klassen der shared.jar
  • Injizieren AEjb über @Inject in AnotherCdiManagedBeanPojo feinen, die in B-EJB befindet.jar (sprich: Toplevel/außerhalb/lib) funktioniert auch gut

  • Meine erste Frage Meine Fragen: Warum kann injizieren die BeanManager die EJB auch , wenn es weiß, darüber? Gibt es einen Standard, der besagt, dass gemeinsame Bibliotheken nicht mit "globalen" EJBs injiziert werden können? Wenn ja, wo finde ich es?

  • Was wäre der "einfachste" Ausweg? Wo einfach bedeutet, so wenig Code wie möglich zu ändern und keine große Unordnung zu erzeugen, werden wir später Schwierigkeiten haben.

  • Bonus Frage: Was ist mit diesem Kommentar in BeanManagerImpl.getBeans (InjectionPoint injectionPoint) - wo ist das FAQ?

    Wir immer Cache, gehen wir davon aus, dass die Menschen wörtliche Inline-Annotation Erklärungen nicht verwenden, ein wenig riskant, aber FAQd

PS: Ich habe die folgenden und viele andere Sachen lesen über classloading, Kontext und cdi und das besondere Verhalten der verschiedenen Anwendungsservern diese Themen rund - aber immer noch ...

Haftungsausschluss: Keine neue während meiner Forschung genannt wurde.

+0

haben Sie versucht, eine ejb-jar.xml Descriptor an die ejb Gläser hinzufügen? – StefanHeimberg

+0

@StefanHeimberg: Ja, versuchte das auch - immer noch das gleiche Problem - Ich werde die Frage mit dieser Information aktualisieren - danke für den Vorschlag –

+1

Ich habe ein bisschen herum gespielt ... können Sie https://github.com/ klonen StefanHeimberg/stackoverflow-34065368, erstellen und deploy "Eltern/sample-app/target/sample-app-1.0-SNAPSHOT.ear" auf Ihrem Glassfish? und dann schauen Sie sich die Ausgabe an. Können Sie überprüfen, ob alles funktioniert? AStartupEJB -> BApplicationCDIBean -> BEJB – StefanHeimberg

Antwort

2

Die Regeln für die Klassensichtbarkeit in EAR-Dateien sind in §8 der Java EE Specification, v7, festgelegt.

Zusammengefasst:

Jedes Modul in der EAR effektiv seine eigene Klassenlader wird.

Die JAR-Dateien im EAR/lib-Verzeichnis werden zum Zweck der Klassensichtbarkeit in einem einzigen Modul zusammengefasst. Klassen im Klassenladeprogramm EAR/lib werden automatisch für alle anderen Module sichtbar gemacht (wie in §8.3 beschrieben).

Das Gegenteil ist nicht wahr. Klassen in den anderen Modulen sind nicht automatisch für die im EAR/lib-Modul verfügbar.

Einige Java EE-Implementierungen bieten Möglichkeiten, diese Einschränkungen zu umgehen (auf Kosten der Unportabilität Ihrer Anwendung).

Eine mögliche Lösung besteht darin, shared.jar in den Stamm der EAR zu verschieben und in jedem jar Manifest-Klassenpfadeinträge zu verwenden, um den Zugriff sicherzustellen.

dh. der META-INF/MANIFEST.MF in shared.jar würde dann enthalten:

Class-Path: b-ejb.jar 

Wenn Ihre ejb-Gläser müssen Klassen in der bewegten sample.jar sehen, dann würden sie dann ihre eigenen Manifest Klassenpfadeinträge müssen .

Ich denke, das Glas muss verschoben werden, da meiner Erfahrung nach Folgendes nicht funktioniert.

Class-Path: ../b-ejb.jar 
+0

Die Anpassung der MANIFEST.MF löste die Situation nicht, aber wie bereits erwähnt, benötigen wir kein "@Singleton @Startup" EJB mehr, sondern verwenden die hier beschriebene Lösung http://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup, um unseren Code initialisiert zu bekommen –

0

Sie sollten das EJB mithilfe der @ EJB-Annotation in die CDI-Bean injizieren.

public class ACdiManagedBeanPojo { 
    @EJB 
    private AEjb aEjb; 

    @Inject 
    private AnotherCdiDependency anotherCdiDependency;   
} 

für mich gearbeitet auf die Testanwendung auf GitHub und erfolgreich 4.1.154 Payara eingesetzt