0

I have a Jersey endpoint which uses a custom OSGi Service ExceptionManager Service.

@Path("service")
public class ServiceFacade {
    private volatile ExceptionManager exceptionManager;

    public ServiceFacade() {
        BundleContext bC = FrameworkUtil.getBundle(ServiceFacade.class).getBundleContext();
        ServiceReference<ExceptionManager> sR = bC.getServiceReference(ExceptionManager.class);
        if (sR != null)
            this.exceptionManager = bC.getService(sR);
    }

    @GET
    @Consumes({MediaType.APPLICATION_JSON})
    @Produces(MediaType.APPLICATION_JSON)
    public Response sayHello() {
        try {
            if (exceptionManager == null)
                return Response.status(Status.SERVICE_UNAVAILABLE).build();

            // Do some work...
        } catch (Exception e) {
           exceptionManager.handle(e);
        }
    }
}

This Jersey class is added to the Jersey Application as a simple class, that means that every time a user hits this endpoint, a new instance of this class is created to handle the request. As you can see, the class contains a constructor which initializes the ExceptionManager Service. My question is, isn't there a simplified way of retrieving the service without going to BundleContext?

I have seen DependencyManager, but this bundle seems to only add the dependencies to the class (ServiceFacade in this case) during the Activation process, but that dependency resolution is too early this has to be done during run-time, every time an instance is created. Bellow is an approximation with DependencyManager but is not a solution for this:

public class Activator extends DependencyActivatorBase {
    @Override
    public void init(BundleContext bundleContext, DependencyManager dependencyManager) throws Exception {
       dependencyManager.add(createComponent()
                  .setImplementation(ServiceFacade.class)
                  .add(createServiceDependency()
                               .setService(ExceptionManager.class)
                               .setRequired(true));
    }
}

Thanks.-

Joe Almore
  • 4,036
  • 9
  • 52
  • 77

2 Answers2

0

You can obtain the reference to an OSGi service without accessing to BundleContext by using Declarative Services. A tutorial can be found here.

0

You can make the endpoint a singleton resource. This way you can let the dependency manager create a single instance and inject services and then add that instance to the Jersey application.

There are a few limitations, like Jersey's field or constructor injection does not work. You also have to be careful about concurrency when using fields of the resource.

kapex
  • 28,903
  • 6
  • 107
  • 121