since Steve and Niclas been saying how much merlin has evolved, I am giving it one last chance. Not as a user, but as a co-developer. I figured I'd have a look at implementing IoC type 3 support (again). Looking for a short execution path I could digest, I started reading in AbstractMerlinTestCase. It took some effort, but I finally found the actual instantiation and lifecycle startup code in
org.apache.avalon.activation.appliance.impl.DefaultAppliance.StandardFactory
So I am guessing all I really want to do is plug in a different Factory into DefaultAppliance. This, however, is hard-coded (!):
private final Factory m_factory = new StandardFactory();
So the next logical step for a type 3 convert like me is that I need a new DefaultAppliance constructor:
public DefaultAppliance(
Logger logger, ServiceContext context, DeploymentModel model,
Engine engine, Factory factory )
{
this( logger, context, model, Engine engine);
m_factory = factory;
}I couldn't quite figure out all the places from where this constructor is called. IDEA sends me to line 928 (!) of AbstractBlock. The surrounding code leads me to believe that I need to modify DeploymentModel and DefaultDeploymentModel. But this means I don't need my new constructor as my factory will be inside the deployment model. Okay.
Some more searching seems to indicate this DeploymentModel is created somewhere in the AbstractBlock constructor, where it is extracted from a ContainmentModel, which is retrieved from a BlockContext (!). The only place I can find where such a thing is created is line 115 of AbstractBlock, which is the createRootBlock() method, which is called in several places, most importantly DefaultFactory (eh? O wait, this is a different factory), inside the create() method (which is a whopping 579-204=375 lines long). I finally find the code that creates the containment model:
ContainmentModel system =
new DefaultContainmentModel(
createContainmentContext(
systemContext, systemLogger, m_classloader,
getContainmentProfile(
kernelConfig.getChild( "system" ) ) ) );It seems that I want to modify the ContainmentProfile. But wait a minute, the javadocs say about containment context "Implementation of a system context that exposes a system wide set of parameters". This I don't want, since I want to use my type 3 factory for some components and the regular factories for others. Aaaahh!!!
So I will need to modify this 375 lines long create() method and support methods to support different containment contexts, different containment models and different containment profiles, probably breaking dozens of things that don't have test cases to check they are not broken in the process.
Since this has now taken about an hour and a half, I give up. Who's up for the challenge? For reference, here's some code that you should be able to paste in MerlinTestCaseTest and run once this is done:
public void testHelloType3Aquisition() throws Exception
{
Type3Component component =
(Type3Component)super.resolve(
Type3Component.class.getName() );
component.doStuff();
} public static interface Type3Dependency
{
String getMessage();
}
public static class Type3DependencyImpl implements Type3Dependency
{
public String getMessage()
{
return "Hello IoC world!";
}
}
public static interface Type3Component
{
void doStuff();
}
public static class Type3ComponentImpl implements Type3Component
{
private String m_message; public Type3ComponentImpl( String message )
{
if( !"Hello IoC world!".equals( message ) )
throw new RuntimeException("Failure!"); m_message = message;
} public void doStuff()
{
System.out.println( m_message );
}
}And as far as defining simplicity goes (the code I saw so far in this exercise does not qualify :D), in my current home-grown container (which doesn't know anything about type 3 IoC either) I can do
container.addAdapter(
new SingletonComponentAdapter(
new ClassSelector( Type3Component.class ),
new Type3ComponentFactory(
container, Type3Component.class.getName()
)
)
);In fortress this change is non-trivial either because of the hard-coded reference (!)
final ComponentFactory componentFactory =
new ComponentFactory( clazz, configuration,
m_serviceManager, m_componentContext,
m_loggerManager, m_extManager );on line 428 (!) of AbstractContainer. However, its easy to see that what needs to be done. The configuration fed to the abstract container is an element directly gotten from DefaultContainer its configure() parameter. So all that needs to be done is allowing a configuration element to the component definition to be added (factory="..."), and then the code around line 428 needs to be made to check for that parameter and parse it.
The next step would then be to refactor the code a bit more, adding the factory information to ComponentHandlerMetaData inside the DefaultContainer.configure() method.
-- cheers,
- Leo Simons
----------------------------------------------------------------------- Weblog -- http://leosimons.com/ IoC Component Glue -- http://jicarilla.org/ Articles & Opinions -- http://lsd.student.utwente.nl/jicarilla/Articles ----------------------------------------------------------------------- "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]
