Jersey Hk2 Injection @Service annotated classes

Throughout life, I cannot get Jersey with hk2 to automatically open annotated @Service classes and introduce them. I tried to follow all the tips for stack overflow, jersey and documentation on hk2 and still no luck. I am trying to introduce a simple echo service to a Jersey resource. The skeleton is created from a simple japp webapp maven archetype that I was trying to expand. This is what I have so far:

pom.xml

<build> <finalName>sandbox</finalName> <plugins> <plugin> <groupId>org.glassfish.hk2</groupId> <artifactId>hk2-inhabitant-generator</artifactId> <version>2.3.0</version> <executions> <execution> <configuration> <verbose>true</verbose> </configuration> <goals> <goal>generate-inhabitants</goal> </goals> </execution> </executions> </plugin> </plugins> </build> ... <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.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> </dependency> <dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>hk2</artifactId> <version>2.3.0</version> </dependency> </dependencies> 

web.xml

 <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>my.package.jerseytest</param-value> </init-param> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>my.package.jerseytest.application.Application</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 

my.package.jerseytest.application.Application

 public class Application extends ResourceConfig { public Application() { ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); } } 

my.package.jerseytest.service.EchoService

 @Service public class EchoService { public String generateResponse(String echo) { return echo; } } 

my.package.jerseytest.resource.MyResource

 @Path("myresource") public class MyResource { @Inject EchoService echoService; @GET @Produces(MediaType.TEXT_PLAIN) public String getIt() { return echoService.generateResponse("Got it!"); } } 

I checked that the inhibitor generator really starts and produces its output, but when starting the Tomcat server getting http://localhost:8080/sandbox/webapi/myresource I get

 SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/sandbox] threw exception [A MultiException has 3 exceptions. They are: 1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EchoService,parent=MyResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,932014249) 2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of my.package.jerseytest.resource.MyResource errors were found 3. java.lang.IllegalStateException: Unable to perform operation: resolve on my.package.jerseytest.resource.MyResource ] with root cause org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EchoService,parent=MyResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,932014249) 

Any ideas what I am missing? I would be grateful for any help :(

NB! I know about

but they didn’t help me ...

+6
source share
5 answers

I combined the understanding that I received from these two questions:

First, use the HK2 Metadata Generator (or the residential generator) in your build chain (as you already did). This scans your source and creates META-INF/hk2-locator/default .

Secondly, create a new ServiceLocator populated with services from metadata:

 ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); 

Now pass on to Grizzly . Quoting @peeskillet :

Jersey has its own ServiceLocator, and it’s not easy to try to get a link to it. We could provide Jersey with our ServiceLocator, but Jersey ultimately still creates its own locator and populates it with our locator.

 ResourceConfig config = new MyApplicationConfig(); HttpServer server = GrizzlyHttpServerFactory.createHttpServer( URI.create(BASE_URI), config, serviceLocator ); 
+1
source

I solved my problem just like this, using a class that extends AbstractBinder, instantiating and registering it with the application.

 resourceConfig.register(new DependencyBinder()); 

Besides,

 /** * dependency injection bindings. * Jersey requires that service implementations are bound to their contracts this way. */ public final class DependencyBinder extends AbstractBinder { @Override protected final void configure() { bind(StatusServiceImpl.class).to(StatusService.class); } } 
+1
source

Try adding packages that you want to scan in the Application constructor. The true option in packets means scanning the packet recursively:

 public class Application extends ResourceConfig { public Application() { packages(true, "my.package.jerseytest"); ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); } } 
0
source

Use packages(true, "my.package.jerseytest"); And use the annotation org.glassfish.jersey.spi.Contract not org.jvnet.hk2.annotations.Contract . And use simple interfaces without generics.

0
source

Try adding @Stateless

 @Path("myresource") @Stateless public class MyResource { @Inject EchoService echoService; ... } 
0
source

Source: https://habr.com/ru/post/976336/


All Articles