Reputation: 1493
I tried to understand from the OSGi specs what it should happen in case an activate method blocks indefinitely but I did not find an answer. On the other hand, it seams that that Felix SCR has ds.lock.timeout.milliseconds
and ds.stop.timeout.milliseconds
properties to manage activate/deactivate timeouts, right?
Questions:
ds.lock.timeout.milliseconds
value? Or is it better to avoid the activate method altogether and register the service "by hand" using context.registerService
in a dedicated thread?Upvotes: 4
Views: 336
Reputation: 1000
As suggested in this video OSGI Best Practices by Eclipse Foundation, you can start long lasting job in a seperate thread then register your service manually.
@Activate
public void activate(BundleContext context) {
this.context = context;
this.reg = CompletableFuture.supplyAsync(this::longRunning);
}
@Deactivate
public void deactivate() {
this.reg.thenAcceptAsync(ServiceRegistration::unregister);
}
private ServiceRegistration<TaskService> longRunning() {
// long running call
return context.registerService(TaskService.class, this, new Hashtable<String, String>());
}
Upvotes: 0
Reputation: 15372
If you have a long initialization you mark the component immediate
. In the activate method you start a background initialization. When your service is called, you block until the initialization is done. (Promises work very nice for this technique.)
@Component(immediate=true)
public class FooImpl implements Foo {
Promise<Foo> promise;
@Activate void activate() { promise = begin(); }
@Override
public void foo() { promise.get().foo(); }
}
The advantage of this technique is that it allows many initializations to proceed in parallel.
The delegation you need is kind of ugly. If performance is not overly important you can easily create a proxy doing the actual work.
Upvotes: 1
Reputation: 19626
As far as I know the only safe method is to spawn another thread in activate and register the service when your async code is finished.
Upvotes: 4