Firstly - I 100% agree with everything Neil said, it's spot on.
We also hit issues with an "in process" restart (albeit for different
reasons) and also settled on a JVM restart approach as an easier model
for our initial solution. We based the approach on this article:
http://java.dzone.com/articles/programmatically-restart-java
It works for us - but maybe won't work in every scenario.
We didn't use the above model verbatim - we split the part where we "get
command line args" out and did that at startup, saving them away for
later. We also "wrappered" the shutdown, making sure we have an attempt
to shut felix down cleanly first, and only then do we register the
"restart shutdown hook" as described in the article, and call exit to
trigger the restart e.g.
/**
* Ensure any Felix instance we started is shutdown
*/
public void stop(boolean wait)
{
try
{
if (this.felix != null && this.felix.getState() ==
Bundle.ACTIVE)
{
this.felix.stop();
if (wait)
{
felix.waitForStop(20000);
}
}
}
catch (Exception ex)
{
System.out.println("*** Exception stopping felix:" + ex);
}
}
/Note we keep a "felix" reference in our launcher during startup for
later shutdown./
It's important to realise that whilst the above can work, it isn't
necessarily as clean or controllable as a proper in-OSGi restart.
Regards
-- Rob
On 14/05/2013 1:44 PM, Neil Bartlett wrote:
Dan,
Each bundle should be responsible for stopping any threads that it has
started itself, and it should do this from its BundleActivator.stop()
callback method (or if you have used DS, from the deactivate methods,
etc). The management agent should not care about bundle threads --
that is an implementation detail that the agent should know nothing
about. It should just call Bundle.stop().
With respect to when the thread has to stop, think about it the other
way around... what if you never stop any threads? This would mean that
objects allocated by the thread do not become candidates for garbage
collection; therefore neither do the classes that define those
objects; therefore, neither do the classloaders that loaded those
classes. So you're going to create a lot of garbage on the heap,
eventually resulting in OOME. Also, if a bundle's thread continues
running after the bundle has been stopped/updated then you could get
unexpected exceptions occurring in that thread; e.g. the bundle
classloader might not allow any new classes to be loaded, and calls
into OSGi using your BundleContext will probably throw
IllegalStateException. Generally these exceptions are not harmful
since you wanted the thread to die anyway, but they could cause
confusion if written to a log.
Therefore from a pure Java/OSGi standpoint it doesn't really matter
whether the threads stop before or after update, so long as they do
eventually stop. However a bigger problem is likely to be the internal
logic of the bundles... is it able to cope with two copies running
simultaneously? For example if you access a resource such as file, can
you cope with "somebody else" (actually, an old undead copy of
yourself!) accessing the same resource at the same time?
I hope this helps,
Neil
On Tue, May 14, 2013 at 12:17 PM, Dan Gravell <[email protected]> wrote:
Hi all. After giving it about a year of tweaks, I'm finally going to give
up trying to update my OSGi app in process. The killer is the requirement
to stop all threads... for my particular requirements this just isn't
feasible. I have to maintain my own forks of projects, some complex (the
Lift web framework) and some less so (JNotify) and this just takes too long.
So I'm putting thought to how I can structure a solution that restarts the
JVM *at some point*. I am using Felix 'bundlerepository' bundle to perform
the deployments of bundles.
So first, the requirement to stop threads: is this a requirement *before*
start(), stop() or update(URL) is called?
If it's only something that has to be done before stop() then I _could_ do
everything I do now, up to when start() is called on each bundle. At that
point, I could exit with an exit code and my launcher script checks that
and, if it's a known value, restarts the same process. In this case, I
would have to re-start the bundles on restart.
If threads have to be stopped before the update itself, then I suppose I
can download the bundles to a holding area, and have a bootstrap JVM that
picks them up and somehow performs the update, and then starts.
If anyone has any wisdom or experience of this I would be grateful to hear
it...
Dan
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
--
Ascert - Taking systems to the edge
[email protected]
+27 21 300 2028 ext 5119
www.ascert.com