L'injection de dépendance avec Jersey 2.0
À partir de zéro sans précédent Jersey 1.x de connaissances, je vais avoir un moment difficile de comprendre comment le programme d'installation d'injection de dépendance dans mon Maillot 2.0 projet.
Je comprends aussi que HK2 est disponible en Jersey 2.0, mais je n'arrive pas à trouver des docs qui aident avec le Maillot 2.0 intégration.
@ManagedBean
@Path("myresource")
public class MyResource {
@Inject
MyService myService;
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* @return String that will be returned as a text/plain response.
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/getit")
public String getIt() {
return "Got it {" + myService + "}";
}
}
@Resource
@ManagedBean
public class MyService {
void serviceCall() {
System.out.print("Service calls");
}
}
pom.xml
<properties>
<jersey.version>2.0-rc1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jax-rs-ri</artifactId>
</dependency>
</dependencies>
Je peux obtenir le conteneur de début et de servir de mes ressources, mais dès que j'ai ajouter @Inject pour MyService, le cadre déclenche une exception:
SEVERE: Servlet.service() for servlet [com.noip.MyApplication] in context with path [/jaxrs] threw exception [A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.noip.MyResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.noip.MyResource
] with root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
Mon starter projet est disponible sur GitHub: https://github.com/donaldjarmstrong/jaxrs
Vous devez vous connecter pour publier un commentaire.
Vous devez définir une
AbstractBinder
et de l'inscrire dans votre JAX-RS de l'application. Le classeur spécifie comment l'injection de dépendance devrait créer vos classes.Quand
@Inject
est détecté sur un paramètre ou d'un champ de typeMyService.class
il est instancié en utilisant la classeMyService
. Pour utiliser ce classeur, il faut être inscrit auprès de JAX-RS de l'application. Dans votreweb.xml
, de définir un JAX-RS application comme ceci:Mettre en œuvre les
MyApplication
classe (indiquée ci-dessus dans leinit-param
).Le liant de la spécification de l'injection de dépendance est enregistré dans le constructeur de la classe, et nous avons aussi dire à l'application où trouver le RESTE des ressources (dans votre cas,
MyResource
) à l'aide de lapackages()
appel de méthode.EntityManager
est, mais à en juger par le docs.oracle.com/javaee/6/api/javax/persistence/... il semble être une interface. Vous pouvez le lier à l'aide debind(EntityManagerImpl.class).to(EntityManager.class)
(qui va lier une classeEntityManagerImpl
la mise en œuvre de l'interfaceEntityManager
. Si vous avez besoin d'utiliser une usine, d'un prendre un coup d'oeil àbindFactory()
dans leAbstractBinder
. Si vous avez besoin d'aide, veuillez créer une nouvelle question (je ne vais pas avoir de la place pour y répondre dans les commentaires). Aussi, je ne suis pas sûr que vous devriez utiliser @PersistentContext, il suffit d'utiliser @Inject pour toutEntityManager
, vous pouvez regarder les ce postJuste pour répondre à un commentaire dans l'accepte réponse.
Il lit simplement
bind( implementation ).to( contract )
. Vous pouvez alternative de la chaîne d'.in( scope )
. Par défaut portée dePerLookup
. Donc, si vous voulez un singleton, vous pouvezIl y a aussi un
RequestScoped
disponibleAussi, au lieu de
bind(Class).to(Class)
, vous pouvez égalementbind(Instance).to(Class)
, qui sera automatiquement être un singleton.Ajoutant à la accepté de répondre à
Pour ceux qui essaient de comprendre comment inscrire votre
AbstractBinder
mise en œuvre dans votre web.xml (vous n'êtes pas à l'aide d'unResourceConfig
), il semble que le classeur ne pas être découvert par le biais de paquet de la numérisation, c'est à direOu ce soit
À le faire fonctionner, j'ai dû mettre en œuvre un
Fonction
:La
@Provider
annotation devrait permettre à laFeature
à être ramassé par le paquet de numérisation. Ou sans forfait de numérisation, vous pouvez vous inscrire explicitement laFeature
dans leweb.xml
Voir Aussi:
et pour des informations générales à partir de la Maillot de documentation
Mise à JOUR
Usines
De côté à partir de la base de liaison dans la accepté de répondre, vous avez également des usines, où vous pouvez avoir plus complexe de la création de la logique, et ont également accès à la demande d'informations de contexte. Par exemple
Ensuite, vous pouvez injecter
MyService
dans votre classe de ressource.web.xml
même si leconfigure()
surHk2Feature
est appelé, en demandant des ressources jette unNullPointerException
. @PaulSamsothaLa réponse sélectionnée dates à partir d'un certain retour. Il n'est pas possible de déclarer tous les contraignant à une coutume HK2 classeur.
J'utilise Tomcat et j'ai juste eu à ajouter une dépendance. Même si il a été conçu pour Glassfish, il s'intègre parfaitement dans d'autres récipients.
Assurez-vous que votre récipient est correctement configurée (voir la documentation).
En retard mais j'espère que cela aide quelqu'un.
J'ai mon JAX RS définie comme ceci:
Puis, dans mon code je peux enfin injecter:
Dans mon cas, le
SomeManagedBean
est un ApplicationScoped bean.Espère que cette aide à la personne.
Oracle recommande d'ajouter le @Path annotation à tous les types de être injecté lors de la combinaison de JAX-RS avec le CDI:
http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm
Mais c'est loin d'être parfait (par exemple, vous obtiendrez avertissement de Jersey au démarrage), j'ai décidé de prendre cette route, qui me permet de gagner de la maintenance de tous les types pris en charge dans un classeur.
Exemple:
Si vous préférez utiliser Guice et vous ne voulez pas de déclarer toutes les liaisons, vous pouvez également essayer cette carte:
guice-pont-jit-injecteur
Pour moi, il fonctionne sans le
AbstractBinder
si je comprend les dépendances suivantes dans mon application web (en cours d'exécution sur Tomcat 8.5, Maillot 2.27):Il fonctionne avec le CDI 1.2 /CDI 2.0 pour moi (à l'aide de Soudure 2 /3, respectivement).