Hi all,
Over the past 6 months I have been really getting into the COP approach.
Starting with Excaliber, a brief foray over to XWork, and now the porting of
Turbine and Fulcrum to Merlin. And over the past month's I have had to
explain repeatedly why I am interested in using a container and components
in my applications.
And most of the ususual reasons make sense to people. The easy
configuration of components. The reliance on the container to start things
up in the correct order, etc..
And of course, the number one complaint/concern: "I don't want to implement
somebodies interfaces.. Isn't that like EJB?" To which I typically respond
that implementing a Startable/Stoppable/Configurable interface is no
different then what you would be doing anyway if you needed that
functionality. And you are implementing well understood, widespread
interfaces. Especially the Startable/Stoppable interfaces, that makes
complete sense. Some people people do point out that instead of a
Configurable interface, they would set a series of javabean properties. To
which I respond that eventually, if you have too many, you end up with a
config object, so you might as well start out with Configurable. And you
can always do it by hand via JavaBeans. And this satifies most people..
Which brings me to the one thing people really don't get.. Why do I have
to implement Serviceable to get a hook into other components? Why can't the
container just give me the components? I mean, in my java code inside the
component I have to pick what I want. Why not define it outside and have
the container set it? And I get all balled up in explanations.. Of which I
can think of many, like at run time I can pick and choose my components I
need.. If I have setting X, I get component X. If I have setting Y, I get
component Y. However, this did kinda make me wonder... Why can't I just
expose the components I need and provide a setter? Most of the time, I
always want an instance of component X. In fact, often, because of unit
testing, if I have a dependency on component Y, then I just provide a
setter, so that at unit test time I can pass in my MockY component, versus
having to use a custom test configuration loaded through avalon.
I looked at the /tutorial/composition/application/impl/../Application.java
class, and it does precisily what I want it to do.. It implements
Serviceable, and it looks up objects named "locator" and "publisher".
Admittedly, in the example, it then does something, but for my purposes, I
would be happy to just know that when I loaded up the Application component
I had a locator and publisher objects. Now, both of these objects were
defined for me in my block.xml:
<include name="location" id="merlin-tutorial:locator-impl"
version="1.0"/>
<include name="publisher" id="merlin-tutorial:publisher-impl"
version="1.0"/>
Including all the info to resolve them! So, what would be involved in
having a something that did the servicable for me? If Application.java has
a setLocation() and setPublisher() methods, and something was set in the
block.xml, then Application.java could skip the serviceable method and
Merlin could just populate the setters for me. In the XML below, I just
added an autoset="true" to the component declaration that would be the key
to Merlin to just create the darn objects and pass them in...
<container name="application">
<classloader>
<classpath>
<repository>
<resource id="avalon-framework:avalon-framework-api"
version="4.1.5"/>
<resource id="avalon-framework:avalon-framework-impl"
version="4.1.5"/>
<resource id="merlin-tutorial:locator-api" version="1.0"/>
<resource id="merlin-tutorial:publisher-api" version="1.0"/>
<resource id="merlin-tutorial:application-impl" version="1.0"/>
</repository>
</classpath>
</classloader>
<include name="location" id="merlin-tutorial:locator-impl"
version="1.0" />
<include name="publisher" id="merlin-tutorial:publisher-impl"
version="1.0"/>
<component name="application"
class="tutorial.application.Application" autoset="true">
</component>
</container>
I can see issues where location maybe wanted some other objects as well.
However, those dependencis could be setup in here to, correct? Via more
<component> tags?
The reason I bring this up is because I have been reviewing, under prodding,
other frameworks. The nice thing about the SpringFramework is that your
components don't have to implement interfaces (other then a
startable/stoppable one) to be used in Spring. And they don't have to
implement a Serviceable type interface.
I think having Serviceable is very good in some situations. But, in many,
it is overkill. I just want to get a component, and have the X dependent
component already loaded, versus having to everytime do this:
LocationService locator = null;
Object object = manager.lookup( "locator" );
if( object instanceof LocationService )
{
locator = (LocationService) object;
}
else
{
final String error =
"Object " + object.getClass().getName()
+ " does not implement the LocatorService class.";
throw new ServiceException( "locator", error );
}
On a related note.. If you had this facade (?)/interface layer, then the
various Activity lifecyle interfaces wouldn't need to be implmented. I
could instead provide a mapping file that said: For my component, I do
implement the Startable interface, I just didn't implement it, and my method
is called "begin()". This would work for noarg methods especially well.
Actually, I guess would this be a proxy?
Eric Pugh
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]