Potential way to manage unloading beans
#424

Comments

edited by seancorfield

Edited 1 time

seancorfield edited Dec 29, 2016 (most recent)

When the framework is reloaded, setupApplicationWrapper() is called. At this point, any reference to the prior instance of the beanFactory is lost. This is problematic for any services that need to run shutdown logic, such as services who are maintaining references to connection pools. Ideally, you'd want to do this sort of thing in setupApplication(), but wrapper has already lost your reference.

The very simple solution would be to just provide a hook to for users to override, such as onFrameworkReload() to manually handle safely shutting down services for those that need it.

The more complex solution would be to have DI/1 register singleton objects as "unloadable" as they are created via checking for the unload method. Inject One could then invoke the shutdown methods on all registered objects upon receiving instruction to shutdown. FW/1 could call shutdown on the beanfactory (if it has it) during a reload request before instantiating a new instance of the beanfactory. FW/1 could also include similar logic via onApplicationEnd(). I'm not sure if would make use of an overridable setupOnApplicationEnd()/onApplicationEndWrapper() as is done for the other built in ...Start() methods but at least the skeleton is there.

Known workaround : Don't have DI/1 manage the service and handle the logic one off in onApplicationStart()/onApplicationEnd() and have a secondary reload to call onApplicationStart().

This comment has been minimized.

I finally got around to looking at this recently and the bottom line is: this is tricky. Having looked over how FW/1 manages the bean factories it creates, it would be very hard for FW/1 to correctly "shutdown" those bean factories at the right time and in the right order.

Subsystem bean factories are created on demand, so they may or may not exist at any given point, and because each of them has the default bean factory as a parent, they must be "shutdown" prior to "shutting down" the default bean factory.

FW/1 is also bean factory agnostic so I would rather not build too much special behavior in around DI/1 that would make it more difficult for users to replicate that functionality when they are managing their own bean factory (even if they are using DI/1 outside of FW/1's immediate control).

I think having an onReload() extension point is about the most that FW/1 can realistically do for users in general. It would be called on a reload request, immediately prior to the call to setupApplicationWrapper() and users could override it to do whatever they needed at that point.

Note: if you services need to do housekeeping for a prior instance some time before a new instance initializes itself, one thing to consider is that the bean's constructor could stash this in some application scope variable and, if that exists when init() is called, it does whatever necessary to the previous instance before constructing the new instance. That would allow a bean to be self-contained, and manage its own special lifecycle, under any circumstance -- including standalone testing, outside of a bean factory.

I finally got around to looking at this recently and the bottom line is: this is tricky. Having looked over how FW/1 manages the bean factories it creates, it would be very hard for FW/1 to correctly "shutdown" those bean factories at the right time and in the right order.

Subsystem bean factories are created on demand, so they may or may not exist at any given point, and because each of them has the default bean factory as a parent, they must be "shutdown" prior to "shutting down" the default bean factory.

FW/1 is also bean factory agnostic so I would rather not build too much special behavior in around DI/1 that would make it more difficult for users to replicate that functionality when they are managing their own bean factory (even if they are using DI/1 outside of FW/1's immediate control).

I think having an onReload() extension point is about the most that FW/1 can realistically do for users in general. It would be called on a reload request, immediately prior to the call to setupApplicationWrapper() and users could override it to do whatever they needed at that point.

Note: if you services need to do housekeeping for a prior instance some time before a new instance initializes itself, one thing to consider is that the bean's constructor could stash this in some application scope variable and, if that exists when init() is called, it does whatever necessary to the previous instance before constructing the new instance. That would allow a bean to be self-contained, and manage its own special lifecycle, under any circumstance -- including standalone testing, outside of a bean factory.