javajava-8jersey-2.0hk2

How to inject object with HK2 in main method in a embedded Grizzly Jersey application


I have a catch 22 problem while designing REST micro services using Jersey. I'm trying to create an application with an embedded grizzly server to reduce deployment complexity. Therefore, I have a main method that creates a grizzly server. I need to inject some object before the server's bootstrap procedure.

My main looks like this:

public static void main(String[] args) {
    App app = new App(new MyResourceConfig());
    // Need to inject app here.
    app.init(args);
    app.start();        
}

How can I get the ServiceLocator singleton instance so I can inject my app object?

I tried:

ServiceLocatorFactory.getInstance()
                     .create("whatever")
                     .inject(app);

However, I need to bind all AbstractBinder onto it twice (because I'm already doing it in my ResourceConfig).


Solution

  • Bind all you AbstractBinders to the ServiceLocator you are creating, then pass that locator to one of the Grizzly server creating factory methods. This will be the parent locator that Jersey will just extract all the services from and stick them into another locator. For example something like

    ServiceLocator serviceLocator = SLF.getInstance().create(...);
    ServiceLocatorUtilities.bind(serviceLocator, new Binder1(), new Binder2());
    App app = new App();
    serviceLocator.inject(app);
    HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
            URI.create(BASE_URI),
            resourceConfig, 
            serviceLocator
    );
    

    You need to make sure you have the Jersey-Grizzly dependency and not just Grizzly.

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-http</artifactId>
    </dependency> 
    

    See Also:

    Note:

    If you are trying to create a Grizzly servlet container with GrizzlyWebContainerFactory, trying to make the above work will be difficult. There's is no factory method to pass a locator. Jersey did add support with a property ServletProperties.SERVICE_LOCATOR, but even then, the property value should be a ServiceLocator. The factory method for the grizzly servlet container only accept Map<String, String> for init-params. This property was actually added by a third-party contributor that was using Jetty embedded, which did have methods to set init-params with the values as objects. So if you want support for this, you may want to file an issue with Jersey.