Just to close this loop… I just finished an iteration, following the advice presented in this thread. I think that I have been able to successfully deal with all my concurrency troubles.
Thanks for the tips! Cheers, =David > On Jul 23, 2018, at 16:36, Tim Ward <tim.w...@paremus.com> wrote: > > An alternative way to look at this is simply that your DS component needs to > be sufficiently thread-safe to deal with the consequences of its own internal > threading model. In this case: > >> What would be a good (and simple) strategy to handle this type of >> long-running configuration, where the configuration is in a different thread >> and depends on services that may come and go? > > Long-running asynchronous activation isn’t where DS really shines for several > reasons: > > There’s no way to tell DS that your component activation is asynchronous. > Once the activate method returns then DS will give your object to the client > bundle. As you’ve already discovered, Promises can make this much simpler to > deal with. > As you’ve seen, the DS “happens before” model is based on when your activate > method returns. Once you go into another thread you have to deal with the > consequences of that > If your long-running activation fails, then it’s too late to tell DS that the > component is broken. To be safe here you really need to disable your > component on failure. > > That said, it is perfectly possible to activate asynchronously in a safe way. > It’s just very important to signal to any thread(s) that you started that > they need to stop and abandon their work. Thread.interrupt() is useful here, > as is having an AtomicBoolean flag in your component that you set to false > during deactivation. These states should be checked regularly during startup, > and the “startup thread" should be prepared to abandon any work it has done > if/when it has become invalid. > > Best Regards, > > Tim > >> On 23 Jul 2018, at 08:00, Peter Kriens via osgi-dev <osgi-dev@mail.osgi.org >> <mailto:osgi-dev@mail.osgi.org>> wrote: >> >> >> >> Ok … on the top of my head … >> >> >> public interface Bar { >> void m1(); >> void m2(); >> } >> >> @Component >> public class BarImpl implements Bar { >> Deferred<Bar> delegate = new Deferred<>(); >> >> @Reference >> void setExec( Executor e ) { >> delegate.resolve( new BarImpl2(e) ); >> } >> >> >> public void m1() { >> delegate.getPromise().m1(); >> } >> >> public void m2() { >> delegate.getPromise().m2(); >> } >> } >> >> This works for you? >> >> Kind regards, >> >> Peter Kriens >> >> >> >>> On 22 Jul 2018, at 22:51, David Leangen via osgi-dev >>> <osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>> wrote: >>> >>> >>> Hi Peter, >>> >>> Thanks for the tip. >>> >>> I’m not quite getting it. Would you be able to direct me to an example? >>> >>> Thanks! >>> =David >>> >>> >>> >>>> On Jul 22, 2018, at 21:49, Peter Kriens <peter.kri...@aqute.biz >>>> <mailto:peter.kri...@aqute.biz>> wrote: >>>> >>>> In some cases (when the extra complexity was warranted) I let the >>>> component class act as a proxy to a delegate. I then get the delegate from >>>> a Promise. So you just forward every method in your service interface to >>>> the delegate. There is a function in Eclipse that will create the >>>> delegation methods. >>>> >>>> In general you want to afford this complexity and for example use a simple >>>> init() method that blocks until init is done. However, the delegate has >>>> some nice qualities if you switch more often than just at init. >>>> >>>> Kind regards, >>>> >>>> Peter Kriens >>>> >>>>> On 22 Jul 2018, at 10:35, David Leangen via osgi-dev >>>>> <osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>> wrote: >>>>> >>>>> >>>>> Hi, >>>>> >>>>> This may be more of a basic Java question, but I’ll ask it anyway because >>>>> it relates to “bouncing” and the handling of dynamic behavior. >>>>> >>>>> In my @Activate method, I configure my component. Since the configuration >>>>> may be long-running (data is retrieved remotely), I use a Promise. But, >>>>> the component is available before it is actually “ready”. So far, this >>>>> has not been a problem. >>>>> >>>>> It looks something like this: >>>>> >>>>> @Reference private Store dataStore; >>>>> >>>>> @Activate >>>>> void activate() { >>>>> configure(dataStore); >>>>> } >>>>> >>>>> void configure(Store withDataStore) { >>>>> // Configuration is set up via a Promise, using a data store to retrieve >>>>> the data >>>>> } >>>>> >>>>> However, because there is some bouncing occurring, I think what is >>>>> happening is that configure() starts running in a different thread, but >>>>> in the meantime the reference to the dataStore is changed. The error log >>>>> shows that the data store is in an impossible state. After following a >>>>> hunch, I could confirm that the configureData process is running on a >>>>> data store service that was deactivated during bouncing. >>>>> >>>>> What would be a good (and simple) strategy to handle this type of >>>>> long-running configuration, where the configuration is in a different >>>>> thread and depends on services that may come and go? >>>>> >>>>> >>>>> Note: in the end, the component gets configured and the application runs, >>>>> but I would still like to be able to handle this situation properly. >>>>> >>>>> >>>>> Thanks! >>>>> =David >>>>> >>>>> >>>>> _______________________________________________ >>>>> OSGi Developer Mail List >>>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>>> >>> >>> _______________________________________________ >>> OSGi Developer Mail List >>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>> https://mail.osgi.org/mailman/listinfo/osgi-dev >> >> _______________________________________________ >> OSGi Developer Mail List >> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >> https://mail.osgi.org/mailman/listinfo/osgi-dev >
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev