You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Stephen McConnell <mc...@apache.org> on 2003/06/12 09:31:47 UTC

Re: merlin's meta tags and a bigger LCD


Hi Leo:

Good to see your hard at work!

Some agreements and some disagreements in-line.

;-)


Leo Simons wrote:

> Stephen McConnell wrote:
>
>> Only works if we cater for all of the requirements.
>> I.e. the LCD approach fails the usability test.
>
>
> it fails some tests, not all. A LCD is always less usable, but the 
> point is that it is still usable. For example, in merlin, versions 
> might default to 1.0.0 if left unspecified, names might default to 
> lowercased classnames, @avalon.dependency mapped into 
> @avalon.meta.dependency and @avalon.service mapped into 
> @avalon.meta.service, resulting in a fully functional LCD. 


LCD fails to deliver the aim of portable declarations.
If a component declares a lifecycle stage then that component should not 
be deployable in Phoenix.  To ensure this - the Phoenix meta generation 
tool MUST recognize a lifecycle stage extension tag.  Same story for 
lifestyle - it MUST be recognized in order to ensure non-deployment.  
LCD simply means potential runtime failure.  This makes LCD unusable.

>
> == @avalon.meta.namespace ==
> class       Enables client modification of the tag namespace.

<snip>

I aggree that this one can dissapear.


> == @avalon.meta.version ==
> class     Identifies a class or interface are a Type or Service.
>
>     <type><info><version>1.3.0<version></info></type>
>
> === comments ===
>
> - why is there a <version/> for classes? 


It is the declaration of the implememtation version of the class.  This 
reflects the behavioural contract (as distinct from the interface 
contract).  A component with a major version incriment refects a 
incompatible semantic change which may be independent of the interface 
change.  For example, semantics may be introduced on the interpritation 
of a string argument.  The interface reamins the same, but the sematics 
of the implementation may have changed in an incompatible manner.  This 
information can be used by custom selectors and/or management tools.

>
> - can you depend on a version of a class? Why? 


An ORB version 1.x is very different to version 2.x.  The implementation 
version 2.1 a lower level of functionality to 2.4.  Yes - you can depend 
on this sort of information because it reflects compliance with 
implementation semantic constraints.

>
> - why is the standard '@version' tag not usable for this purpose?


The @version tag is typically used to reflect CVS versioning. 
Overloading this with formal class implementation versioning would be a 
bad thing to do.

>
> == @avalon.meta.attribute ==
> class     A attribute associated with a containing type or service.
>
>  <service>
>   <attributes>
>     <attribute name="description" value="an example"/>
>     <attribute name="color" value="red"/>
>     <attribute name="priority" value="normal"/>
>   </attributes>
>  </service>
>
> === comments ===
>
> Is it not better to simply make all unknown javadoc tags into an 
> "attribute"? IE:
>
>     /**
>      * @my.tag jo!
>      * @my.second.tag blah blah blah
>      */ 


I don't like the idea of bundliung anything that is unknown (I can just 
see lots of future problems, not to mention the fact that junk 
information will end up on the screens of management tools).

These attributes are used to suppliement a component description with 
information that will typically be specific to a container , component 
or service.  In the general case - attributes should be ignorable - but 
there defintition as meta-info attributes should be explicit.  This 
simply means that if a named value pair is to be associated with a 
component type - then there is a standard way to do it.

<snip-examples/>

I like the declaration approach of multi attributes ion a single 
declaration. The current approach was largely driven by the assumption 
that multiple line usage was not possible (thanks for the correction on 
that one).

As far as the type and service instance meta-info declaration is 
concerned this could be expressed as:

  @avalon.info
     somekey="some value"
     anotherkey="another value"

>
> More in general, javadoc tags are attributes already, so why specify a 
> special kind of "attribute" to mark an attribute as an attribute? 
> Similarly, <attribute/> feels icky, since an xml attribute is defined as
>
>  <element attributename="attributevalue"/>

Bacause explicit attribute declarations ensure the XML based meta-info 
can be validated against a DTD.  This means that we have to deal with 
known attribute names and elements. The sort of attribute keys and 
values we are dealing with here are unknown.

> == @avalon.meta.name ==
> class     Declaration of a component type name.
>
> The name tag associates a name to a component type. The name tag is a 
> required when generating a type descriptor.
>
> === Comments ===
>
> That's a bit vague; the type DTD got me
>
>   <!--
>   The component element describes the component, it defines:
>
>   name  the human readable name of component type. Must be a string
>         containing alphanumeric characters, '.', '_' and starting
>         with a letter.
>   ... -->
>
> I think "human-readable" implies a free form string. IIUC, name is 
> used to hold a reference to a type, component, service, in map 
> structures (ie HashMaps, service managers, etc), but that only 
> requires uniqueness, not anything else.
>
> If it is _not_ used for this, then what is it used for at all?


Within Merlin it provides two functions

  (a) the association of a name to the type (e.g. "keystore") that
      can be viewed by a management tool
  (b) it establishes the default name for an implict deployment
      instance

