avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen McConnell <mcconn...@apache.org>
Subject Re: Avalon 5 Core Interfaces
Date Mon, 27 Jan 2003 08:50:39 GMT


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:mcconnell@apache.org
http://www.osm.net




--
To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>


Mime
View raw message