Adam:

Sorry for the delay in responding - see notes in-line.

Adam Rossi wrote:

On Fri, 2002-11-15 at 16:02, Stephen McConnell wrote:
<snip>

(While it is of course possible to put stuff like this in a Context,
using a Configuration is usually easier and more straightforward for
data that is naturally represented in XML)


The above approach only works if the CompanyID value is a static (i.e. declared i a configuration, or context directive or whatever). If you have a runtime value, you have to (a) create you own DefaultContext and handle a compoent deployment, (b) use a component lifecycle extension, or (c) roll-your-own container.

Cheer, Steve.

This is exactly the case. In the example, companyID will not be a static
value that I can throw into a config file, it is a runtime value that
will be used during initialization to, for example, pull stuff from a
database under that key.

I understand that components should have a constructor with no arguments
so the container can manage it, but I thought that the component could
get its runtime values from the context in some straightforward way.
Steve, could you please describe (a) and (b) a bit more? What is the
preferred way to do this in avalon? Surely this can't be that uncommon
of a usage pattern....

For the scenario where you are acting in the rol of a container, and you want to supply a component with information under its context you would do something like the following:

Scenario A : Using DefaultContext
---------------------------------

// get the company ID value

CompanyID id = myFactory.getCompanyID() // or whatever

// create a context object and pout the id into it

DefaultContext context = new DefaultContext();
context.put( "company-id", id );
context.makeReadOnly();

// create a component to do something with it
// typically this would inviolve a bunch of other things
//like logger assignment, configuration, initialization, etc.

Object object = new ComponentComponent();
((Contextualizable)object).contextualize( context );

A utility class also exists in the avalon framework called ContainerUtil which is basically a helper class that you can use as follows:

ContainerUtil.contextualize( object, context );

All it does is applies the context value to the supplied object if the object implements the Contextualizable interface. ContainerUtil supports all of the classic lifecycle stage interfaces. So basically helps to keep your code is a little cleaner.

Scenario B: Using a lifecycle extension
---------------------------------------

There is some good documentation and example of the application and use of lifecycle extensions under the following URL:

http://jakarta.apache.org/avalon/excalibur/container/extensions.html

What the extension framework provides is a way for you to cleanly seperate the container abstractions from your component implemetation abstractions. For example, you could declare a component lifecycle interface such as "Identifiable" within which you declare an operation that an extension provider can invoke on you component (in your case, the supply of a CompanyID).

interface Identifiable
{
public void setIdentity( long id );
}

The next step is to define the lifecycle extension provider (the container side of the abstraction). The implementation approach here differers across containers and following example uses the Merlin approach.

public class IntentifiableExtension extends AbstractCreator
{
public void create( Object object, Context context )
throws Exception
{
// this method is invoked by the container managing
// the extension (e.g. Merlin or Fortress) - the
// object is your component and the context is any
// context information you have declared in the meta
// info for the extension

// Because this object will be treated as a full
// component, you can declare dependencies on things
// like a persistence service and so on so that the
// container side functionality you include can be
// totally up to yourself

// Here is the bit of code where the handler interacts
// the component ..

CompanyID id = getMyCompanyID() // or whatever
((Identifiable)object).setIdentity( id );

}
}

However, this is only part of the solution - the extension framework provides a nice way of seperating container/component concerns, but you still need a mechanism to launch your new component. This is possible using the Merlin assembly engine although the examples have been pulled out for the moment. There is some work going on to change the approach to a service you can aquire, then supply pass in your component and whatever other information you want to deploy it with, and bingo - Merlin will take care of the complete assembly and deployment process. You can do this with the current API (after all, that's what happens inside the DefaultContainer implementation - but waiting a little means you will have something much easier to work with.

This will probably look something like:

Class clazz = CompanyComponent.class;

DefaultContext context = new DefaultContext();
context.put( "company-id", id );
context.makeReadOnly();

Appliance appliance = applianceFactory.newInstance( clazz );
appliance.contextualize( context );
appliance.initialize();

The differnece is that Merlin will automate the process of logging channel assignments, getting and aplying any supplied configuration, combnined with any default configuration info bundeled with the type, creating any additional context values that the component needs, resolution of any dependencies that the component has on other services and extension providers, etc. You code just needs to provide the minimum extra info and you can basically ignore the rest of the process.

I suggest you keep an eye on the disucssions on the user list related to Gary's work - he's doing a client side interface thing in which he has a bunch of components he has to manage and is dealing with many of the same questions your asking. With the introduction of a deployment service abstraction in Merlin I'll be keen to see this tested as broadly as possible. In the meantime I will be posting information about the deployent and appliance API as things come together.

Cheers, Steve.

Thanks for your help.

Regards,

Adam




--

Stephen J. McConnell

OSM SARL
digital products for a global economy
mailto:[EMAIL PROTECTED]
http://www.osm.net




--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to