>>>>> Steinar Bang <[email protected]>:

>> The service definition is
>> https://github.com/steinarb/ukelonn/blob/5ca75f438407c594ed476bed790d984b0007cfdf/ukelonn.api/src/main/java/no/priv/bang/ukelonn/UkelonnService.java#L36

>> The service implementation, is this DS component
>> https://github.com/steinarb/ukelonn/blob/5ca75f438407c594ed476bed790d984b0007cfdf/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnServiceProvider.java#L42

>> However, with Jersey getting injection of the above service into the
>> resource classes isn't so easy.

> Based in the following two stackoverflow threads I have a tentative plan
> for getting the service injected into Jersey resources using my current
> stack (ie. karaf 4.1.5 and OSGi 6.0.0):
>  
> https://stackoverflow.com/questions/38373867/inject-dao-instance-into-jersey-resource?noredirect=1&lq=1
>  
> https://stackoverflow.com/questions/16216759/dependency-injection-with-jersey-2-0
[snip!]

> Outline of my plan:
>  1. Make the service implementation extend ResourcesConfig

Turns out this wasn't necessary.  What's @Inject'ed into Jersey
resources by HK2 JSR330 injections, can be any class.

>  2. Create a class extending AbstractBinder, that in its configure()
>     method will bind an instance of the service implmentation to the
>     UkelonnService interface

I ended up just creating an anonymous inner and registering it
immediately.

>  3. In the @Activate method of the service implementation, register the
>     activated instance with Jersey, using the AbstractBinder above

This was wrong.  The instances that needs to be injected, must bek
registered with the ResourceConfig used by the ServletContainer.  They
cannot be registered with any old ResourceConfig.

>  4. In the resource classes use JSR330 @Inject of the UkelonnService

This was as predicted.  Needed to 

>  5. Create a whiteboard DS service from the JerseyServletContainer, with:
>     a. param configuration configuring a package to scan for resources
>     b. add a @Reference for an UkelonnService and an @Activate method, to
>        ensure that the servlet isn't activated, and plugged into the
>        whiteboard until a service is available that can be injected into
>        the created resources (and it should also ensure the servlet is
>        taken down if the UkelonnService implementation is taken down)

Actually, the ServletContainer DS component needs to have the
UkelonnService (and an OSGi LogService) injected as OSGi services,
because it needs to register them as instances in its ResourceConfig.

The trick to get everything working, was to first have the
ServletContainer create a ResourceConfig object containing all of the
servlet setup, then copy that ResourceConfig and register OSGi services
for Jersey injection and reload the ServletContainer with the copy.

The procedure to get Jersey working with OSGi services UkelonnService
and LogService injected into the Jersey resource objects, is then as
follows: 
 1. Create a whiteboard DS component exposing a Servlet service from
    Jersey ServletContainer, configuring the package to scan for API
    resources:
     
https://github.com/steinarb/ukelonn/blob/59c6c693027e6d400ccd9e6b1777ce7f5adb4096/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/api/UkelonnRestApiServlet.java#L37
 2. Make the DS component of ServletContainer depend on OSGi services
    UkelonnService and LogService
     
https://github.com/steinarb/ukelonn/blob/59c6c693027e6d400ccd9e6b1777ce7f5adb4096/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/api/UkelonnRestApiServlet.java#L74
 3. Override the ServletContainer.init(WebConfig) method, and:
    a. Call super.init(WebConfig) to make sure that a ServletConfig
       containing the information set up by the http whiteboard is
       created (contains the servletcontext, the servlet name and the
       package to scan for Jersey resources)
        
https://github.com/steinarb/ukelonn/blob/59c6c693027e6d400ccd9e6b1777ce7f5adb4096/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/api/UkelonnRestApiServlet.java#L57
    b. Copy the ResourceConfig of the ServletContainer (because that
       ServletConfig is immutable after the setup, and calling
       ServletConfig.register() will cause an IllegalOperationException)
    c. On the ServletConfig copy, register an anonymous inner inheriting
       AbstractBinder that in its configure() method registers the
       OSGi services injected into the ServletContainer as JSR330
       injections in the Jersey resources
    d. Call ServletContainer.reload(ResourceConfig) with the
       ResourceConfig copy as the argument
  4. In the resources use JSR330 injections of UkelonnService and/or
     LogService, e.g.
      
https://github.com/steinarb/ukelonn/blob/59c6c693027e6d400ccd9e6b1777ce7f5adb4096/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/api/resources/RegisterJob.java#L32

Reply via email to