Then came Cocoon, and a need for pooled components.<snip/>
That's a lot of tries, lookups, catches, finallies and releases.
+1
StatefulPooled interfaces are the black sheep of Avalon.
+1
interface TransientFactory {
public Object get ();
public void put (Object o);
}
this can work. Sort of. I've also been thinking about things like
interface TransientFactory
{
public Object get();
public void put( Object o );
Class provides(); // at least a little bit of "hard-coded"
// client-side validation
} interface TransientFactory
{
public Object get();
public Object get( Class expectedClass )
throws CannotProvideExpectedClassException;
// Spring framework has this one
public void put( Object o );
}the former would be used somewhat like
public MyClient(TransientFactory saxTransformerFactory)
{
Assert.assertProvides( SaxTransformer.class,
saxTransformerFactory );
this.saxTransformerFactory = saxTransformerFactory;
}
public void doStuff()
{
SaxTransformer t;
try
{
// the cast should be relatively 'safe'; otherwise the factory
// is violating its contract
t = (SaxTransformer)saxTransformerFactory.get();
}
finally
{
saxTransformerFactory.release( t );
}
}while the latter likely results in an exception a lot later, and will hence look more like
public MyClient(TransientFactory saxTransformerFactory)
{
this.saxTransformerFactory = saxTransformerFactory;
}
public void doStuff()
{
try
{
SaxTransformer transformer =
saxTransformerFactory.get( SaxTransformer.class );transformer.blah();
saxTransformerFactory.release( transformer );
}
catch( CannotProvideExpectedClassException cpece )
{
this.exceptionListener( cpece ); // bad container!
throw new IllegalStateException(
"this goes to client components :(" );
}
// save a finally {}...
}or you could support both options. Of course, you need just as much discipline in your component writing to write the assertions as you need to write the try/catch/finally.
Then there's the option of seperating out the validation into helpers or wrappers or aspects or metadata with the hope of saving some lines of typing at the cost of increased complexity.
If you don't watch out, you're also introducing lots of small (mandatory) factory objects, parallel class hierarchies, etc etc.
Then there's the option of removing the transparency requirement on the manager, and specifying that the release contract is between the component and its dependency, but that if it exists it goes through the manager. There's very little difference between this one and a transient factory IMHO.
Then there's the option of making your components threadsafe and fully transaction aware (ugh!).
There's even weirder alternatives like per-component-thread-with-threadlocal.
/**
* @@.saxTransformerFactory Dependency (SAXTransformer.class)
*/
public MyClient (TransientFactory saxTransformerFactory) {
this.saxTransformerFactory = saxTransformerFactory;
}
did you ever get the metadata for an argument-by-name association working properly?
This is one for A5 definitely
why? It's not backwards-incompatible :D
-- cheers,
- Leo Simons
----------------------------------------------------------------------- Weblog -- http://leosimons.com/ IoC Component Glue -- http://jicarilla.org/ Articles & Opinions -- http://articles.leosimons.com/ ----------------------------------------------------------------------- "We started off trying to set up a small anarchist community, but people wouldn't obey the rules." -- Alan Bennett
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
