Gary Shea wrote:

Hi Steve --

Now we're getting somewhere!

:-)

[2002-11-14 02:31 +0100] Stephen McConnell ([EMAIL PROTECTED]) wrote:

Hi Gary:

See notes in line.


Gary Shea wrote:


Hey Steve --

I'm getting merlin to work for me, a little at a time. If I can ever
get all the way there it'll be great! I've got myself pretty stuck at
the moment, need some feedback.


No problem.


As I mentioned before, the UI is considered a component in this app.

In my current hand-lifecycled version, I have a giant ugly method in
which all the ui 'controllers' are created as components, one by one, in
a depth-first order wrt the tree of Swing UI relationships. Suppose
component X is responsible for displaying Y. First Y is fully lifecycled,
then X is fully lifecycled, with Y as part of X's context.


Just a comment here - when providing one component as a service to
another component, you should really be using the Serviceable interface.
While Serviceable and Contextualizable are computationaly similar -
there are some import differences. First of all in you case, presumaby
you component Y is implementating a service oriented interface which is
required by component X. If your assemblying these components manually
(i.e. building the context and service manageme object your code), and
if your following the framework patterns, you would create an instance
of DefaultServiceManager and add component X to the manager under a role
name that Y will use to reference it.

E.g. component X implements a TimeService interface and component Y is a
Scheduler that has a dependency on a service implementing the
TimeService interface. The scheduler should use the Serviceable
interface, under which it is supplied a ServiceManager, and from which
it can lookup the time service with a key.

In this scenario, your lifecycle handler you need to know the role name
to assign for the different services, and all of your components would
need to be careful about using the same role name. That's ok in a
limited scenario - but what is even better is if your utility can get
the class of the component it is processing, get a bunch of meta
information, and derive from that the service defintion and role name
that the component needs. This is achieved through the structures in
the excalibur/meta package - "the xfiles". The file named
<component-classname>.xinfo should contain a <type> element as the root,
and within this you can declare a depedency (e.g. the .xinfo for X would
declare a dependency in a time service, and component Y would declare
that it porvides the time service. If you package this information
within "x-files" your application becomes more loosely coupled because
you don;t have to follow strinct naming conventions, and keys used to
lookup services can be scoped locally within the depedency defintion of
the consuming componet.

Let me restate this as I understand it. With manual assembly, the
DefaultContext and DefaultServiceManager objects are created by hand for
each component that will be deployed. That code must have the text of
the key, meaning that to be reasonably safe the key is a public static
somewhere.
Correct - however, I think this is inherintly problamatic as it eliminates the possibility for a component to use two service that happen to implement the same interface. I'm guessing - but it does seem that I'm the probably the only one here who is holding out on this example of what has been refered to as a best practice. In my opinion, the best practice is to be explicit and to take the time to document the fully dependency information which means interface + version together with good documentation about the semantic attributed to a service interface version.

On the other hand, with automated assembly, the key is in
the .xinfo files instead of the code. I prefer that too. It's probably
a slight loss of safety since there's no consistency constraint
equivalent to the public static key that's visible everywhere in the
classloader scope, but it reduces coupling in the code, which is a very
highy priority.

Yep - good assessment of the pro and cons.

It had occurred to me switching to Service might get it, but hadn't
gotten to do the experiment yet. Glad to hear I'm on the right track.

Yep - one other thing to be aware of is that the Serviceable interface implies an additional obligation. Services aquired though a ServiceManger should also be relased back to the manager. Keep in mind that a container is putting a lot of effort into respecting lifestyle policies that object implementations assume. To propoerly respect something like a pooled policy, you need to declare to the container that you have released the service in question. The container receives bnotification of the release of a service via the ServiceManger's release operation and from that can free up resources no longer required, or other optiimization functions.


Ok, enough rambling about that - except to say that all of the above is
addressed in the excalibur/meta package and really havn't got into
Merlin space yet.


I think the reason my method doesn't want to work with merlin is that a
mapping needs to be created automatically from a deployed component to a
context key value! How could merlin know that?


Let's ignore the fact that your example talks about putting a service
into a context object and assume instead that your dealing with the
problem of populating a context object automatically. At the component
meta level (excalibur/meta) you can declare that the component instance
implemets an interface derived from the framework Context interface (if
nothing is declared for a context type then the framework Context
interface is assumed). You can also declare in the .xinfo file
<context/> element the entries to be included in the context. Context
entries include the declaration of the class of the object that is
expected, the context key the component will use to access the context,
and if the context entry is required or optional.

Yep, with you so far ;)


If we move up to the next meta level (refer excalibur/meta/model) you
have the Profile class. The profile class contains a much of structures
called directives which let you build an object model of the parameters
to be supplied to a component during lifecycle processing. For the
context object the Profile type includes support for the declaration of
a ContextDirective. A ContextDirective lets you declare two form of
context value aquisition:

* importing a context from a container using a container scoped key
* declarative construction of a context object using parameters

Yeah, I'm declaring a context value in the profile now. It makes sense.

I'm still not entirely comfortable with Profile, although I suspect
that's largely because the doc is not complete yet and I am not yet
familiar enough with the code.
Current documentation on the context directive at the profile level could be improved - what is there currently is minimal and bunch more stuff is needed to detail all of the fun things you can do with parameters, nested parameters, referencing existing context values as parameter arguments, etc.

I like using it but am still closing in
on feeling like I know what I can do with it. I think that's because
the profile is a combination of three kinds of information:

Data which is truly meta wrt the .xinfo contents:
+ the presence of a <component/> directive is metainfo telling
merlin to deploy that component in this profile, information you
cannot specify in the .xinfo

Your example is the application of <component/> as a directive within a container - which is basically telling Merlin "take this information and build a type then build a profile referencing the type, the create an instance based on the profile, and locate the instance within the enclosing container".
The second example of the use of a <component> directive is within an xprofile file. The .xprofile can contain multiple pacaged and named descriptions (profiles) which merlin can use automatically when another component declares a service dependency.

Finally (although not implemeted yet) would be the referencing of a packaged component profile from within a container.

E.g:

<component type="MyComponent" profile="persistent"/>

Or:

<component type="MyComponent" extends="persistent">
<configuration>
<connection jdbcdrive="whatever"/>
<cofiguration>
</component>

Data which is independent of the .xinfo contents:
+ can specify context keys and validation info in the .xinfo,
   can specify values in the profile

Its more correct to say that this is data that that fulfilling criteria exressed at the type level.

For example - the .xinfo declares that a context entry keyed to the name "avalon:home" must be provided and the type of argument must be a javalio.File. At the profile level you my see an import or constructor directive which is satisfying the type level criteria.

type + class <--- establishes the crieria
profile <--- populates the criteria

Data which overrides .xinfo contents:
+ configuration
+ categories

Configuration - yes - assuming the typoe has a packaged default configuration.
Categories - no. Category declaration is a directive that assign things loke the logging channel priority, logging target, etc. Wheras the type level information is purely the declaration that a named logging channel is required. Again, this follows the seperation of criteria for fullment at the type level, directives supporting fullfilment at the profile level.

Have I got that right?

You have me thinking if it would be a good idea to introduce a seperate profile tag, which would better seperate the notion of the component tag as a directive. For example:

<component type="MyComponent"activation="startup">
<profile name="default-authorization">
<!-- other profile stuff -->
</profile>
</component>

Using the excalibur/meta APIs, you can introduce a much higher degree of
loose-coupling into your lifecycle utility. You can even take avantage
of preconfigured profiles and default configurations - which make life
*much* easier for the end user.

Agreed.


Just for clarification - here is the basic seperation that the
excalibur/meta package provides, and the seperation I'm working on with
respect to synchronizing merlin with the excalibur/meta.

Type Level

An API supplimenting class information with details about
required dependencies, and extensions, service the
component provides, context and logging constraints and
type-level defaults.

http://jakarta.apache.org/avalon/excalibur/meta/type.html

Profile Level

An API that allows the capture of different deployment
profiles - where a profile is a combination of configuration,
context, parameters and logging information. It is possible
for may profile to be declared for a particular type.

http://jakarta.apache.org/avalon/excalibur/meta/profile.html

Many profiles may be declared for a particular type? My understanding
is that multipe profiles may be declared for a particular application,
each of which may assemble a particular Type in a different way. Is
there a way to say "for type X use profile P"? That sounds like a
meta-profile!

This does not sound right.

Imagine you have a component that provides a persistence service. That component implementation may provide support for multiple persistence solutions (memory based for testing, file based for convinience, database for scalable deployment). Each one of these deployment scenarios could be pre-packaged as a named profile using the <classname>.xprofile resource. During the assembly process, the assembly engine calls in a selector (which a component or container can customize). While explict references to profiles in a <component/> tag isn't isn't available yet, its possible to achieve the same thing using a custom selector (a helper that kicks in during resolution of multiple candidates during the assembly phase).

Whereas an "application profile" would be much closer to a container directive. Because an application is in effect defined by the assembly of profiled components within an application context established by things like the container's classloader, etc.


Appliance

An applicance (not in CVS yet but part of the refactoring I'm
doing in merlin to sync. with excalibur/meta updates) represents
an assembled profile and the access point to the services that
a type provides. Appliance also encapsulates lifestyle
management because this is the object that is used to actually
get an instance of a service.

[no doc yet - working on it]

This is a hard concept to put a word to because it's two things at once,
right?  The factory part which is about meta-info, and the lifestyle
management which is about meta-state.  So the the final object which
hands over the instance of the service is a lifestyle manager (which
maintains meta-state based on lifestyle meta-info), which delegates
object creation to the factory (which is a meta-info interpreter)?

Yep - hole in one.

Keep in mind that an Appliance is part of the container architecture and would not be exposed to the client. Typically the client will only see service via a service manager and the service manager implementation will interact with the appliance. However, there are lots of cases of code that manually handling the creation of service and context objects because its just plain easier and faster than declaring all of this. In those situations, a nice middle ground is to use some sort of intermidiate utility - and that's the function/role of the Appliance.


Instance

A regualar java.lang.Object, established as a result of a
request to an appliance. The identity of the instance is
a function of the lifestyle policy that the appliance is
enforcing. This object is the service from a consumers
perspective and could be a proxy of the component, a
obnject reference, etc. depending on the type of appliance
that is handling activation.

Ok, you now have my permission to add you name to the "Steve's wordy
email hate list"!

:-)

Not on your life!  I will have you know I printed this damn email, it
was too big to read on the screen. ;)   Very useful too!  Thanks for
taking the time.

No problem - more questions like this only lead to better system.

Cheers, Steve.


Gary


Hope this helps!

Cheers, Steve.


Regards,

Gary



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




--

Stephen J. McConnell

OSM SARL
digital products for a global economy
mailto:mcconnell@;osm.net
http://www.osm.net




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





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




--

Stephen J. McConnell

OSM SARL
digital products for a global economy
mailto:mcconnell@;osm.net
http://www.osm.net




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

Reply via email to