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

流过昼夜 提交于 2019-12-03 16:41:15
Woodbird

I know that this answer is a little late. I struggled with the same issue, but in the Dropwizard framework. After some debugging, I saw the some lines of code which made me happy!

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

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

environment.getApplicationContext().getAttributes().setAttribute(ServletProperties.SERVICE_LOCATOR, locator);
Nathan Brown

We have a similar set up, and I've managed to get our architecture working using jwells131313's new bridgeServiceLocator API.

EDIT : Note that the current HK2 bridging implementation means Singleton instances are only local to the ServiceLocator they are created in, meaning that bridged architectures can contain more than one instance of a Singleton service. Please see this question for more information and a possible workaround/alternative approach.

EDIT #2 : The aforementioned bug in the ServiceLocator bridge has been fixed. The fix will be in hk2 2.5.0-b07 or later

Basically I created a Feature implementation to set up the bridging and registered it with Jersey (in our instance via the 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 is then called from the application code with the ServiceLocator created by the application to manage the application resources.

This means that Jersey RESTful service implementations can now simply declare fields with the @Inject annotation and access those injected resources to service requests.

You can not make one ServiceLocator the parent of another after the ServiceLocator has been created.

However as of hk2 2.4.0-b11 there will be the ability to have a ServiceLocator -> ServiceLocator bridge. Thus all the services from your ServiceLocator can be put into the ServiceLocator of Jersey (or any other ServiceLocator). This is the API: bridgeServiceLocator. It is in the hk2-extras module of hk2.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!