jerseyosgiapache-felixbndtools

OSGI REST "Jersey is not ready yet" - Cannot find a default implementation of the HK2 ServiceLocatorGenerator


I am trying to get a simple osgi rest endpoint working using osgi-jax-rs-connector, jersey, and bndtools.

I'm wrapping the publisher-5.3.1.jar bundle and jersey-all-2.22.2.jar bundles (both provided by osgi-jax-rs-connector) into my own separate bundle. I have another bundle of my own which provides the rest endpoint using annotations.

I am able to resolve and run it in Apache Felix using a bndrun file, and verify in the gogo shell that my own rest endpoint is registered as an osgi service used by com.eclipsesource.jaxrs.publisher.

When the app starts up it logs:

org.glassfish.hk2.utilities.reflection.Logger warning
WARNING: Cannot find a default implementation of the HK2 ServiceLocatorGenerator

When I attempt to hit my api from a browser I get:

HTTP ERROR: 503
Problem accessing /services/my-service. Reason:
Jersey is not ready yet!
Powered by Jetty:// 

My wrapped jersey/publisher bnd.bnd file is:

Bundle-Version: 2.22.2.${tstamp}

javac.source: 1.8
javac.target: 1.8

-includeresource: OSGI-OPT/src=@libsrc/jersey-publisher.jar
-classpath: lib/jersey-all-2.22.2.jar, lib/publisher-5.3.1.jar
-sources: true

Export-Package: javax.ws.rs*;version=2.0,\
    org.jvnet.hk2.annotations;version="1.0",\
    org.jvnet.hk2.component;version="1.0",\
    org.jvnet.hk2.external.generator;version="1.0",\
    org.jvnet.hk2.external.runtime;version="1.0";uses:="org.jvnet.hk2.annotations",\
    org.jvnet.hk2.internal;version="1.0";uses:="org.jvnet.hk2.external.runtime",\
    org.jvnet.mimepull;version="1.0",\
    org.jvnet.tiger_types;version="1.0"

-privatepackage: *

Import-Package: !jersey.repackaged.com.google.common.cache.LocalCache.jersey.repackaged.*,\
    !jersey.repackaged.com.google.common.collect.AbstractMapBasedMultimap.jersey.repackaged.*,\
    !jersey.repackaged.com.google.common.collect.AbstractMultimap.jersey.repackaged.*,\
    !jersey.repackaged.com.google.common.collect.FilteredKeyMultimap.jersey.repackaged.*,\
    !jersey.repackaged.com.google.common.collect.ImmutableMultimap.jersey.repackaged.*,\
    !jersey.repackaged.com.google.common.collect.MapMakerInternalMap.jersey.repackaged.*\
    *

I can see that org.jvnet.hk2.external.generator.ServiceLocatorGeneratorImpl is a class that implements the ServiceLocatorGenerator interface that is included in the active jersey-all bundle jar file as well as my generated wrapping bundle jar that wraps it.


Solution

  • The HK2 ServiceLocatorGenerator error refers to the fact that the jersey-all jar contains several provider-configuration files related to class java.util.ServiceLoader simple service providing library in the jdk (see https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).

    These services originally existed in the hk2-locator jar file, which is a Jersey dependency.

    This was fixed by having my wrapping bundle include the file from META-INF/services/org.glassfish.hk2.extension.ServiceLocatorGenerator in the jersey-all.jar. The bnd declaration that accomplishes this is

    -includeresource: @lib/jersey-all-2.22.2.jar!/META-INF/services/org.glassfish.hk2.extension.ServiceLocatorGenerator
    

    This completely fixed the issue and caused my rest endpoint to work successfully.

    Interestingly, when I had the bnd declare that the other META-INF/services/* files be included in the generated bundle the result was several more errors, but simply restricting it to the ServiceLocatorGenerator solved everything.