2015-02-13 12:23 GMT+01:00 Christian Schneider <ch...@die-schneider.net>:
> On 13.02.2015 11:58, Guillaume Nodet wrote: > >> >> >> Your example expects a simple restart of the service, I'm talking about an >> update/refresh of the bundle. >> But even restarting the service, if the service is an EntityManager, that >> does not work afaik : you can't just switch it in the middle of your >> processing (what you've already done with the JDBC connection in the >> context of your transaction can't be propagated to a new connection). >> > You are right about a service that provides EntityManger instances. The > problem here is that the service is not really stateless which makes it > much harder to manage. > You could also think about a camel component you want to update. In such a case, you want the routes to cleanly shutdown before actually updating the component. > For a normal EntityManagerFactory (like provided by jpa.container) this > should not apply as the EntityManager is under control of the client bundle. > > In case of jpa.container.context there probably is a problem. The service > holds instances of EntityManager. So if this bundle is updated I would > expect it to close > all EntityManager instances. So the state would be lost. This is a very > special case though and I dont think it would warant the Quiesce support > all for itself. > After all updating aries jpa is rather seldom for a customer compared to > updating their own bundles. So I think it should be ok to handle this case > manually in a special way. > > For updates of user bundles there should be no issue I think. > This problem is a general problem, think about CXF services, camel routes, etc... It may be possible to partially get rid of the quiesce api if all bundles would always perform a clean shutdown when being stopped. That's actually what camel does afaik. If shutting down a blueprint bundle or an jpa container would wait for all calls to be finished before actually shutting down, it may help a lot. Though even doing that would not really be sufficient, as you can't track inside an individual bundle, the fact that a service is "still" in use, even without being currently called. I.e. if you have a service which performs several operations on the entity manager, you could delay the stop of the entity manager until one call is finished, but what you really want is coordination so that the entity manager it stopped until the bundle using the entity manager is completely done. For that, you need cooperation of bundles, and the OSGi api does not really provide anything afaik. There may be alternatives though, as the service dependencies can be introspected from the outside. In karaf 4, when we need to refresh bundles, we do an orderly shut down of bundles according to service dependencies. In the case above, we would first shut down the client bundle, then the JPA entity manager. If each bundle performs a clean shut down, it may be sufficient and we could get rid of the quiesce api, but not of the code which tracks calls, that's needed to perform the clean shut down. > > Btw. I am not yet sure what a refresh in OSGi actually does. Let us assume > we refresh a bundle that provides a package that is imported by other > bundles. Will these bundles also be refreshed then? > Yes > If not then I think these bundles will not see the new package. So in > case the package contains a service interface they will not see the new > service. As this seems to work in practice (at least in karaf) I assume > that in karaf the > client bundles are also refreshed. Is that correct? > If the interface containing the bundle is refreshed, the bundle using that interface is refreshed too. If the api is packaged as a separate bundle and you update the implementation, the client bundle won't be refreshed. > > Btw. this reminds me of this issue https://issues.apache.org/ > jira/browse/ARIES-1270 . > There we refresh a persistence unit bundle. After this the client bundle > and the EntityManagerFactory saw different classes for the Entities. > I do not think this is Quiesce related though. If you have any ideas about > that would be great as I do not seem to find any solution. > > The doc mentions "threads started by this bundle". >>> >>> If a bundle B calls a service from bundle A then the thread is not >>> started >>> by bundle A. So it should be fine that this thread keeps running >>> even when the Activator.stop was called. >>> >>> Here's what the spec says for services (section 5.7, osgi core 6): the >> behaviour of a a service object that becomes unregistered is undefined. >> Such service objects may continue to work properly or throw an exception >> at >> their discretion. Imho, in a production environment, you don't really >> want >> to rely on an undefined behavior. And if the service throws an exception, >> it's not a clean shutdown anymore. >> > I would interpret this part of the spec ("at their discretion") that the > service implementor is free to either continue working or throw an > exception. > So if he does not do anything special it should be fine. > > > Christian > > > -- > Christian Schneider > http://www.liquid-reality.de > > Open Source Architect > http://www.talend.com > >