Jersey and HK2 ServiceLocator

I am trying to initialize some components in a Jersey application in the Application constructor (a thing that inherits from ResourceConfig). Looks like this

public Application(@Context ServletContext context, @Context ServiceLocator locator)... 

When I try to use the locator at any time, I still cannot instantiate the things that I registered with AbstractBinder using the locator.create (MyThing.class) method.

I am sure that they are connected correctly because they are correctly injected into my resource classes through the annotation of the @inject field.

The difference is that the Jersey / HK2 structure creates instances of my resource classes (as expected, since they are in the package scan path), but I cannot use ServiceLocator with the code.

My ultimate goal is to introduce other non-standard classes if they have the @Inject attribute, for example. I have a working class that needs to enter a configured database access level. I want to say

 locator.Create(AWorker.class) 

and enter it.

How to get a real ServiceLocator that will enter everything that I have already registered / associated with my Binder? (Or should I use something other than ServiceLocator?)

+2
source share
2 answers

How do you launch your container? If you use ApplicationHandler, you can simply call: handler.getServiceLocator() . ServiceLocator is what you want to use to access your dependencies.

If you run the servlet, I find that the best way to access the service locator is to set the Jersey function in its launch class:

  private static final class LocatorSetFeature implements Feature { private final ServiceLocator scopedLocator; @Inject private LocatorSetFeature(ServiceLocator scopedLocator) { this.scopedLocator = scopedLocator; } @Override public boolean configure(FeatureContext context) { locator = this.scopedLocator; // this would set our member locator variable return true; } } 

This function will simply be registered in our configuration file with config.register (new LocatorSetFeature ()).

It would be important to link other components at startup, based on the life cycle of your container, so this still seems a bit odd. You can consider adding these classes as first-class dependencies in the HK2 container and simply injecting the corresponding dependencies into your third-party classes (for example, using Binder).

+2
source

I assume that you are an org.glassfish.jersey.server.ResourceConfig servlet and you have a class extending org.glassfish.jersey.server.ResourceConfig and your bindings are correctly registered (e.g. using Binder and registerInstances). If you then want to access the ServiceLocator to perform additional initialization, you have two options:

One approach is to register a ContainerLifecycleListener (as shown here in this post ):

 // In Application extends ResourceConfig constructor register(new ContainerLifecycleListener() { @Override public void onStartup(final Container container) { // access the ServiceLocator here final ServiceLocator serviceLocator = container.getApplicationHandler().getInjectionManager().getInstance(ServiceLocator.class); // Perform whatever with serviceLocator } @Override public void onReload(final Container container) { /* ... */} @Override public void onShutdown(final Container container) { /* ... */} }); 

The second approach is to use Feature , which can also be automatically detected using @Provider :

 @Provider public final class StartupListener implements Feature { private final ServiceLocator sl; @Inject public ProvisionStartupListener(final ServiceLocator sl) { this.sl = sl; } @Override public boolean configure(final FeatureContext context) { // Perform whatever action with serviceLocator return true; } 
+1
source

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


All Articles