Zaczynając od zera bez wcześniejszej wiedzy na temat Jersey 1.x, trudno mi zrozumieć, jak skonfigurować wstrzykiwanie zależności w moim projekcie Jersey 2.0.
Rozumiem również, że HK2 jest dostępny w Jersey 2.0, ale nie mogę znaleźć dokumentów, które pomogłyby w integracji Jersey 2.0.
@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>
Mogę uruchomić kontener i udostępnić mój zasób, ale gdy tylko dodam @Inject do MyService, framework zgłasza wyjątek:
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)
Mój projekt startowy jest dostępny na GitHub: https://github.com/donaldjarmstrong/jaxrs
źródło
EntityManager
jest, ale sądząc po docs.oracle.com/javaee/6/api/javax/persistence/ ... wydaje się, że jest to interfejs. Możesz go powiązać za pomocąbind(EntityManagerImpl.class).to(EntityManager.class)
(co spowoduje związanie klasyEntityManagerImpl
implementującej interfejsEntityManager
. Jeśli potrzebujesz użyć fabryki, zajrzyjbindFactory()
doAbstractBinder
. Jeśli potrzebujesz pomocy, utwórz nowe pytanie (nie będę mieć miejsca na odpowiedz na to w komentarzach) .Nie jestem również pewien, czy powinieneś używać @PersistentContext, po prostu używaj @Inject do wszystkiegoNajpierw wystarczy odpowiedzieć na komentarz w odpowiedzi akceptuje.
Po prostu czyta
bind( implementation ).to( contract )
. Możesz alternatywnie łańcuch.in( scope )
. Domyślny zakresPerLookup
. Więc jeśli chcesz singletona, możeszJest też
RequestScoped
dostępnyZamiast tego
bind(Class).to(Class)
możesz teżbind(Instance).to(Class)
, co automatycznie będzie singletonem.Dodawanie do zaakceptowanej odpowiedzi
Dla tych, którzy próbują dowiedzieć się, jak zarejestrować twoją
AbstractBinder
implementację w twoim web.xml (tj. Nie używasz aResourceConfig
), wydaje się, że spinacz nie zostanie wykryty przez skanowanie pakietów, tj.Albo to
Aby to zadziałało, musiałem zaimplementować
Feature
:@Provider
Adnotacja powinna umożliwićFeature
być odebrany przez skanowanie pakietu. Lub bez skanowania pakietów, możesz jawnie zarejestrować plikFeature
wweb.xml
Zobacz też:
oraz ogólne informacje z dokumentacji Jersey
AKTUALIZACJA
Fabryki
Oprócz podstawowego powiązania w zaakceptowanej odpowiedzi masz również fabryki, w których możesz mieć bardziej złożoną logikę tworzenia, a także mieć dostęp do żądań informacji kontekstowych. Na przykład
Następnie możesz wstrzyknąć
MyService
do swojej klasy zasobów.źródło
web.xml
choćconfigure()
onHk2Feature
nazywa, żądając zasobów rzucaNullPointerException
. @PaulSamsothaWybrana odpowiedź pochodzi sprzed jakiegoś czasu. Zadeklarowanie każdego powiązania w niestandardowym segregatorze HK2 nie jest praktyczne. Używam Tomcat i po prostu musiałem dodać jedną zależność. Mimo że został zaprojektowany dla Glassfisha, doskonale pasuje do innych pojemników.
Upewnij się, że kontener jest również prawidłowo skonfigurowany ( zobacz dokumentację ).
źródło
Późno, ale mam nadzieję, że to komuś pomoże.
Mam moje JAX RS zdefiniowane w ten sposób:
W końcu w swoim kodzie mogę wstrzyknąć:
W moim przypadku
SomeManagedBean
jest to komponent bean ApplicationScoped.Mam nadzieję, że to pomoże każdemu.
źródło
Oracle zaleca dodanie adnotacji @Path do wszystkich typów, które mają być wstrzykiwane podczas łączenia JAX-RS z CDI: http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm Chociaż jest to dalekie od ideału ( np. otrzymasz ostrzeżenie z Jersey przy starcie), zdecydowałem się na tę trasę, co oszczędza mi utrzymywania wszystkich obsługiwanych typów w segregatorze.
Przykład:
źródło
Jeśli wolisz używać Guice i nie chcesz deklarować wszystkich powiązań, możesz również wypróbować ten adapter:
guice-bridge-jit-injector
źródło
U mnie działa bez,
AbstractBinder
jeśli dołączę następujące zależności w mojej aplikacji internetowej (działającej na Tomcat 8.5, Jersey 2.27):Działa z CDI 1.2 / CDI 2.0 dla mnie (używając odpowiednio Weld 2/3).
źródło
Zależność wymagana do pełnej obsługi koszulki, a Tomcat jest serwerem. gdzie $ {jersey.version} to 2.29.1
Podstawowy kod będzie wyglądał następująco:
źródło