How can I cleanly override the standard ServiceLocator used by Jersey?

I am developing an application that uses Jersey (2.5) as its REST interface, and Jetty as an embedded HTTP (S) server, using the so-called "embedded" method, for example. without resorting to creation .warand deployment, but through the software configuration of handlers, resources, injections ...

I would like to somehow override HK2 ServiceLocator, which is used on the server side by Jersey, or perhaps provide this service locator with a parent to resolve dependencies that are defined outside of the REST part of the application. From what I see in the code, this is not possible: a ServiceLocator is created internally ApplicationHandlerby a call Injections:

if (customBinder == null) {
        this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder());
    } else {
        this.locator = Injections.createLocator(new ServerBinder(application.getProperties()), new ApplicationBinder(),
                                                customBinder);
    }

And the code in Injections tells me the following:

 public static ServiceLocator createLocator(Binder... binders) {
    return _createLocator(null, null, binders);
 }

which means that the newly created service locator has some kind of randomly generated name and does not have a parent.

Is there a (clean) way to change this behavior so that I introduce my own ServiceLocator as the application parent?

+4
source share
3 answers

I know this answer was a bit late. I struggled with the same problem, but as part of the Dropwizard. After some debugging, I saw some lines of code that made me happy!

final ServiceLocator locator = (ServiceLocator) webConfig.getServletContext()
            .getAttribute(ServletProperties.SERVICE_LOCATOR);

This piece of code is inside the constructor of WebComponent jerseyes. So the solution is to provide ServletProperties.SERVICE_LOCATORfor your ServletContext. In the Dropwizard environment, I achieved this by doing

environment.getApplicationContext().getAttributes().setAttribute(ServletProperties.SERVICE_LOCATOR, locator);
+5

, jwells131313 bridgeServiceLocator API.

EDIT: , HK2 , Singleton ServiceLocator, , Singleton. . / .

# 2: ​​, ServiceLocator. hk2 2.5.0-b07

Feature ( ServletContainer).

public class InjectionBridge implements Feature
{
  private static ServiceLocator _applicationServiceLocator;

  private final ServiceLocator _serviceLocator;

  @Inject
  private InjectionBridge(ServiceLocator serviceLocator)
  {
    _serviceLocator = serviceLocator;
  }

  @Override
  public boolean configure(FeatureContext context)
  {
    if (_applicationServiceLocator != null)
      ExtrasUtilities.bridgeServiceLocator(_serviceLocator, _applicationServiceLocator);
    return true;
  }

  public static void setApplicationServiceLocator(ServiceLocator applicationServiceLocator)
  {
    _applicationServiceLocator = applicationServiceLocator;
  }
}

setApplicationServiceLocator ServiceLocator, , .

, RESTful @Inject , .

+3

ServiceLocator ServiceLocator.

However, with hk2 2.4.0-b11 it will be possible to have a ServiceLocator → ServiceLocator bridge. Thus, all the services of your ServiceLocator can be placed in the ServiceLocator of Jersey (or any other ServiceLocator). This is the API: bridgeServiceLocator . It is located in the hk2-extras hk2 module.

There is a version of this in hk2 2.4.0-b10 that should work, a fully tested and documented function will be in hk2 2.4.0-b11

+2
source

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


All Articles