What's the good practice regarding the usage of ServiceManager.release(obj)?
If you use...
* ECM or Fortress: always call it when you're done with a component.
* Phoenix: doesn't matter (everything is a singleton anyway and objects exist for the life of the application).
* Merlin: you *may* get away safely if you don't call it.
If you want to completely comply with avalon-framework contracts: always call it.
hence, if you want portable components: always call it.
Let's take a look at a few of the common comments made (we see these periodically):
= try{}finally{release} is a PITA =
Yes it is. It is the price you pay for having a rich set of component lifestyles available to you automagically - we need to deal with all components as if they have a rich lifestyle, since the lifestyle is not exposed to the client (which is a Good Thing).
Note there's several things you can do to make this stuff easier. Consider adopting a code convention where you have private members with a ms_ (or something, for "My Service") prefix, then an abstract base class which implements dispose() and will release all those private members, then call super.dispose() as the last method inside your child class dispose() (if any):
public abstract class AbstractServiceDisposer // UNTESTED CODE SKETCH
extends AbstractLogEnabled
implements Disposable, Serviceable
{
private ServiceManager m_sm; public void service( ServiceManager sm )
{
m_sm = sm;
} protected ServiceManager getServiceManager()
{
return m_sm;
} public void dispose()
{
try
{
Field[] fields = this.getClass().getDeclaredFields();
for( int i = 0; i < fields.length; i++ )
{
try
{
field = fields[i];
if( field.getName().startsWith("ms_") )
m_sm.release( field.get(this) );
}
catch( IllegalArgumentException iae )
{
// won't happen
}
catch( IllegalAccessException iace )
{
getLogger().warn( "Can't release all my services: " +
"SecurityManager won't allow me to reflect on myself",
iace );
}
}
}
catch( SecurityException se )
{
// we need permissions from security manager
getLogger().warn( "Can't release all my services: " +
"SecurityManager won't allow me to reflect on myself",
se );
}
}alternative approaches include mixins/AOP/etc. Before you do any of this, words of caution:
http://lsd.student.utwente.nl/jicarilla/TooMuchMagic
= GC magic with finalize() can work =
GC magic is not part of the avalon-framework contract. Why? It can be somewhat buggy on obscure JDKs, it's expensive, it's complex, its misusing intended use of finalize().
To be on the safe and portable side, don't rely on it being available, nor on it to always work perfectly.
= Developers are dumb/lazy =
What you can do is create a framework on top of avalon that makes more assumptions about developer laziness that uses mechanisms such as the above. You'll want to coerce your dumb developer friends to all use your special class though.
= No-one uses it =
Errr...wrong. ServiceManager.release() is used in applications all over the globe. A notable one is cocoon.
= what about Releaseable, ReleaseRequired, ReleaseUtil? =
Been there, done that, won't work. Marking components as releasable will just mean you'll be checking whether they're marked as such, which is just as ugly.
= It boils down to... =
There's a simple choice:
either * you restrict yourself to a subset of lifestyles that do not require release() semantics (example: Phoenix, PicoContainer); or * you always do the release() semantics, even when they're not really required
= please use wiki =
Everyone who learned something from this is encouraged to summarize this discussion and create a page on our wiki (wiki.apache.org/avalon) so others may learn as well. Alternatively, submit a patch to the javadocs for the ServiceManager class.
back to my corner!
cheers,
- LSD
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
