I think the following statement is not correct: It is indeed part of the spec that a component should avoid blocking in activate/deactivate callbacks: a DS implementation might actually skip and/or blacklist a component that takes too much time to activate or deactivate.
Thought it is better for a component to have fast activate/deactivate methods that would have no use if the situation then becomes wrong. Blacklisting is only (as far as I remember at least) part of Event Admin. An activate/deactivate method must first be _correct_, regardless of the blocking time. That said, the activate method should return in finite deterministic. Since it blocks all or dependent components from being activated you need to make sure it does end in finite time. In the case you should only register your service if a certain condition is true then you cannot use a component with a service. You would have to use a headless immediate component and register/unregister the service based when the condition changes. For returning, deactivate methods should block until any associated threads have finished. Kind regards, Peter Kriens > On 7 aug. 2016, at 17:37, Simon Chemouil <ecli...@mithrandir.net> wrote: > > list+org.o...@io7m.com a écrit le 07/08/2016 14:01 : >> Hello. > > Hi, > >> As a learning exercise, I've put together a very contrived example of a >> "reverse" service (like an echo service, except that each returned line >> comes back reversed). Mostly, I'm using it as a learning example of how >> to build a small TCP/IP client/server in OSGi. > > You hit a limitation in DS, and a very common one because often > components might need to run blocking code (e.g some SQL queries to make > sure a database is ready/with the right model) and make sure the > services it provides are not exposed before that. > > It is indeed part of the spec that a component should avoid blocking in > activate/deactivate callbacks: a DS implementation might actually skip > and/or blacklist a component that takes too much time to activate or > deactivate. > > Felix SCR does it, and we have run into this before. > > A bad workaround for us was to increase the time limit in SCR, which can > be set using a framework property. > > A better workaround is not to block at all, but avoid using DS for these > blocking calls. You can for instance define a DatabaseReady or > TCPServerReady service and have it as a reference in your DS component. > You then go on to programatically register that service. > > Your problem with port reuse would remain, because activate() can be > called before an async task called by deactivate() has finished. > A solution would be to make sure the same thread is reused for all > TCPServer binding and closing. > > You then have a Setup DS component (it could be in the activator as > well, but would make it difficult to depend on other services): > > @Component > public final class TCPSetup { > > private BundleContext context; > private ServiceRegistration reg; > private TCPServer tcpServer; > > @Reference > private TCPServerManager srvManager; > > > @Activate > public void activate(BundleContext context) { > this.context = context; > Promise<TCPServer> tcpServerPms = srvManager.newServer(port); > tcpServerPms.onResolve(() -> register(tcpServerPms.getValue())); > } > > @Deactivate > public void deactivate() { > if (tcpServer != null) { > Promise<Void> tcpServerClosed = srvManager > .close(tcpServer); > tcpServerClosed.onResolve(() -> reg.unregister()); > } > tcpServer = null; > } > > public void register(TCPServer tcpServer) { > > this.tcpServer = tcpServer; > > // blocking code. > reg = context.registerService(TCPServer.class, tcpServer, null); > > // this thread will potentially activate components depending > // on the service. > } > > } > > TCPServerManager holds a single thread executor that is used for > creating TCPServer instances. > > This way, whatever happens with the lifecycle of your components, you > are sure the bind/close method runs sequentially. There might still be a > problem with the sequence close / restart manager component / bind, but > you get the kind of trickery required to deal with these issues... > > Ideally, TCPServerManager's thread dealing with binding/closing sockets > should not be held statically, but it's a bit tricky to deal with the > restarting of TCPServerManager instances otherwise. > > You'll notice I use the OSGi Promise API rather than callbacks in my > example. It's similar, but I suggest you explore it (if you haven't done > so yet) in your experiments because it gets very handy when dealing with > state, IO and blocking code. > > Things would be much better if DS provided adequate support, for > instance for controlling whether we expose or not services (using the > component context). Other OSGi component frameworks provide this, so I > hope this will eventually get included in DS 1.4. > > Hope this helps, > Simon > > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev