2016-03-08 8 views
5

Ich versuche, meinen Kopf hier etwas einzuwickeln: Nur Injektion funktioniert auf der ersten Ebene meiner Anwendung, aber dann stoppt es und alle @Inject annotierte Eigenschaften sind null in den Objekten, die von meiner Factory-Musterimplementierung zurückgegeben wurden. Ich lese viel über Leute, die Probleme haben, CDI mit JAX-RS zu arbeiten, aber das scheint nicht mein Problem zu sein. Ich habe das Gefühl, dass mir einige Anmerkungen fehlen, oder ich sehe das Holz nicht vor allen Bäumen (wie wir hier sagen) ;-)CDI funktioniert nicht in Objekten aus Factory-Muster-Implementierung

Edit: Habe ein Beispielprojekt mit dem Code, den ich gepostet habe hier zu überprüfen. Jetzt erkenne ich, dass ich über vereinfacht: in der Tat verwende ich eine Factory Pattern, um meinen Service zu erhalten, die den verwalteten Kontext unterbrechen könnte. Bitte beachten Sie das erweiterte Beispiel:

Los geht's.

Erste Schicht: JAX-RS Anwendung, alle gut

@RequestScoped 
@Path("/somePath/someResource") 
public class SomeResource { 
    @Inject 
    ISomeServiceFactory someServiceFactory; 

    @POST 
    @Produces(MediaType.APPLICATION_JSON) 
    @Consumes(MediaType.APPLICATION_JSON) 
    public SomeResponse someMethod(@PathParam("foo") final String foo) { 
     ISomeService myService = someServiceFactory.getService(ServiceCatalog.valueOf(foo)); // works, we jump in there! 
     myService.someMethod(); 
    } 

} 

public enum ServiceCatalog { 
    STANDARD("standard"), ADVANCED("advanced"), FOO("foo"); 
    // ... 
} 

Die gebrochen Service-Fabrik, die anhand bekannten Parameters (Enum) Werte von REST API aufrufen, um eine Implementierung der Auswahl:

public interface ISomeServiceFactory { 
    public ISomeService getService(ServiceCatalog serviceType); 
} 

@Stateless 
public class SomeServiceFactory implements ISomeServiceFactory { 
    public ISomeService getService(ServiceCatalog serviceType) { 
    if(serviceType.equals(ServiceCatalog.FOO)) { 
     return new FooService(); // will break CDI context 
    } else if (...) { 
     // ... 
    } else { 
     return new DefaultService(); // will also break CDI context 
    } 
    } 
} 

Zweite Schicht: Einige EJB, Probleme hier

// Interface: 

public interface ISomeService { 
    public void someMethod(); 
} 

// Implementation: 

@Stateless 
public class SomeService implements ISomeService { 
    @Inject 
    private ISomeDao someDao; // this will be null !!! 

    @Override 
    public void someMethod() { 
    someDao.doSomething() // exception thrown as someDao == null 
    } 
} 

Das Dao, die angeblich

injizierte
public interface ISomeDao { 
    public void someMethod(); 
} 

@Stateless 
public class SomeDao implements ISomeDao { 
    public void someMethod() {} 
} 

Jetzt zur Laufzeit WebSphere Freiheit sagt mir werden (unter anderen Bindungen ...) diese:

com.ibm.ws.ejbcontainer.runtime.AbstractEJBRuntime 
I CNTR0167I: The server is binding the com.ISomeDao interface of the 
SomeDao enterprise bean in the my.war module of the my application. 
The binding location is: java:global/my/SomeDao!com.ISomeDao 

Ich habe ein Bohne. xml:

<beans 
    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" 
    bean-discovery-mode="all"> 
</beans> 

Es scheint, als ob der neue SomeService() alles bricht, könnten Sie o beraten n Wie wird die Fabrik so implementiert, dass CDI weiter unten möglich ist? Vielen Dank.

+0

Falls dies relevant ist, verwende ich WebSphere Liberty 8.5.5.8 mit folgendem Feature-Set: [servlet-3.1, jndi-1.0, jaxrs-2.0, cdi-1.2, webProfile-7.0, ejbLite- 3.2, ejbHome-3.2, ejbRemote-3.2, javaee-7.0, ejb-3.2, ...] und haben javaee-api 7, cdi-api 1.2, javax.inject 1 in meinem maven pom.xml –

+0

die Feature-Liste ist definitiv relevant - Ich würde empfehlen, Ihre Frage mindestens mit dem '' Teil Ihrer server.xml zu aktualisieren. –

+0

Wie angefordert: ' javaee-7.0 jaxrs-2.0 localConnector-1.0 cdi-1.2 JSONP-1.0 ' –

Antwort

2

In der geänderten Frage zeigen Sie, dass tatsächlich kein EJB in den Webservice eingespeist wird, sondern indirekt über die Fabrik neu angelegt wird.

Ein Objekt wird nur dann mit einer CDI-Injektion ausgeführt, wenn der Container das Objekt erstellt, entweder indem es selbst injiziert wird oder eine der verwalteten EE-Komponenten ist.

Net, Sie können kein EJB oder irgendeine CDI-Bean neu erstellen und CDI-Dienste darin haben.

+0

Ja, du hast recht, genau das habe ich mir auch gedacht. Ich lese jetzt, wie man die Fabrik innerhalb der CDI-Beschränkungen in Betrieb nehmen kann. Ich müsste etwas mit @Produce haben, das eine Implementierung basierend auf einem Enum-Wert zurückgibt. Neugierig darauf, wie Sie dies auf die eleganteste Art umsetzen können. Bis dann danke für deine Eingabe. –

+0

Ich glaube nicht, dass wir aus diesem Fragenkontext wissen, welche Art von Wahl Sie versuchen, indem Sie nicht nur den EJB nach Typ einspeisen. Aber die nächste einfachste ist Typ + Qualifier. – covener

+0

Ja, Sie benötigen eine Producer-Klasse, die Instanzen Ihrer Klasse erzeugen kann. hier ist das Beispiel: http://buraktas.com/cdi-dependency-injection-producer-method-example – user1697575