0

I'm currently using Jersey, Grizzly and Gradle in a web project and I'm attempting to get dependency injection working with HK2. I've followed the instructions in the documentation (https://hk2.java.net/2.5.0-b04/inhabitant-generator.html) for getting the HK2 Metadata Generator working with Gradle. However, when I run my application, I get following exception:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IApiKeyRepository,parent=AuthService,qualifiers={},position=-1,optional=false,self=false,unqualified=null,293474277)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:75)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:211)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:234)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:357)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:83)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:71)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:122)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2020)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:114)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:693)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:78)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:211)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:234)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:357)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:83)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:71)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:122)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2020)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:114)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:88)
at org.glassfish.jersey.internal.inject.Providers.getAllRankedProviders(Providers.java:247)
at org.glassfish.jersey.server.ApplicationHandler.getProcessingProviders(ApplicationHandler.java:772)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:537)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:184)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:350)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:347)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:347)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.<init>(GrizzlyHttpContainer.java:349)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(GrizzlyHttpServerFactory.java:238)
at com.neuro.track.web.api.ApplicationConfig.main(ApplicationConfig.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

As you can see, DI is not working. My application's main method looks like this:

public static void main(String[] args) throws Exception {
    final ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
    final ResourceConfig resourceConfig = new ApplicationConfig();
    resourceConfig.packages("com.package")
    final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, resourceConfig, locator);

    Runtime.getRuntime().addShutdownHook(new Thread(server::shutdownNow));

    server.start();
}

My assumption is that the HK2 Metadata Generator package will scan my project and automatically register all classes annotated with the @Service class without me needed to register the classes explicitly. However, nothing I do will cause those services to register. I really want to avoid having to manually add service classes myself since this project will be growing quite large. Also, I'm trying to avoid an additional build step using the HK2 Inhabitant Generator library. Is there something I'm missing in order to get the HK2 Metadata Generator package to automatically register my services when running my application?

Vincent Catalano
  • 2,259
  • 4
  • 22
  • 29
  • 1
    Have you checked the locator to see if your services are there? `locator.getService(Service.class)` – Paul Samsotha Jul 01 '16 at 01:49
  • You can [add a check](http://stackoverflow.com/q/34433454/2587435) in your code to make sure, and maybe log a warning or just fail. This way you know you need to fix something with the setup. – Paul Samsotha Jul 01 '16 at 02:10
  • What do you mean by saying that you want to avoid *an additional build step*? You need to have the `META-INF/hk2-locator/default` generated, right? This is what the doc you linked is all about. HK2 will read this file during runtime and serve you the `@Service` annotated classes. Are you looking for a way to generate this information during runtime? If so why don't you use standard injection annotations? – Stepan Vavra Jul 01 '16 at 08:52
  • FYI, the generated `META-INF/hk2-locator/default` file contains lines such as `[my.package.jaxrs.service.MyService]S`. Then, you're able to get the service by calling `MyService service = locator.getService(MyService.class);` – Stepan Vavra Jul 01 '16 at 09:00
  • I'm wondering if it wouldn't be better to use a Populator (https://hk2.java.net/2.5.0-b06/apidocs/org/glassfish/hk2/api/Populator.html) from a DynamicConfigurationService (https://hk2.java.net/2.5.0-b06/apidocs/org/glassfish/hk2/api/DynamicConfigurationService.html) using Jersey's own ServiceLocator rather than creating your own. You can use the Populator to easily read the files generated in your build step – jwells131313 Jul 01 '16 at 17:35

1 Answers1

1

It turns out that I was using the wrong @Contract decorator for my interface. I was using org.glassfish.jersey.spi.Contract instead of org.jvnet.hk2.annotations.Contract.

Vincent Catalano
  • 2,259
  • 4
  • 22
  • 29