Antti Koivunen wrote:

Stephen McConnell wrote:


Antti Koivunen wrote:

Stephen McConnell wrote:


Antti Koivunen wrote:

<snip/>

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.

Yes, of course, I understand the need for optional entries. I was talking about a use case where you would call hasEntry(KEY) without intention of calling get(KEY).


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! :-)

OK, I thought it might be more user-friendly to return null, if the entry is not found, and throw an exception if something else goes wrong, but I can certainly live with just exceptions (actually might even prefer them), i.e.

NoSuchEntryException extends ContextException

Also, although it makes little difference in practise, we have to acknowledge the following:

if ( context.hasEntry(KEY) ) {
obj = context.get(KEY); // Could throw NoSuchEntryException
// if the entry was just removed.
}

But this isn't really an issue, so let's include hasEntry for convenience.

Its not an issue because the container will never let it happen. If the context object has released a referecne, and it invoked get a second time, the handler just builds another or returns a pooled reference or whatever. The thing is that the container makes sure that hasEntry alway corresponds with the reality of a get().

<snip/>

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.

I don't think I was implying that; 'reinitialize' means that something has changed. The component would only have to decide whether to take any action, e.g.

void reinitialize( Object key, Object value )
{
if ( key.equals(KEY_A) ) {
objectA = (A) value;
} else if ( key.equals(KEY_B) ) {
objectB = (B) value;
}
}

Now, compare this to the following (please correct me, if misunderstood your suggestion):

void resume()
{
try {
objectA = (A) context.get(KEY_A);
objectB = (B) context.get(KEY_B);
} catch (ContextException ce) {
//...
}
}

We could of course have a more general notion of a ContextListener, if necessary.

What I have in my head is:

   public void resume()
   {
       // grab any volatile values
       String name = (String) m_context.get( "the-name" );
       if( !m_name.equals( name ) )
       {
           // update stuff related to the name because
           // the name has changed
       }

       // everything else if final - so we're done
   }


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.

There is a real scalability issue. Think about a deployed enterprise application; there might be one configuration change a month and 10 000 calls to suspend() and resume().

In this sort of a scenario I would take a lot more control over container/component contract (via extensions for example) - get the container to provide some specific change handler that provides the details of what features need updating - if any. I'm also assuming that suspension/resumption will only occur in order to introduce a change of state from the container (i.e. one a month). I'm not looking at suspend/resume suporting any other semantics. Keep in mind that suspension of one component implies suspension of all components that are consuming services from the target. Once the target is resumed, the dependent service can resume - however - the behaviour of the service may have changed as a result of new state. From this point of view - I don't see 10,000 calls to suspend/resume (or perhaps I don't want to imagine 10,000 calls to suspend/resume given the implications on associated components).
Looking at this purely for the context point of view - things are manageble, but configuration changes are a lot more complicated. I've through about a number of scenarios such as a component registering listeners on particular notes - etc. but it always ends up icky. A simpler solution could be to simply tag artifacts as modified and then just redo configuration, contextualization, etc. The component could do something like:

public void reconfigure( Configuration config ) throws ConfigurationException
{
if( config.isModifiedSince( m_timestamp ) )
{
// configuration contains a modified value so we need
// check any volatile children
}

m_timestamp = new Date();
}


But its really late!

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