> From: Stephen McConnell [mailto:[EMAIL PROTECTED]]
>
> The latest Merlin news is the completion of pluggable lifecycle
> extensions.
Now that I have had time to read the message in its entirety, here
are some observations:
> The extension framework is fully incorporated in the
> component model -
> components can declare a dependency on a lifecycle extension provider
> via a <phase> declaration in the component type model. For example:
>
> <component-info>
> <component>
> <name>my-component</name>
> </component>
>
> <phases>
> <phase>
> <reference
> type="org.apache.excalibur.playground.Exploitable"
> version="1.0"/>
> </phase>
> <phase>
> <reference
> type="org.apache.excalibur.playground.Demonstratable"/>
> </phase>
> </phases>
>
> </componenent-info>
>
> Declaration of a <phase/> is similar to the declaration of a service
> dependency in that phase providers are managed by the Merlin
> container
> as dependencies of the target component. In the above example, two
> lifecycle extension dependencies are being declare. The type
> attribute
> declares the lifecycle interface implemented by the component
> - its up
> to the container to resolve an appropriate lifecycle extension to
> provide this to the target component when handling component
> instantiation.
We can reduce the verbosity of the <component-info/> declaration by
merging the <reference/> element with the <phase/> and <extension/>
elements. In essence, we are changing this:
<phases>
<phase>
<reference type="com.mycom.foobar.Demonstratable" version="1.0"/>
</phase>
<phase>
<reference type="com.mycom.foobar.Exploitable"/>
</phase>
</phases>
to this:
<phases>
<phase reftype="com.mycom.foobar.Demonstratable" version="1.0"/>
<phase reftype="com.mycom.foobar.Exploitable"/>
</phases>
And similarly with the extensions
<extension stage="ALL"
type="com.mycom.foobar.Demonstratable"
version="1.0">
<name>demonstrate</name>
<attributes>
<attribute key="status" value="experimental"/>
</attributes>
</extension>
At least from an XML point of view, it simplifies what someone has
to type.
> Lifecycle handlers are declared as extension of the "classic"
> component
> type definition. Here is an example of a lifecycle handler. It
> publishes its ability to handle a phase via an <extension/> element.
> The container is responsible for locating extension providers
> based on
> the matching of the <phase> type attribute with an
> <extension><reference/> type attribute. Selection of an extension
> handler is identical to the selection of a service dependency. This
> means that multiple candidate extensions can exist within a singe
> classloader scope.
Honestly, I'm not sure if I like this. I prefer lifecycle extension
handlers being treated distinctly as such. Maybe it would be better
if it had its own markup like this:
<extension-info>
<!-- Declare everything else the same -->
</extension-info>
> Other important points are that a extension provider can
> declare its own
> phase dependencies and also classic service dependencies.
> Merlin will
> take care of the ordering of component establishment based on
> the phase
> and service dependencies that the component publishes.
>
> Extension providers must implement the following interface:
>
> org.apache.excalibur.merlin.assembly.resource.Extension
>
> The interface declares the operation "extend( int stage,
> Object object,
> Context context ) which will be invoked by the Merlin
> container during
> the appropriate stages. Merlin defines a number of stages
> that can be
> associated with an extension provider. Merlin will only
> invoke extend
> if the provider declares that it supports the particular stage.
>
> Standard stages include the following:
>
> CREATE invoked immediately before initialization
> ACCESS invoked immediate before lookup
> RELEASE invoked immediately before release
> DESTROY invoked immediately before dispose
> INNER equivalent to ACCESS + RELEASE
> OUTER equivalinet to CREATE + DESTROY
> ALL equivalent to INNER + OUTER
:/
I kind of like Marcus' solution a bit better. We have simple
methods that have a specific meaning. If a lifecycle event happens
on more than one type of use (create/destroy/access/release),
the implementor has the freedom to use OO principles more clearly
by encapsulating the common elements in a separate method.
More often then not, we are not processing the same method even
if we are processing the same interface. Take for instance the
following:
interface PersistantConfigurable
{
void configure(Configuration conf);
Configuration saveConfiguration();
}
Which is more clear?
Marcus solution:
------------------------------------------------------------------------
--
class PersistantConfigurableHandler extends AbstractExtension
{
void create( Object component, Context context )
throws Exception
{
if ( component instanceof PersistantConfigurable )
{
((PersistantConfigurable) component)
.configure( (Configuration) context.get(
"configuration" ) );
}
}
void destroy( Object component, Context context )
throws Exception
{
if ( component instanceof PersistantConfigurable )
{
Configuration config = ((PersistantConfigurable) component)
.saveConfiguration();
// perform config persistence here.
}
}
}
-----------------------------------------------------------------
Your solution:
-----------------------------------------------------------------
class PersistantConfigurableHandler implements LifecycleExtension
{
void stage( int stage, Object component, Context context )
throws Exception
{
if ( component instanceof PersistantConfigurable )
{
switch(stage)
{
case CREATE:
((PersistantConfigurable) component)
.configure( (Configuration) context.get(
"configuration" ) );
break;
case DESTROY:
Configuration config = ((PersistantConfigurable)
component)
.saveConfiguration();
// perform config persistence here.
break;
}
}
}
}
---------------------------------------------------------------
I like having separate and distinct methods that do one thing, and
do not change behavior based on a value passed in.
The stage(...) solution gets much more complicated when you have more
than one interface you are supporting.
> Demonstration of extension declaration and phase declaration
> is included
> in the org.apache.excalibur.playground package (see
> assembly/demo) - in
> particular, the DemoManager, ExpliotationManager (both examples of
> extension providers), and SimpleComponent - a multi-phase
> phase consumer.
I will check your example to see if I completely missed what
I think you were saying here, but I don't think I'm that far
off.
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>