Antti Koivunen wrote:

Stephen McConnell wrote:


Antti Koivunen wrote:

<snip/>

Now, to ensure performance and consistent client access, we should also have a 'service handle' interface (Resource in Merlin):

public interface Handle
{
Object access() throws AppropriateException;
void release( Object instance );
}



Experience with handler access and release has led me to include an argument containing the source of the access and release. This allows the handler to track usage, and more specifically, during demonnissioning the handler can take responsibility for the gracefull termination of all exposed instances. A context implementation along the lines your describing above plays into this as it is the primary origin of instance creation actions (ie. lookup (or get) results in resolution of a handler, access is invoked on the handler passing the context as the source, etc.). This also means that you need to expand you context interface to enable client to release components, which in turn triggers the flow back to the handler to release an object granted by the handler to the context.

This leads to a Context interface something along the lines of (note - lookup replaced by get and String argument replaced by Object to be A4 consitent):

public interface Context
{
Object get( Object key ) throws ContextException;
void release( Object object );
}

Yes, that makes sense, although the release would usually be initiated by the container (disposing components). I'm assuming here that Context.get() could still return a Handle, and the Context.release() would thus be roughly equivalent to a Handle.close(). (The handle is basically there to eliminate that one Map.get()).

The release operation can be invoked by a client (e.g. it may be using some intensive stuff during initialization that is no longer required and as such it can go ahead and release the artifact after doing whatever it does. I agree that it not a frequent patter but it something I do frequently on security related stuff - get what I need and relase the reference.

If we add some convinience operations to the above, we end up with something like:

public interface Context
{
boolean hasEntry( Object key );
Object get( Object key ) throws ContextException;
void release( Object object );
void release();
}

The convinience operations include hasEntry (because context entries can be optional and its simply nicer to do this that wrap things in a try catch block and it is consitent with A4 service manager semantics;

Yes and there's also a slight semantic difference, i.e. hasEntry: "tell me if you have the component, but no reason to wake it up just yet". However, this makes little difference in reality, and in theory, the following could also happen:

boolean ok = ctx.hasEntry(someKey); // returns true
Object obj = ctx.get(someKey); // returns null (or throws exception)
// because the entry was removed

I think it's mostly a question of wheter you would ever look up an entry without necessary thinking of using it (for convenience, Context.get() could return null). I've never had this use case, but I won't object to including the method, if others really need it.

Yes - there is a valid use case for this. There are situations where you want to have "optional" entries. The hasEntry lets you test is the entry has been supplied and if so, you go ahead and do your stuff. Optional entries are *really* useful. In principal the get (lookup) operation should not return null - it should always throw an exception if the resource is unavailable - why - because that'sa how it is in A4 and I'm getting too old to change! :-)

and includes a release() operation which is simply an instruction to the context to release all objects that hve been claimed by the client).

Perhaps it'd be more aptly named Context.releaseAll() or Context.close(), the latter also indicating that the context won't be used anymore.

Yep.

<snip/>

I prefer the notion of seperating out logging, configuration, context and initialization as seperate and destinct stages of a deployment phase. I do think (based on Merlin 2.1 experience) that there is a lot of benefit to be gained from comverging context and service manager into a single interface - in fact all of the internals of Merlin use an extended A4 Context interface which is basically providing this (note: this is a reversal of my prior position on service context seperation). However, we don't need to let this difference of opinion stand in the way :-) .. lets just call call this the deployment phase (see below).

Actually, I think we mostly agree here (this time I wanted to start small with something simple :)


The question of statup/suspend/resume/stop as you suggested above is a valid target for discussion. In particular, the distinction between initialize and start seems to me to be artificial . The same can be said for stop/dispose. Removing these artificial stages leaves you with something like the following:

[INSTANCE] ------ deployment -----> [INITIALIZED]

Component is taken through the stages necessary
to establish it as an initialized and available
object capable of performing whatever its work
interface exposes.

[INITIALIZED] ------ suspension ----> [SUSPENDED]

The action of suspending an initialized object
enabling modification of non-final artificates
established during deployment

[INITIALIZED] <----- resumption ----- [SUSPENDED]

Returning a suspended component to its normal
initialized state.

[INSTANCE] <-- decommissioning ---- [INITIALIZED]

Stripping down and disposing of the component.

Yes, this is what I wanted to see :)

<snip/>

In the following example of a simple context defintion, I'm declaring the the name entry is non-final. I.e. this means that the component, if suspended, can be recontextualized during which the value returned from the name entry may be different. The component need not check final entries (because they will be unchanged).

<context>
<context key="urn:avalon:name" final="false"/>
<context key="urn:avalon:home" final="true"/>
</context>

This is a very interesting idea, but we have to think about the overhead. Reconfiguration cannot happen every time a component is suspended and resumed. However, we could make it asynchronous, i.e. the container would notify the component if the context is modified, by calling a certain method, say reinitialize(), after which the component could reload the values. In fact, we could even pass the name and value of the modified entry as arguments to reinitialize(), effectively eliminating the need for unnecessary lookups and the final/non-final separation.

You getting at the difference between "changable" and "has-changed".
The implication of simply invoking configure, contextualize, etc a second time with volative members simply shift the responsibility onto the component to worry if something has changed or not. It's an area that can get really complext really quickly and taking this lazy approach (lazy from the container point of view) seems to make more sence to me.

<snip/>

In you post you mention the Merlin Resource interface (Merlin 2.0). This has been the subject of some refactoring, the result of which is the redefintion of the abstraction as *Appliance*. In addition - the internals related to component assembly, lifecycle and lifestyle management of Merlin 2 have been seperated out into the assembly package in avalon-sandbox and the aspects concerning "containement" have been moved to the avalon-sandbox/merlin package.

Also, you may want to take a look at the Locator interface and related implementation in avalon-sandbox/assembly/src/..../locator/*.java.

Thanks, I'll do that (see, I'm catching up already :)

BTW, I really like what you've done with Merlin.

Great!
I'm happy too - but I really need to get in place a HELP-WANTED.TXT list because there is still a lot to do.

I have a few ideas relating to high availability, i.e. having a way of identifying and dealing with malfunctioning components, but more on this later.

Cool - I'll look forward to it.

Cheers, Steve.


(: A ;)

--

Stephen J. McConnell
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