|
From: Rod J. <rod...@in...> - 2003-07-13 16:03:52
|
Ivan, Juergen
Some thoughts. Ivan, don't get the impression I'm negative about this area:
I just want to make sure that any additional complexity we build into the
bean factory is warranted.
> * Complete bean life cycle: parameters, initialisation, start, stop,
suspend, resume, reconfigure, dispose/destroy
> I agree that a single pair of start/stop methods should do the job, no
need for a suspend/resume. This could be modelled as a "Startable"
interface. A separate "Disposable" interface could feature a dispose method
for cleanup purposes on shutdown.
+1. Non-invasive in good Spring fashion. Only if a bean implements these
methods will they be called. No irrelevant methods to implement like
ejbActivate/ejbPassivate for SLSBs.
>
> * Beans that want to can execute on their own thread
> How is this supposed to work? The execution thread is always determined by
the caller of a bean's methods. In that respect, a bean can't execute "on
its own thread", if I understand correctly. A bean can *create* its own
threads though, either on initialization or on certain method calls. But in
any case, the main method invocation will always execute in the caller's
thread. Therefore I don't think that we need "own thread" support. Spring
simply treats such thread starters as conventional beans, initializing them
and making them available. It doesn't care if and when a bean starts and
stops new threads - that's the bean's responsibility.
You mean a bean that kicks off an asynchronous process somehow? But what
would it return to the caller? We probably do need more sophisticated thread
models for app context event listeners. At present the multicast event
listener uses the same thread as the call that created the event, allowing a
rogue listener to lock the app. It would be easy to support several options,
with this the default, as it's low overhead if people implement their
listeners properly. (Ie a listener kicks off a background thread if it needs
to).
> * Singleton/shared and not-shared beans
> * Bean pools (check-in, check-out)
>
> As you've noted, Spring already supports the first two notions. Regarding
bean pools, I'm not too convinced if they actually add value. In contrast to
EJBs, beans are extremely lightweight, the on-demand creation overhead
normally doesn't matter. Personally, I just use singleton beans, as I find
hardly any scenarios where I couldn't write a thread-safe, reusable bean.
Even when exporting remote beans via Hessian / Burlap / RMI / SOAP /
whatever, it should always be possible to write a single thread-safe bean
instance.
I agree on Juergen regarding pooling. IMHO, object pooling is overrated,
considering the efficiency of garbage collection in modern JVMs. With our
model, if people want single threaded, they can use the "prototype"
(non-shared) model. This will then be something like WebWork.
> Instance pooling would add a significant amount of overhead: There would
indeed have to be an explicit checkout and checkin, or a transparent
checkout / checkin on each method invocation, using an invocation proxy that
delegates to the actual pooled instance. That may make sense for access to
load-balanced remote services, but I really doubt the value for local
invocations. I simply don't see a need for modelling local services this
way, even if EJB's Stateless Session Beans offer such pooling for local
instances too.
Like Juergen, I'd need a lot of persuasion oin this.
> * Ability to safely reconfigure a bean that is referenced by other beans
> Reconfiguration is indeed an interesting issue, as it may need to block
the system to guarantee consistency: Various configuration changes might
depend on each other, i.e. need to be applied completely or not at all to
keep the system intact. This is somewhat similar to a classloader that
supports "hot" class reloading, like in a servlet container: Effectively, it
can't be guaranteed that updating a class won't break the system due to all
kinds of side effects. Thus, hot class reloading is mainly a development
feature, not recommended for production environments.
> For specific settings that are local to a single bean, "hot"
reconfiguration should be solvable though. For development environments, one
could simply overwrite the respective bean properties and proceed - this
would be fine in many cases, avoiding the need to restart the container. In
a concurrent production environment, this can obviously cause all kinds of
side effects. So we would need to use a lifecycle-aware proxy here,
intercepting and registering all method calls to the bean instance. In case
of an ongoing reconfiguration, the container would have to wait for all
running method calls to return while blocking all new requests, then apply
the reconfiguration, and finally allow the waiting requests to proceed.
> This sounds like a case for an AOP interceptor to me!
This is a very interesting area. Semi-coherent braindump follows.
Do we want to call additional setters on a running bean? e.g.
setRetryCount(n) to a new value? This might be appropriate in some cases,
especially for simpler things. Yet it would place constraints on beans,
implying that some metadata might be required to indicate which fields were
refreshable.
Our AOP, and your suggestions regarding interceptors, suggest the idea of
using copy-on-write in a proxy. However, this would only work with proxies,
and the synchronization could be scary. We could have as well as the simple
InvokerInterceptor (which invokes the target via reflection) a
ChangeAwareInvoker, that recognizes when it needs a new instance of the
underlying object or needs to reconfigure the underlying object, and queues
requests at that time. This would mean only a new interceptor not a major
change to the framework. It would have to know when things had changed,
however, so the BF would need to provide that. I guess the factory could
poll the underlying resource (the abstract factory could provide polling in
a storage-independent way). How would it communicate changes? Via setting
new property values on bean instances? We don't really want to detype the
changes into an update(Properties) method or the like.
How much blocking is required really depends on the app code in question.
Which means that metadata might need to be used to drive it.
>
> * Load/unload beans
>
> I guess you mean bean instances here, not bean classes, and I assume load
/ unload means invoking initialize / dispose of predefined bean instances. I
wonder what use cases you see for explicit beanFactory.load("myBeanName")
and beanFactory.unload("myBeanName") calls. When would an application
developer want to explicitly load and unload beans at runtime - maybe to
make certain exported remote services available / unavailable?
I'd like to see use cases for this.
>
> * Reload bean class (in combination with bean pools this probably means
that multiple bean versions will run in parallel at times)
> We would need own classloader hierarchies for such stuff. Basically, every
bean instance would have to be loaded in its own classloader to achieve
this. I rather consider classloader handling an issue for J2EE containers,
not for application frameworks, due to all the nasty hassles that are
involved. And as I've outlined above, this is really hard if not impossible
to handle properly in a concurrent environment, as any bean can have
dependencies on any other. How to guarantee consistency within the whole
system here?
I don't want to get into class loading, if we can possibly help it.
>
> * Persist bean configuration (not serialization, properties only)
Isn't the XML doing this?
> Why would you want to persist a bean's property values - when would you
want to load them again? Basically, the bean factory defines all property
values, e.g. in a properties or XML file. Changing values at runtime should
also occur via these files IMO, the modified file timestamp triggering a
reconfiguration of the watching factory.
That's my view. The factory should be able to compute the minimum change
set.
> * Finally, a container needs to be written which would allow access to all
beans and their configuration from the outside, plus options to load/unload
beans, reconfigure them, inspect them and so on.
> Basically, a Spring BeanFactory resp. ApplicationContext matches that
role, although these interfaces represent a bean user API, avoiding bean
definition details. Implementation classes like AbstractBeanFactory,
ListableBeanFactoryImpl, and AbstractApplicationContext offer access to such
SPI details too. With some added methods e.g. for loading/unloading,
sufficient control and inspection capabilities should be available.
What about JMX? So long as it could be done without forcing JMX complexity
on user code.
Regards,
Rod
|