Both name and version tags could be combined under a @avalon.component tag:

  @avalon.component name="keystore" version="2.7"


> == @avalon.meta.lifestyle ==
> class     Declaration of the lifestyle policy.

> === comments ===
>
> the above sample provides ambiguity (example: 


Agreed. This has already come up on the users list.  The lifestyle 
attribute will be folded into a sub-element of the <info> block in the 
near futue.

>
> == @avalon.meta.service ==
> class     Service export declaration from a type.
>
> This maps to '@avalon.service' from AMTAGS directly:


Yep.

>
>
>  * @avalon.meta.service type="net.osm.vault.Vault;
>  * @avalon.meta.service type="net.osm.vault.KeystoreHandler:2.1.1;
>
> note the typo, this should be:
>
>  * @avalon.meta.service type="net.osm.vault.Vault"
>  * @avalon.meta.service type="net.osm.vault.KeystoreHandler:2.1.1" 


Brain is on slow - what type?

>
>
> === comments ===
>
> Of course, the ":2.1.1" is there for a reason. The example implies 
> this is not a freeform string, but rather a specific version of a 
> service may be exported by providing ":2.1.1". Especially since no 
> prefix results in auto-addition of ":1.0.0". This seems like a bad 
> idea. These things are seperate and introducing another kind of 
> construct (the ':' within a value to seperate values) seems much worse 
> than
>
>  * @avalon.meta.service type="net.osm.vault.Vault" version="1.1.1"


Moving to an explicit version would be implicit with migration to a 
complete "common model".

> <type>
>   <info>
>     <version>5.1.0</version>
>     <name>vault</name>
>   </info>
>   <services>
>     <service type="net.osm.vault.Vault"
>         version="1.1.1"/>
>   </services>
> </type>
>
> Better stil, since the code will do
>
>     class MyVault implements net.osm.vault.Vault
>
> it is probably a better idea to have the tool determine what version 
> of Vault is exported by taking a look at what version of Vault is on 
> the compile path. That requires some work of course.


More than a little work when you take into consideration the possibility 
of multiple service defitions of the same type but with different 
versions.  This possibility exists as soon as you have stacked 
repositories mapped to stacked classloaders.

> == @avalon.meta.stage ==
> class     Lifecycle stage dependency declaration.
>
> === comments ===
>
> this is container-specific. Or perhaps excalibur-lifecycle-specific. 


It is not container specific.

It is a concept used in the majority of Avalon containers (Fortress and 
Merlin) and needs to be recognized by Phoenix because Phoenix needs to 
throw out componets that require extension stages.  This is one of those 
"crunch" issues - if we don't recognize extensions we cannot deliver 
portable defintions.

> == @avalon.meta.extension ==
> class     Lifecycle stage handling capability declaration.
>
> === comments ===
>
> this is container-specific. Or perhaps excalibur-lifecycle-specific.


Unlike the stage declaration, this can be container specific because it 
is the defintion of a components ability to provide extension handling.

>
> == @avalon.meta.logger ==
> enableLogging()     Logging channel name declaration.
>
> /**
>     * Supply of a logging channel to the component.
>     * @param logger the logging channel
>     * @avalon.meta.logger name="system"
>     */
>     public void enableLogging( Logger logger )
>     {
>         super.enableLogging( logger );
>         m_system = logger.getChildLogger( "system" );
>     }
>
> <type>
>   <info>
>     <version>2.4.0</version>
>     <name>component</name>
>   </info>
>   <loggers>
>     <logger name="system"/>
>   </loggers>
> </type>
>
> === comments ===
>
> by contract, logger.getChildLogger() should work, even without such a 
> declaration. So why is the declaration there at all? 


The declaration is there so that assemblers can do useful things.  You 
want to declare (via a directive) a logging target for a nameed 
channel.  The only way you can do this from a management tool is to pull 
in the channels declarations that a type declares.  For example, you may 
have a channel that you want to encrypt.  How does the management tool 
get a refewrence to the channel name in order to build the directive?

> In particular, what happens if you change to <logger name="blah"/>? 
> Nothing, right?


Wrong.

What changes is the information that is presented to a management tool 
and the potential for assembly stage customization and control (i.e. 
what changes is the usability and manaagability of the component system).

>
>
>
> == @avalon.meta.context ==
> contextualize()     Declaration of a specialized context class.
>
>    /**
>     * @avalon.meta.context type="net.osm.CustomContext"
>     */
>     public void contextualize( Context context )
>       throws ContextException
>     {
>         CustomContext custom = (CustomContext) context;
>         ...
>     }
>
> === commments ===
>
> that should be discouraged! The contextualize() contract is that a 
> component can expect to receive a Context, nothing /more/, nothing 
> /less/. I think BlockContext shows how problematic the above is. 


Avalon contextualize implies this constraint.  In practive many 
containers define extended context interfaces (Phoenix, Plexus, ...).  
In addition users prefer to use things like File file = 
context.getWorkingDirectory() as opposed to File file = (File) 
context.get( SOME_KEY ).  Thing is that this is required if you going to 
run a Phoneix component that assumes BlockContext.  The important point 
here is that Avalon containers need to recognize this casting criteria 
and reject the component if they cannot support it.

I.e. this is one of those CRUNCH issues.

>
> == @avalon.meta.entry ==
> contextualize()     Context entry declaration.
>
> === comments ===
>
> thought for a bit how this might be combined with 
> @avalon.meta.dependency. Probably not a good idea.


This is also one of those declarations that must be recognized.  
Optional entries can be ignored by containers, non-option cannot be 
ignored.

> == @avalon.meta.dependency ==
> service()     Service type dependency declaration.
>
> === comments ===
>
> maps to '@avalon.dependency' in AMTAGS.


Yep.

> == More on versioning ==
>
> Lots of unanswered questions.
>
> - do you really need this granular versioning? 


Yes.

> Isn't versioning per deployable unit enough? 


No. Different granularity.

>
>
> - when is a service backwards compatible? 


Backward compatibility is undefined at this time (i.e. versions are 
managed at absolutes). Looking forward, backward compatability semantics 
would require more work on things like the framework Version class.

> How do you specify a version range?


Version ranges are not included.

> - how are versions actually used in container space? What can you 
> expect to happen when you declare a version? 


Components in a hierachy can provide different versions of the same 
interface.  When your mapping a provider to a consumer component you 
basically search up the tree for a component exporting a matching 
service (where matching means equivalent interface classname and 
equivalent version).  As mentioned above - this matching algorith is 
currtently absolute but this is isolated in the equality test for a 
service reference (allowing more general version semantics in the future).

> - how "optional" can version support be in a container?


A container can ignore this information and depend on "hope".  The level 
of confidence you can assign to "hope" semantics is typically a 
container implemetation issue.  Containers that use this information can 
provide assured solutions.

>
> == summary ==
>
> use of '@avalon.meta' is a bad idea. s/@avalon.meta/@merlin/ would be 
> nice.
>
> My biggest issue is with versioning. Either go all the way and declare 
> (for example) that the arguments to some of the tags are urns in the 
> avalon namespace (and declare the format for urns in that namespace), 
> or be consistent in application of a pattern.
>
> Also, I'm sceptical as to the need of this granular kind of 
> versioning, especially with regard to implementations.
>
> === existing merlin tags ===
>
> @avalon.meta.namespace        should just dissapear


+1

>
> @avalon.meta.version        should just use '@version', if
>    needed at all

-1 mixes different concerns

>
> @avalon.meta.attribute        should just dissapear; this stuff
>    is attributes already. If there's really a need for avalon container
>    support, just implement a generic algorithm that stores all unknown
>    attributes (or even all attributes), rather than invent a new
>    mechanism 


-1 should not dissapear - tag spec and structure can be improved

> @avalon.meta.name        needs more specification as to intended
>    usage, and perhaps should allow free-form strings


+1 on more specification
-1 on free-form strings

>
>
> @avalon.meta.lifestyle        no comment
>
> @avalon.meta.service        <-> AMTAGS @avalon.service; concerns
>    about versioning setup
>
> @avalon.meta.stage        tied to excalibur-lifecycle package
>
> @avalon.meta.extension        tied to excalibur-lifecycle package
>
> @avalon.meta.logger        should just dissapear


-1
Put on a suite, re-read email, and think about management implications.

>
> @avalon.meta.context        has a use case because there exist
>    components that depend on specific context implementations or
>    extensions (ie BlockContext), but should be discouraged


If you have a complete interoperable solution - then there is no need to 
discourage the practice.  It is possible to provide solutions to both 
context casting and context semantic additions (and both are required if 
you want to provide complete Phoenix compatibility).  All we should be 
addressing here is "what information at the tag level is needed to 
completely declare the criteria of a component type".  Using Phoenix as 
a case study this means (a) context casting assumptions, (b) context 
enty assumptions, (c) context behavioural assumptions.  Our tag model 
for context has to address all three.

>
> @avalon.meta.entry        no comment
>
> @avalon.meta.dependency        <-> AMTAGS @avalon.service; concerns
>    about versioning setup
>
>
> == conclusion ==
>
> The tags currently in use by merlin are not ready for generalization 
> into a "full suite of tags". I think some things do not make sense, 
> and in other places contracts are underspecified.


I think you have made some good suggestions for improving the Merlin tag 
suite.  I also think you still missing the point about what is really 
required for a generic and complete specification that would enable 
"assured component portability" and "assured component integrity".  What 
I'm talking about is recognizing that a bunch of stuff MUST BE 
RECOGNIZED irrespective of container support.  Until we reach a general 
acceptance of this truth a common tag model will be of little value.

Cheers, Steve.

-- 

Stephen J. McConnell
mailto:mcconnell@apache.org
http://www.osm.net

Sent via James running under Merlin as an NT service.
http://avalon.apache.org/sandbox/merlin



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