2016-03-29 13 views
0

Ich habe eine Subresource-Klasse, die mit einem Parameter aus dem Pfad initialisiert werden muss und die auch einen Verweis auf ein EJB enthält, das injiziert werden muss.Jax-rs initialisiert Subresource Es gab kein Objekt zur Injektion

Ressourcenklasse:

@Path("widgets") 
public class MasterResource{ 
    @Inject 
    WidgetBean widgets; 

    @Context 
    ResourceContext rc; 

    @Path("{year}") 
    public WidgetArchives wArchives(@PathParam("year") String year){ 
     return rc.initResource(new WidgetArchiveResource(year)); 
    } 
} 

Subresource Klasse

public class WidgetArchiveResource{ 
    @Inject 
    WidgetBean widgets; 

    public WidgetArchiveResource(String year){ 
     ....code 
    } 

    @GET 
    public String doGet(){ 
     ....code using WidgetBean 
    } 
} 

Als ich mit dem Jahr erhalten aufrufen, sehe ich den folgenden Fehler:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=WidgetBean,parent=WidgetArchiveResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,542790913) 

ich Java bin neu EE. Was mache ich falsch?

+0

Versuchen zu injizieren 'WidgetArchiveResource' und nicht manuell diese Klasse mit' new' erstellen. Stellen Sie einen Standardkonstruktor bereit und legen Sie das Jahr durch eine Methode fest. Vielleicht möchtest du 'bean-discovery-mode =" all "' in bohnen.xml verwenden. – simdevmon

+0

Das ist eine Art Lernübung für mich. Ich habe gesehen, dass initresource auf diese Weise verwendet wird, und ich versuche es zu verstehen. – KG6ZVP

Antwort

2

Die Methode rc.initResource ist nur sinnvoll, wenn Sie einige Abhängigkeiten in die Ressource einfügen müssen (z. B. mit @Inject annotiert). Dies ist eine spezielle JAX-RS-Methode zum Eingeben von Abhängigkeiten in eine Bean. Es ist in einer vollständigen JavaEE-Umgebung veraltet, in der Abhängigkeiten vorzugsweise über CDI injiziert werden. rc.initResource injiziert nicht alle CDI-Beans (z. B. @EJB könnte funktionieren, aber @Inject nicht).

Daher ist in JavaEE die bevorzugte Vorgehensweise, um das zu erreichen, was Sie erreichen möchten, WidgetArchiveResource in das übergeordnete Element MasterResource zu injizieren. CDI-Beans müssen einen Konstruktor ohne Argumente haben, aber Sie können Jahr mit Setter übergeben. Wenn Sie Ihren Master resouce in Anfrage Rahmen setzen, wird es für jede Anforderung neu erstellt, so dass es sicher für die gleichzeitige Anfragen:

@Path("widgets") 
@RequestScoped 
public class MasterResource{ 
    @Inject 
    Instance<WidgetArchiveResource> waResources; 

    @Path("{year}") 
    public WidgetArchives wArchives(@PathParam("year") String year){ 
     WidgetArchiveResource waResource = waResources.get(); 
     waResource.setYear(year); 
     return waResource; 
    } 
} 

Außerdem sollten Sie entweder beans.xml in Ihrem WEB-INF-Ordner mit bean-discovery-mode="all", oder fügen sie explizit abhängigen Umfang auf Ihrem WidgetArchiveResource es CDI in Frage zu stellen:

@Dependent 
public class WidgetArchiveResource { 
    public WidgetArchiveResource() {} // optional no arg constructor 
} 
+0

Gibt es eine Möglichkeit, dies zu tun, ohne eine WidgetArchiveResource instanziieren jedes Mal, wenn etwas auf dem "Widgets" -Pfad aufgerufen wird? – KG6ZVP

+0

Sie können ihm einen größeren Bereich zuweisen. Der größte Bereich ist @ @ ApplicationScoped, was bedeutet, dass er einmal erstellt und dann wieder verwendet wird, bis die Anwendung beendet wird. Sie können @Dependent entfernen und '@ ApplicationScoped' hinzufügen. Sie können auch 'MasterResource' wie folgt anstelle von' @ RequestScoped' markieren. Aber denken Sie daran, dass Sie keinen Zustand zwischen REST-Anfragen speichern sollten, deshalb empfehle ich '@ RequestScoped' – OndrejM

+0

Also gibt es keine Möglichkeit, RequestScoped auf dem Master zu verwenden, ohne alle Subressourcen zu instanziieren, selbst wenn sie nicht in der Anfrage verwendet werden? – KG6ZVP