Service - the service type for this callerpublic class ServiceCaller<Service>
extends java.lang.Object
ServiceCaller provides functional methods for invoking OSGi services
in two different ways
For single invocations of a service the static method
callOnce(Class, Class, Consumer) can be used.
This method will wrap a call to the consumer of the service with
the necessary OSGi service registry calls to ensure the service
exists and will do the proper get and release service operations
surround the calls to the service. By wrapping a call around the
service we can ensure that it is correctly released after use.
Single invocation example:
ServiceCaller.callOnce(MyClass.class, ILog.class, (logger) -> logger.info("All systems go!"));
Note that it is generally more efficient to use a long-running service
utility, such as ServiceTracker or declarative services, but there
are cases where a single one-shot lookup is preferable, especially if the
service is not required after use. Examples might include logging unlikely
conditions or processing debug options that are only read once.
This allows boilerplate code to be reduced at call sites, which would otherwise have to do something like:
Bundle bundle = FrameworkUtil.getBundle(BadExample.class);
BundleContext context = bundle == null ? null : bundle.getBundleContext();
ServiceReference<Service> reference = context == null ? null : context.getServiceReference(serviceType);
try {
Service service = reference == null ? null : context.getService(reference);
if (service != null)
consumer.accept(service);
} finally {
context.ungetService(reference);
}
For cases where a service is used much more often a ServiceCaller instance
can be used to cache and track the available service. This may be useful for cases
that cannot use declarative services and that want to avoid using something like
a ServiceTracker that does not easily allow for lazy instantiation of the service
instance. For example, if logging is used more often then something like the following
could be used:
static final ServiceCaller<ILog> log = new ServiceCaller(MyClass.class, ILog.class);
static void info(String msg) {
log.call(logger -> logger.info(msg));
}
Note that this class is intended for simple service usage patterns only. More advanced cases
should use other mechanisms such as the ServiceTracker or declarative services.
| Constructor and Description |
|---|
ServiceCaller(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType)
Creates a
ServiceCaller instance for invoking an OSGi
service many times with a consumer function. |
ServiceCaller(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.lang.String filter)
Creates a
ServiceCaller instance for invoking an OSGi
service many times with a consumer function. |
| Modifier and Type | Method and Description |
|---|---|
boolean |
call(java.util.function.Consumer<Service> consumer)
Calls an OSGi service by dynamically looking it up and passing it to the given consumer.
|
static <Service> boolean |
callOnce(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.util.function.Consumer<Service> consumer)
Calls an OSGi service by dynamically looking it up and passing it to the given consumer.
|
static <Service> boolean |
callOnce(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.lang.String filter,
java.util.function.Consumer<Service> consumer)
As
callOnce(Class, Class, Consumer) with an additional OSGi filter. |
java.util.Optional<Service> |
current()
Return the currently available service.
|
void |
unget()
Releases the cached service object, if it exists.
|
public ServiceCaller(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType)
ServiceCaller instance for invoking an OSGi
service many times with a consumer function.caller - a class from the bundle that will consume the serviceserviceType - the OSGi service type to look uppublic ServiceCaller(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.lang.String filter)
ServiceCaller instance for invoking an OSGi
service many times with a consumer function.caller - a class from the bundle that will consume the serviceserviceType - the OSGi service type to look upfilter - the service filter used to look up the service. May be null.public static <Service> boolean callOnce(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.util.function.Consumer<Service> consumer)
If not running under OSGi, the caller bundle is not active or the service is not available, return false. If the service is found, call the service and return true.
Any runtime exception thrown by the consumer is rethrown by this method. If the consumer throws a checked exception, it can be propagated using a sneakyThrow inside a try/catch block:
callOnce(MyClass.class, Callable.class, (callable) -> {
try {
callable.call();
} catch (Exception e) {
sneakyThrow(e);
}
});
...
@SuppressWarnings("unchecked")
static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
throw (E) e;
}
Service - the OSGi service type to look upcaller - a class from the bundle that will use serviceserviceType - the OSGi service type to look upconsumer - the consumer of the OSGi servicejava.lang.NullPointerException - if any of the parameters are nullpublic static <Service> boolean callOnce(java.lang.Class<?> caller,
java.lang.Class<Service> serviceType,
java.lang.String filter,
java.util.function.Consumer<Service> consumer)
callOnce(Class, Class, Consumer) with an additional OSGi filter.Service - the OSGi service type to look upcaller - a class from the bundle that will use serviceserviceType - the OSGi service type to look upconsumer - the consumer of the OSGi servicefilter - an OSGi filter to restrict the services foundjava.lang.NullPointerException - if any of the parameters are nullpublic boolean call(java.util.function.Consumer<Service> consumer)
callOnce(Class, Class, Consumer) for a solution.)
Subsequent calls to this method will attempt to reuse the previously acquired service instance until one
of the following occurs:
unget() method is called.ServiceCaller filter no longer matches.
consumer - the consumer of the OSGi servicepublic java.util.Optional<Service> current()
public void unget()
call(Consumer) will
lazily get the service instance again and cache the new
instance if found.