You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Leo Simons <le...@apache.org> on 2003/06/17 23:18:31 UTC

[merlin] concepts, embedding fortress

Block Engine Configuration
--------------------------
on

http://avalon.apache.org/sandbox/merlin/meta/model/block/container/index.html 


it reads: "An engine is an extended classloader."

that does not make sense to me. I would call it "classloader":

<classloader>
   <classpath>
     <repository>
       <resource id="tutorial:composition-api" version="1.0"/>
     </repository>
   </classpath>
</classloader>

also, what is the actual difference between

   <engine>
     <library dir=".">
       <include name="dist">
       <include name="lib">
     </library>
   </engine>

and

   <engine>
     <classpath>
     <fileset dir="./dist">
       <include name="*.jar"/>
     </fileset>
     <fileset dir="./lib">
       <include name="*.jar"/>
     </fileset>
     </classpath>
   </engine>

? IIUC, the <library/> directive can contain lifecycle extension 
declarations, whereas the normal <classpath/> does not. So <classpath/> 
is about making stuff available to components in a block, and <library/> 
about making stuff available to the block's container (where the 
container also gets access to the <classpath/> stuff). Right?

I'd just state it like that, and change <library/> to 
<container-classpath/> or something similar. Perhaps having a 
<classloader/> and a <systemclassloader/> containing PATH-like structures.


.xprofile and block.xml
-----------------------
I started changing the samples, but it occured to me that the rule is 
"everything that can be defined in the .xprofile can be overriden inside 
the <component/> element of a block.xml". What should be added is what 
the rules are for overriding/merging those, and then the .xprofile 
settings seperated out. Right?

Where do I find those rules?


Custom containers
-----------------
Embedding fortress is the goal. Step one is including it as a component. 
That works of course, but I want the components hosted in a fortress 
container exported and available to its peers in some way.

IOW, I think I want something like

<block>
    <info>
      <name>merlin-fortress-interop-demo</name>
    </info>
    <implementation>
      <engine>
        <classpath>
          <fileset dir="lib/fortress">
            <include name="avalon-fortress-complete-1.0.jar"/>
          </fileset>
        </classpath>
      </engine>

      <container name="fortress"
         class="org.apache.avalon.merlin.fortress.FortressContainer">

         <configuration>
          <class>org.apache.avalon.fortress.impl.DefaultContainer</class>
          <xconf>
<!-- fortress.xconf contents here -->
          </xconf>
          <xlog>
<!-- fortress.xlog contents here -->
          </xlog>
         </configuration>
      </container>

    </implementation>

<component
   name="test1"
   class="tutorial.FortressCallingComponent"
   activation="startup">

   <dependencies>
      <!-- what does this look like??? -->
      <dependency key="somethinghostedinfortress" type="Component1"/>
   </dependencies>

</component>
</block>

where o.a.a.m.f.FortressContainer creates a Context that is passed to 
f.impl.DefaultContainerManager to set up a f.impl.DefaultContainer. Idea 
is simple, how to do it is very blurry. For example:

- what is the minimum contract o.a.a.m.f.FortressContainer should 
support? Clearly, it will not do everything a 'normal' merlin container 
instance does. For example, it's not going to support stuff like 
container nesting. It's just going to provide whatever it is that 
fortress provides.

- what interfaces should it implement besides Container? The Container 
interface is all but empty; that can't be right, can it?

- what's the deal with the Merlin DefaultContainer and StandardBlock? 
There's next to no implementation in DefaultContainer, yet this works in 
'some' way 'somewhere'. I have a feeling I'll be wanting to tell lots of 
assembly and appliance stuff to keep out of the way...

:-$

a few pointers would be nice :d

g'night,

- LSD



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


Re: [merlin] concepts, embedding fortress

Posted by Stephen McConnell <mc...@apache.org>.

Leo Simons wrote:

> Block Engine Configuration
> --------------------------
> on
>
> http://avalon.apache.org/sandbox/merlin/meta/model/block/container/index.html 
>
>
> it reads: "An engine is an extended classloader."
>
> that does not make sense to me. I would call it "classloader":
>
> <classloader>
>   <classpath>
>     <repository>
>       <resource id="tutorial:composition-api" version="1.0"/>
>     </repository>
>   </classpath>
> </classloader> 


Updated.
The <engine> tag has been replaced with the <classloader> tag. 
(the implementation remains backward compatible).
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


Re: [merlin] concepts, embedding fortress

Posted by Leo Simons <le...@apache.org>.
Anton Tagunov wrote:
> Hi, Leo!
> 
> LS> public class AbstractFortressServicable extends AbstractLogEnabled
> 
> Just for fun, what is this code doing? (i do not speak merlin, that's
>                                         the fun :-)

probably nothing as it was top-of-head-to-show-a-concept. I no longer 
have access to the actual code I wrote...

> I mean did I get it right that you bypass the limitation that
> you may lookup only those components on which the dependency
> has been declared, and instead you gain access to all the
> components hosted by your container?

not exactly. The AbstractFortressServicable here is sort of "wrapping" 
around a fortress instance. Fortress is a subcontainer inside your 
component. Of course, you can share that subcontainer component.

Everything is a component :D

(...)

you declare a dependency on a fortress instance, and this fortress 
instance exposes components you could lookup from it. So you use the 
fortress Container as a sort-of "service manager". Since most of your 
component doesn't care about where it gets the components from, 
basically join the services your fortress container provides with the 
ones in your servicemanager.

Useful if you embed something like fortress inside a phoenix block (for 
example).

cheers!

- Leo



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


Re[2]: [merlin] concepts, embedding fortress

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hi, Leo!

LS> public class AbstractFortressServicable extends AbstractLogEnabled

Just for fun, what is this code doing? (i do not speak merlin, that's
                                        the fun :-)
                                        
I mean did I get it right that you bypass the limitation that
you may lookup only those components on which the dependency
has been declared, and instead you gain access to all the
components hosted by your container?

-Anton


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


Re: [merlin] concepts, embedding fortress

Posted by Nicola Ken Barozzi <ni...@apache.org>.
Leo Simons wrote, On 18/06/2003 21.22:

...
> this stuff is fun :D

What?!?!

Listen Leo, be careful before you say these words! I'm not used to them 
anymore here!

;-)))

-- 
Nicola Ken Barozzi                   nicolaken@apache.org
             - verba volant, scripta manent -
    (discussions get forgotten, just code remains)
---------------------------------------------------------------------



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


Re: [merlin] concepts, embedding fortress

Posted by Leo Simons <le...@apache.org>.
Stephen McConnell wrote:
> Service availability is handled at assembly time (i.e. before the 
> instantiation of any components). If you want dynamic service selection 
> at runtime then you need to be accessing a service that provides support 
> for this (e.g. component X provides brokerage service S - component Y 
> declares dependency on X).

:/. That's effectively back to the phoenix world then. These things 
don't fly that imo nicely, but a 'mixin' provides for an adaptable setup 
still.... anyways, for my particular highly dynamic usecase, I need (and 
think will use):

/**
  * An abstract class which expects a fortress container and will
  * try and look up dependencies from that container instance before
  * trying the 'regular' ServiceManager. Useful for applications that
  * embed fortress as a 'subcontainer'.
  */
public class AbstractFortressServicable extends AbstractLogEnabled
		implements Servicable
{
         private ServiceManager m_parent;

	private Container m_c; // fortress container
	private Map m_refs = new HashMap();
	private List m_parentRefs = new ArrayList();

	private ServiceManager m_sm;

	/**
	 * Note: if your metadata parser tool does not parse
          *       dependencies for base classes, you will have
          *       to add a dependency on
          *       org.apache.avalon.fortress.Container
          *       in some other way
          *
          * @avalon.dependency
          *   type="org.apache.avalon.fortress.Container"
          * @avalon.meta.dependency
          *   type="org.apache.avalon.fortress.Container"
          * @phoenix.dependency
          *   name="org.apache.avalon.fortress.Container"
          */
	public void service( final ServiceManager sm )
	{
                 m_parent = sm;
		m_c = sm.lookup( c.ROLE );
		m_sm = new MyServiceManager();
	}

	/** get access to the servicemanager. Warning:
          * the provided ServiceManager is *not* threadsafe! */
	protected final ServiceManager getServiceManager()
	{
		return m_sm;
	}

	private class MyServiceManager implements ServiceManager
	{

		public Object lookup( final String role )
			throws ServiceException
		{
			if( !hasService( role ) )
				throw new ServiceException(
					role );

			if( m_c.has( role, null ) )
			{
				final ComponentHandler h = m_c.get(
					role, null );
				final Object comp = h.get();
				m_refs.put( comp, h );
				return comp;
			}
			else
			{
				final Object comp =
					m_parent.get( role );
				m_parentRefs.add( comp );
				return comp;
			}
		}

		public boolean hasService( final String role )
		{
			return m_c.has( role, null ) ||
				m_parent.hasService( role );
		}

		public void release( final Object comp )
		{
			if( refs.containsKey( comp ) )
			{
				final ComponentHandler h =
					m_refs.remove( comp );
				h.put( comp );
			}
			else if( m_parentRefs.contains( comp ) )
			{
				m_parentRefs.remove( comp );
				m_parent.release( comp );
			}
		}
	} // end of MyServiceManager
}

public class MyClient extends AbstractFortressServicable
	implements MyService
{
   protected FortressProvidedService getFPS()
       ServiceException
   {
     return getServiceManager().lookup( FortressProvidedService.ROLE );
   }
   protected void releaseFPS( FortressProvidedService fps );
   {
     getServiceManager().release( fps );
   }
}

while this is certainly workable (as its been working in 
phoenix+fortress-based apps for a long time now), it's not totally clean:

1) al your components actually depend on Container
2) the meta generation tool has to be able to parse dependencies 
declared by base classes
3) you need a 'utility jar' with AbstractServicable
4) you really need to use an inner class to do this cleanly

the advantages:

5) it has a potential to easily work in any container, ensuring 
component portability
6) nastiness is isolated in AbstractServicable

>> well, I don't want [merlin to autoresolve all deps]! Or really,
 >> I want to tell it how to take
>> care of that: I want to be able to configure at deployment time 
>> (perhaps even runtime) that for some services that MyGraphicalClient 
>> asks for, merlin will defer the call to MyFortressContainer.
> 
> http://avalon.apache.org/sandbox/merlin/starting/advanced/selectors.html

IIUC, that would mean I'd have to have

<type>
   <!-- ... -->
   <dependencies>
     <dependency key="(...)" type="(...)">
       <attributes>
         <attribute key="urn:avalon:profile.selector" value="(...)"/>
       </attributes>
     </dependency>
   </dependencies>
</type>

for all the dependency declarations of all my components! No thanks!

>> Maybe the contract on a <container/> implementation is a bit heavy then? 
> 
> It's not too heavy for what Merlin does but its probably too heavy for 
> what you have in mind.  Keep in mind that the "block" notion is all 
> about defintion of new components using other components as the logical 
> implementation.

yeah, I understand how the current setup makes sense as long as you just 
want to use the containment/container scenarios merlin supports out of 
the box. I think this thread shows advanced customization is currently 
harder than potentially possible.

preliminary conclusion: Merlin is not a fully "profilable" container at 
this point in time, and some work is neccessary to make it into one :D

> [neat example] is what the block concept is all about.

agreed. The problem I've found here is that setting up a merlin block 
that is completely different in implementation and internal organisation 
but still is completely usable by other (more standard) merlin blocks is 
far from trivial. Which imo is one of our goals with the bundle API stuff :D

>> hmm. COP-wise, I want merlin to provide a sandbox containment 
>> environment containing my fortress instance, and I want it to route 
>> some component lookup calls to this instance, where the "some" is to 
>> be dynamically configurable. So from merlin's view, I am talking about 
>> computations on both the container and the component sides. Indeed, I 
>> am wanting to modify the containment environment. 
> 
> Yep.
> No problem.
> 1. component invokes lookup on its service manager
> 2. the service manager implementation holds a reference
>   to the appliance managing the component
> 3. the managing appliance has already been assembles with
>   references to multiple provider appliance instances that
>   are capable of handling respective service dependencies
>   (a) you can influence the selection process by supplying
>       a custom profile selector

step 3 is the nontrivial part, because you need to write your own 
appliance, which is a heavy contract.

> 5. the service manager implementation invokes resolve on the
>   fortress appliance (assuming lookup was for a service
>   that the fortress appliance has been assigned to provide)
> 6. the fortress appliance gets hit with a resolve() request
>   and does its stuff and returns a service reference to
>   the service manager implementation
> 7. service manager implementation returns reference to
>   component implementation

yep. It's possible :D

>>>  ServiceDescriptor[] getServices();
>>>  Object resolve( Object source, String ref );
>>
>> sounds like sort-of what I need. But isn't this a functional contract 
>> identified here, something which deserves to be marked with an 
>> interface rather than an abstract base class? 
> 
> Its defined by the Appliance interface.

yeah, but Appliance also defines lots of other stuff. The fact that it 
is feasible and desirable to seperate that interface into a common base 
and an implementation seems to indicate that it also possible to split 
it into two interfaces, IOW, it might be a good idea to replace the 
inheritance you suggest here with composition resulting in less 
coupling. OOP 201 ;D

> I'm currently working on the 
> appliance implementation (making the contextualization patterns for 
> appliance instances easier to work with). As a result I have some 
> uncommitted code which I want to get into CVS as soon as I'm done.

In that case, I'm not going to write a FortressAppliance at this point.

I think I've given you some ideas of possible needs you might want to 
incorporate or just let simmer. In the meantime, I'll use 
AbstractServicable and a fortress block like you've explained works well 
for james.

It should be possible to switch to using a custom appliance just by 
changing AbstractServicable and some config files later.

this stuff is fun :D

g'night,

- Leo



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


Re: [merlin] concepts, embedding fortress

Posted by Stephen McConnell <mc...@apache.org>.

Leo Simons wrote:

> Stephen McConnell wrote:
>
>> Leo Simons wrote:
>>
>>>   <engine>
>>>     <library dir=".">?
>>
> >
>
>> The <library> declaration is simply the declaration of a directory in 
>> which you have "jar extension jar files".  This is the same notion as 
>> the java -Djava.ext.dirs except that it packaged with and only 
>> visible within the scope of the classloader (engine) in which it 
>> defined.
>
>
> ah. So the contract is "anything you put in a library dir will be 
> treated with respect to this block/engine as if it were a downloaded 
> optional package".


Correct.

>
>> Path structures inside a classloader defition are problamatic because 
>> they result in physical paths in block defintions.  This was the 
>> reason for the introduction of the <resource> tag - a better approach 
>> that uses a logical repository.
>
>
> hmm. Have you thought about using classworlds? Also, what about using 
> sourceresolve? (...thinking...) This is imo something to tackle as 
> part of a not-so-avalon-specific bundle api.


Have though about classworlds as part of the thinking about seperating 
out the different aspects of the engine.  But it hasn't gone beyond the 
thinking stage.

>
> .xprofile and block.xml
> -----------------------
>
>>> I started changing the samples, but it occured to me that the rule 
>>> is "everything that can be defined in the .xprofile can be overriden 
>>> inside the <component/> element of a block.xml". What should be 
>>> added is what the rules are for overriding/merging those, and then 
>>> the .xprofile settings seperated out. Right? 
>>
>>
>> Not sure if you saying "should be added to the documetation" or 
>> "should be added to the implementation".
>
>
> docs. They're full of samples but I keep getting the feeling the 
> samples don't come close to outlining the scope of actual 
> possibilities, or the limits. 


Priority has been to get in place the fundimentals. At this level the 
usage of configration, context, and dependency management is reasonably 
complete.  Examples for logging and parameterization directives are 
still outstanding.  Some of the more advanced topics are still pending 
(which is also the area your getting into).

>
>> Currently profiles exist only as a facility enabling automated 
>> assembly (pre-packaged deployment information).  A <component> tag is 
>> simply declaring a new profile dynamically.
>>
>> There have already been requests for things like component directives 
>> by reference to a profile (e.g.)
>
>
> Okay, I thought this was already possible. So a <component/> tag in a 
> block.xml contains a profile defitions, it doesn't customize an 
> existing one.


Correct.

> Where do I find those rules? 


It's not a rule - its a reflection of available features.  Keep in mind 
that the seperation of the three packages (a) meta, (b) assembly, and 
(c) merlin provides a lot of flexibility in what is possible.  Merlin is 
a rather samll container that reall makes the assembly and meta apis 
work for a living.

>
>> There isn't a formal model for rules related to what is and isn't 
>> modifiable reative to profiles.  I have been thinking about this on 
>> and off with respect to the JMX stuff. For everything in the 
>> meta-data model (all of the directives) we really need additional 
>> information about read versus writable, and probably some additional 
>> typing and constraint info.  The biggest job is dealing with 
>> configurations and enabling arbitary configuration data.
>
>
> yeah, dtds won't work there. There's alternatives like relaxng that 
> might help here though. Regardless of a formal model, how does one 
> discern current limitations of the implementation codebase?


Via imagination, exploration, experimentation, frustration and 
implementation (in that order).

>
>>> Custom containers
>>> -----------------
>>
>
> ok, you confused me even more :D
>
> let me explain a little where I'm going. I have a fortress-based 
> servlet application (say, for example, a scriptable web-based media 
> management catalogus and webradio broadcast system). Now I want to 
> port this application to run inside a merlin (CLI) environment. IE, 
> merlin replaces the servlet engine.
>
> I've extended fortress' DefaultContainer to provide some very specific 
> features (example: it handles communication with the linux ALSA 
> system), so I don't want to just port my components to merlin. I want 
> to embed fortress inside merlin.
>
> I want to develop (example) a graphical swing client that runs inside 
> the same merlin instance and/or remotely. For the local version, I 
> want sm.lookup() calls inside this block to be resolved to my 
> fortress-based container. 


To rephrase:

You want to implement a component that will be managed by Merlin.  The 
component implementation is going to invoke lookup on a supplied service 
manager and you want to get back services that happen to be established 
using Fortress.

>
>
> So:
>
> .-----------------------------------.
> | Merlin                            |
> |                                   |
> | -1---------------------     3  /-----some binary tcp/ip-based call
> | | MyFortressContainer |<------/   |  that is the equivalent of
> | | ------  ------      |           |  lookup()
> | | | C1 |  | C2 |      |           |
> | | ------  ------      |<--------  |
> | -----------------------        |  |
> |                                |  |
> | -2--------------------- <Redirect>|
> | | MyGraphicalClient   |        |  |
> | | ------  ------      |        |  |
> | | | C3 |  | C4 |-lookup("C1")--|  |
> | | ------  ------      |           |
> | -----------------------           |
> .-----------------------------------.
>
> now, what I want to create here is the box labelled "1"; process 
> labelled "3" does not yet exist but will probably involve a 
> MyRemoteClient. Box labelled "2" will be a more or less standard 
> merlin block, but I might build it (example) using Berin's GuiApp 
> which might mean another embedded fortress instance. 


No problem in the above.

> However, my guess is that you want to have the services available from 
> you component as a function of the configuration of the component.
>
> going further, I would like merlin to just poll whether a service is 
> provided by MyFortressContainer. There might be, for example, a QOS 
> assurance built-in that will disable service availability based on 
> instrumentation results, and merlin should just query at lookup time 
> whether a service is available.


Service availability is handled at assembly time (i.e. before the 
instantiation of any components). If you want dynamic service selection 
at runtime then you need to be accessing a service that provides support 
for this (e.g. component X provides brokerage service S - component Y 
declares dependency on X).


> A little off-topic but I would recommend using [<repository/>]
>
> "Repository" introduces a load of implications I'm not ready to deal 
> with. My guess is that it will be easier for me to switch from 
> filesystem to repo than the other way around :D 


Swithing is nothing (either way) - the more interesting thing is 
packaging and portability of the final result. But anyway its not so 
important because the repository stuff is still evolving.


> In either case (component or container), if you want to provide the 
> Merlin assembly system with information about available services that 
> are established dynamically.
>
> yes!
>
>> The assembly system get this information from 
>> Appliance.getServices().  The appliance is a regular component that 
>> is supplied with the deplyment information (configuration, etc.).  An 
>> implementation would use the configuration information (roles files 
>> etc. in the Fortrress case) to build the descriptions of the services 
>> it is capable providing.
>
>
> ok, so in merlin-speak, I'm not looking towards providing a Container 
> implementation but an Appliance implementation. 


Correct.

> Makes me wonder when one would want to provide a custom Container 
> implementation, ever, at all. 


Its a good question.  Is there really a need for a client side 
(component) aspect when handling a containment problem.

>
>
>>>     <component
>>>        name="test1"
>>>        class="tutorial.FortressCallingComponent"
>>>        activation="startup">
>>>
>>>        <dependencies>
>>>          <!-- what does this look like??? -->
>>>          <dependency key="somethinghostedinfortress" 
>>> type="Component1"/>
>>>        </dependencies>
>>
>>
>> Merlin takes care of dependency resolution automatically.  If "test1" 
>> needs a service then merlin will take care of resolving that dependency.
>
>
> well, I don't want it to! Or really, I want to tell it how to take 
> care of that: I want to be able to configure at deployment time 
> (perhaps even runtime) that for some services that MyGraphicalClient 
> asks for, merlin will defer the call to MyFortressContainer.


http://avalon.apache.org/sandbox/merlin/starting/advanced/selectors.html

>
>>> - what is the minimum contract o.a.a.m.f.FortressContainer should 
>>> support?
>>
>>
>> Nothing.
>>
>>  The only real difference [to a component] is that is has access to
>> other appliance instances and as such it can do a lot more dynamic 
>> stuff.
>
>
> ehm. Okay. So it doesn't *have* to do anything but it *can* gain 
> access to any part of the system if it wants to. Got it. However, that 
> raises security questions...and seems to violate IoC. 


I agree. In fact I could imagine Container and DefaultContainer 
dissapearing (but I need to do some refactoring first of all).

> Clearly, it will not do everything a 'normal' merlin container 
> instance does. For example, it's not going to support stuff like 
> container nesting. It's just going to provide whatever it is that 
> fortress provides.
>
>>
>> Which is why it should be declared as a <component>, not <container>. 
>> If you declare it as a container then you containment side appliance 
>> has additional responsibilities including handling nested components, 
>> containers, includes, etc.
>
>
> Maybe the contract on a <container/> implementation is a bit heavy then? 


It's not too heavy for what Merlin does but its probably too heavy for 
what you have in mind.  Keep in mind that the "block" notion is all 
about defintion of new components using other components as the logical 
implementation.  I've been working on a new James block defintion that 
basically assemables different services exposed by cornerstone blocks.  
The current result are really positive. 

Here is a look at a fragment of the James block descriptor:

<block>

   <info>
     <name>james</name>
   </info>

   <!--
   Service provided by this block.
   Please not that in order to use these services, you must ensure that
   the required API classes are available in a classloader within the scope
   of a container using these services.
   -->
  <services>
    <service type="org.apache.james.services.MailServer:1.0">
      <source>/james</source>
    </service>
    <service type="org.apache.mailet.MailetContext:1.0">
      <source>/james</source>
    </service>
  </services>

   <!--
   Block implementation.  The implementation element may contain component
   and container entities. The block implementation statement is equivalent
   to a root container.
   -->
   <implementation>

     <categories priority="INFO"/>

     <engine>
       <classpath>
         <repository>
           <resource id="excalibur:excalibur-io" version="1.1"/>
           <resource id="excalibur:excalibur-pool" version="1.2"/>
           <resource id="excalibur:excalibur-thread" version="1.1.1"/>
           <resource id="excalibur:excalibur-threadcontext" version="1.0"/>
           <resource id="excalibur:excalibur-collections" version="1.0"/>
           <resource id="commons:commons-collections" version="2.1"/>

           <resource id="cornerstone-threads:cornerstone-threads-api"
              version="1.0"/>
           <resource id="cornerstone-sockets:cornerstone-sockets-api"
              version="1.0"/>
           <resource id="cornerstone-connection:cornerstone-connection-api"
              version="1.0"/>
           <resource id="cornerstone-scheduler:cornerstone-scheduler-api"
              version="1.0"/>

           <resource id="cornerstone:cornerstone-datasources" 
version="1.0"/>
           <resource id="cornerstone:cornerstone-store" version="1.0"/>
           <resource id="james:dnsjava" version="1.3.2"/>
           <resource id="james:mail" version="1.3"/>
           <resource id="james:activation" version="1.0"/>
           <resource id="james:mailet" version="1.0"/>
           <resource id="james:james" version="1.3"/>
         </repository>
       </classpath>
     </engine>

     <include name="threads">
       <resource id="cornerstone-threads:cornerstone-threads-impl" 
version="1.0"/>
     </include>

     <include name="sockets">
       <resource id="cornerstone-sockets:cornerstone-sockets-impl" 
version="1.0"/>
     </include>

     <include name="connections">
       <resource id="cornerstone-connection:cornerstone-connection-impl" 
version="1.0"/>
     </include>

     <include name="scheduler">
       <resource id="cornerstone-scheduler:cornerstone-scheduler-impl" 
version="1.0"/>
     </include>

     <component name="james" class="org.apache.james.James"
           activation="true">
       <configuration>
         <!-- james config -->
       <configuration>
     </config>

     <!-- other components used in james -->

   </implementation>

</block>

In turn, the james block can be included in other block defintions:

     <include name="james">
       <resource id="james:james-impl" version="3.0"/>
       <targets>
         <!-- configuration and logging overrides -->
       </targets>
     </include>

This is what the block concept is all about.


> - what's the deal with the Merlin DefaultContainer and StandardBlock? 
> There's next to no implementation in DefaultContainer, yet this works 
> in 'some' way 'somewhere'.
>
>>
>> The DefaultContainer doesn't need to do anything because all of the 
>> work is done behind the scenes in StandardBlock.
>
>
> everytime I read "behind the scenes" it seems to be one of those 
> occurences when the runtime callstack becomes difficult to track in a 
> debugger for lineair minds such as me :D


ROTFL!

Yep - the sort of thing that abstract minds like my own are totally 
comfortable with.

:-)


>
>> Throught the Merlin system there is a strict seperation of 
>> "containement" concerns from "component". Given that the services 
>> that the FortressContainerwould be providing would be a function of 
>> its configuration - you are taking about computation that is 
>> happening on the container side.
>
>
> hmm. COP-wise, I want merlin to provide a sandbox containment 
> environment containing my fortress instance, and I want it to route 
> some component lookup calls to this instance, where the "some" is to 
> be dynamically configurable. So from merlin's view, I am talking about 
> computations on both the container and the component sides. Indeed, I 
> am wanting to modify the containment environment. 


Yep.
No problem. 

1. component invokes lookup on its service manager
2. the service manager implementation holds a reference
   to the appliance managing the component
3. the managing appliance has already been assembles with
   references to multiple provider appliance instances that
   are capable of handling respective service dependencies
   (a) you can influence the selection process by supplying
       a custom profile selector
5. the service manager implementation invokes resolve on the
   fortress appliance (assuming lookup was for a service
   that the fortress appliance has been assigned to provide)
6. the fortress appliance gets hit with a resolve() request
   and does its stuff and returns a service reference to
   the service manager implementation
7. service manager implementation returns reference to
   component implementation

>
>
>> To make this easy, I have been thinking about putting in place an 
>> AbstractAppliance - something that contains default implementations 
>> of everything such that all you need to do is grab the supplied 
>> configuration and override the following methods:
>>
>>  ServiceDescriptor[] getServices();
>>  Object resolve( Object source, String ref );
>>
>> The getServices() method would simply build an array of 
>> ServiceDescriptors using the information from the configuration 
>> supplied to the appliance.  The resolve method would return service 
>> references based on the fortress implementation.
>
>
> sounds like sort-of what I need. But isn't this a functional contract 
> identified here, something which deserves to be marked with an 
> interface rather than an abstract base class? 


Its defined by the Appliance interface.
http://avalon.apache.org/sandbox/merlin/api/org/apache/avalon/assembly/appliance/Appliance.html

> Call it "Container" and we're getting at fortress-compatible terms 
> again :D
>
> What I don't like about this interface is that it presumes that an 
> implementation will have available an enumeration of services that it 
> is able to provide (and implying those will still be able somewhere at 
> any later point in time), which is not the case.
>
> IOW, I have available:
>
> interface Container
> {
>     Object get( String key, Object hint ) throws ServiceException;
>     boolean has( String key, Object hint );
> } 


In which case you define the service provided by appliance as a 
Container (as part your above spec) and corresponding dependencies on 
the component.

> but nothing functionally equivalent to
>
>     Object[] getAll();
>
>>> a few pointers would be nice :d 
>>
>>
>> Hope the above helps.
>
>
> well yeah, but as so often, answers are raising more questions :D 


Naturally.

> Let me know if you want to go ahead with the appliance approach and 
> I'll refactor things to get in place an AbstractAppliance.
>
> well, uhm, no, that was not the idea...that way I wouldn't learn 
> anything about merlin! (which is the whole point for this exercise, 
> since I already have ripped the plexus cli frontend and wrapped it 
> around fortress, so that works already).


Only reason for mentioning it is that I'm currently working on the 
appliance implementation (making the contextualization patterns for 
appliance instances easier to work with). As a result I have some 
uncommitted code which I want to get into CVS as soon as I'm done.

Cheers, Steve.

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

-- 

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


Re: [merlin] concepts, embedding fortress

Posted by Leo Simons <le...@apache.org>.
Stephen McConnell wrote:
> Leo Simons wrote:
>>   <engine>
>>     <library dir=".">?
 >
> The <library> declaration is simply the declaration of a directory in 
> which you have "jar extension jar files".  This is the same notion as 
> the java -Djava.ext.dirs except that it packaged with and only visible 
> within the scope of the classloader (engine) in which it defined.

ah. So the contract is "anything you put in a library dir will be 
treated with respect to this block/engine as if it were a downloaded 
optional package".

> Path structures inside a classloader defition are problamatic because 
> they result in physical paths in block defintions.  This was the reason 
> for the introduction of the <resource> tag - a better approach that uses 
> a logical repository.

hmm. Have you thought about using classworlds? Also, what about using 
sourceresolve? (...thinking...) This is imo something to tackle as part 
of a not-so-avalon-specific bundle api.

.xprofile and block.xml
-----------------------
>> I started changing the samples, but it occured to me that the rule is 
>> "everything that can be defined in the .xprofile can be overriden 
>> inside the <component/> element of a block.xml". What should be added 
>> is what the rules are for overriding/merging those, and then the 
>> .xprofile settings seperated out. Right? 
> 
> Not sure if you saying "should be added to the documetation" or "should 
> be added to the implementation".

docs. They're full of samples but I keep getting the feeling the samples 
don't come close to outlining the scope of actual possibilities, or the 
limits.

> Currently profiles exist only as a 
> facility enabling automated assembly (pre-packaged deployment 
> information).  A <component> tag is simply declaring a new profile 
> dynamically.
> 
> There have already been requests for things like component directives by 
> reference to a profile (e.g.)

Okay, I thought this was already possible. So a <component/> tag in a 
block.xml contains a profile defitions, it doesn't customize an existing 
one.

>> Where do I find those rules?
> 
> There isn't a formal model for rules related to what is and isn't 
> modifiable reative to profiles.  I have been thinking about this on and 
> off with respect to the JMX stuff. For everything in the meta-data model 
> (all of the directives) we really need additional information about read 
> versus writable, and probably some additional typing and consttrraint 
> info.  The biggest job is dealing with configurations and enabling 
> arbitary configuration data.

yeah, dtds won't work there. There's alternatives like relaxng that 
might help here though. Regardless of a formal model, how does one 
discern current limitations of the implementation codebase?

>> Custom containers
>> -----------------

ok, you confused me even more :D

let me explain a little where I'm going. I have a fortress-based servlet 
application (say, for example, a scriptable web-based media management 
catalogus and webradio broadcast system). Now I want to port this 
application to run inside a merlin (CLI) environment. IE, merlin 
replaces the servlet engine.

I've extended fortress' DefaultContainer to provide some very specific 
features (example: it handles communication with the linux ALSA system), 
so I don't want to just port my components to merlin. I want to embed 
fortress inside merlin.

I want to develop (example) a graphical swing client that runs inside 
the same merlin instance and/or remotely. For the local version, I want 
sm.lookup() calls inside this block to be resolved to my fortress-based 
container.

So:

.-----------------------------------.
| Merlin                            |
|                                   |
| -1---------------------     3  /-----some binary tcp/ip-based call
| | MyFortressContainer |<------/   |  that is the equivalent of
| | ------  ------      |           |  lookup()
| | | C1 |  | C2 |      |           |
| | ------  ------      |<--------  |
| -----------------------        |  |
|                                |  |
| -2--------------------- <Redirect>|
| | MyGraphicalClient   |        |  |
| | ------  ------      |        |  |
| | | C3 |  | C4 |-lookup("C1")--|  |
| | ------  ------      |           |
| -----------------------           |
.-----------------------------------.

now, what I want to create here is the box labelled "1"; process 
labelled "3" does not yet exist but will probably involve a 
MyRemoteClient. Box labelled "2" will be a more or less standard merlin 
block, but I might build it (example) using Berin's GuiApp which might 
mean another embedded fortress instance.

> However, my guess is that you want to have the services 
> available from you component as a function of the configuration of the 
> component.

going further, I would like merlin to just poll whether a service is 
provided by MyFortressContainer. There might be, for example, a QOS 
assurance built-in that will disable service availability based on 
instrumentation results, and merlin should just query at lookup time 
whether a service is available.

> A little off-topic but I would recommend using [<repository/>]

"Repository" introduces a load of implications I'm not ready to deal 
with. My guess is that it will be easier for me to switch from 
filesystem to repo than the other way around :D

> In either case (component or container), if you want to provide the 
> Merlin assembly system with information about available services that 
> are established dynamically.

yes!

> The assembly system get this information 
> from Appliance.getServices().  The appliance is a regular component that 
> is supplied with the deplyment information (configuration, etc.).  An 
> implementation would use the configuration information (roles files etc. 
> in the Fortrress case) to build the descriptions of the services it is 
> capable providing.

ok, so in merlin-speak, I'm not looking towards providing a Container 
implementation but an Appliance implementation. Makes me wonder when one 
would want to provide a custom Container implementation, ever, at all.

>>     <component
>>        name="test1"
>>        class="tutorial.FortressCallingComponent"
>>        activation="startup">
>>
>>        <dependencies>
>>          <!-- what does this look like??? -->
>>          <dependency key="somethinghostedinfortress" type="Component1"/>
>>        </dependencies>
> 
> Merlin takes care of dependency resolution automatically.  If "test1" 
> needs a service then merlin will take care of resolving that dependency.

well, I don't want it to! Or really, I want to tell it how to take care 
of that: I want to be able to configure at deployment time (perhaps even 
runtime) that for some services that MyGraphicalClient asks for, merlin 
will defer the call to MyFortressContainer.

>> - what is the minimum contract o.a.a.m.f.FortressContainer should 
>> support?
> 
> Nothing.
> 
>  The only real difference [to a component] is that is has access to
> other appliance instances and as such it can do a lot more dynamic stuff.

ehm. Okay. So it doesn't *have* to do anything but it *can* gain access 
to any part of the system if it wants to. Got it. However, that raises 
security questions...and seems to violate IoC.

>> Clearly, it will not do everything a 'normal' merlin container 
>> instance does. For example, it's not going to support stuff like 
>> container nesting. It's just going to provide whatever it is that 
>> fortress provides. 
> 
> Which is why it should be declared as a <component>, not <container>. If 
> you declare it as a container then you containment side appliance has 
> additional responsibilities including handling nested components, 
> containers, includes, etc.

Maybe the contract on a <container/> implementation is a bit heavy then?

>> - what's the deal with the Merlin DefaultContainer and StandardBlock? 
>> There's next to no implementation in DefaultContainer, yet this works 
>> in 'some' way 'somewhere'. 
> 
> The DefaultContainer doesn't need to do anything because all of the work 
> is done behind the scenes in StandardBlock.

everytime I read "behind the scenes" it seems to be one of those 
occurences when the runtime callstack becomes difficult to track in a 
debugger for lineair minds such as me :D

> Throught the Merlin system there is a strict seperation of 
> "containement" concerns from "component". Given that the services that 
> the FortressContainerwould be providing would be a function of its 
> configuration - you are taking about computation that is happening on 
> the container side.

hmm. COP-wise, I want merlin to provide a sandbox containment 
environment containing my fortress instance, and I want it to route some 
component lookup calls to this instance, where the "some" is to be 
dynamically configurable. So from merlin's view, I am talking about 
computations on both the container and the component sides. Indeed, I am 
wanting to modify the containment environment.

> To make this easy, I have been thinking about putting in place an 
> AbstractAppliance - something that contains default implementations of 
> everything such that all you need to do is grab the supplied 
> configuration and override the following methods:
> 
>  ServiceDescriptor[] getServices();
>  Object resolve( Object source, String ref );
> 
> The getServices() method would simply build an array of 
> ServiceDescriptors using the information from the configuration supplied 
> to the appliance.  The resolve method would return service references 
> based on the fortress implementation.

sounds like sort-of what I need. But isn't this a functional contract 
identified here, something which deserves to be marked with an interface 
rather than an abstract base class?

Call it "Container" and we're getting at fortress-compatible terms again :D

What I don't like about this interface is that it presumes that an 
implementation will have available an enumeration of services that it is 
able to provide (and implying those will still be able somewhere at any 
later point in time), which is not the case.

IOW, I have available:

interface Container
{
     Object get( String key, Object hint ) throws ServiceException;
     boolean has( String key, Object hint );
}

but nothing functionally equivalent to

     Object[] getAll();

>> a few pointers would be nice :d 
> 
> Hope the above helps.

well yeah, but as so often, answers are raising more questions :D

> Let me know if you want to go ahead with the appliance approach and I'll 
> refactor things to get in place an AbstractAppliance.

well, uhm, no, that was not the idea...that way I wouldn't learn 
anything about merlin! (which is the whole point for this exercise, 
since I already have ripped the plexus cli frontend and wrapped it 
around fortress, so that works already).

cheers!

- Leo



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


Re: [merlin] concepts, embedding fortress

Posted by Stephen McConnell <mc...@apache.org>.

Leo Simons wrote:

> Block Engine Configuration
> --------------------------
> on
>
> http://avalon.apache.org/sandbox/merlin/meta/model/block/container/index.html 
>
>
> it reads: "An engine is an extended classloader."
>
> that does not make sense to me. I would call it "classloader": 


Yep, I agree.

This is also consitent with some refactoring I would like to see (namely 
seperation of the appliance repositories, and jar extension logic from 
the classloader).

>
>
> <classloader>
>   <classpath>
>     <repository>
>       <resource id="tutorial:composition-api" version="1.0"/>
>     </repository>
>   </classpath>
> </classloader>
>
> also, what is the actual difference between
>
>   <engine>
>     <library dir=".">
>       <include name="dist">
>       <include name="lib">
>     </library>
>   </engine>
>
> and
>
>   <engine>
>     <classpath>
>     <fileset dir="./dist">
>       <include name="*.jar"/>
>     </fileset>
>     <fileset dir="./lib">
>       <include name="*.jar"/>
>     </fileset>
>     </classpath>
>   </engine>
>
> ? IIUC, the <library/> directive can contain lifecycle extension 
> declarations, whereas the normal <classpath/> does not. So 
> <classpath/> is about making stuff available to components in a block, 
> and <library/> about making stuff available to the block's container 
> (where the container also gets access to the <classpath/> stuff). Right? 


Nope.

The <library> declaration is simply the declaration of a directory in 
which you have "jar extension jar files".  This is the same notion as 
the java -Djava.ext.dirs except that it packaged with and only visible 
within the scope of the classloader (engine) in which it defined.

> I'd just state it like that, and change <library/> to 
> <container-classpath/> or something similar. Perhaps having a 
> <classloader/> and a <systemclassloader/> containing PATH-like 
> structures. 


Path structures inside a classloader defition are problamatic because 
they result in physical paths in block defintions.  This was the reason 
for the introduction of the <resource> tag - a better approach that uses 
a logical repository.  The objective with the repository approach is to 
enable repository chains and repository policies (but that's all future 
stuff). Part of the rationale here is that something like a war file can 
be considered as the structural element of a repository implementation.

However, the fileset structures are handy during development (which is 
why they are available).

>
> .xprofile and block.xml
> -----------------------
> I started changing the samples, but it occured to me that the rule is 
> "everything that can be defined in the .xprofile can be overriden 
> inside the <component/> element of a block.xml". What should be added 
> is what the rules are for overriding/merging those, and then the 
> .xprofile settings seperated out. Right? 


Not sure if you saying "should be added to the documetation" or "should 
be added to the implementation".  Currently profiles exist only as a 
facility enabling automated assembly (pre-packaged deployment 
information).  A <component> tag is simply declaring a new profile 
dynamically.

There have already been requests for things like component directives by 
reference to a profile (e.g.):

   <component name="fred" profile="secure"/>

Or, customizing a packaged profile:

   <component name="fred" profile="secure">
     <configuration>
       <username>peterrabbit</username>
     </configuration>
   </component>

> Where do I find those rules?


There isn't a formal model for rules related to what is and isn't 
modifiable reative to profiles.  I have been thinking about this on and 
off with respect to the JMX stuff. For everything in the meta-data model 
(all of the directives) we really need additional information about read 
versus writable, and probably some additional typing and consttrraint 
info.  The biggest job is dealing with configurations and enabling 
arbitary configuration data.

>
>
> Custom containers
> -----------------
> Embedding fortress is the goal. Step one is including it as a 
> component. That works of course, but I want the components hosted in a 
> fortress container exported and available to its peers in some way. 


If the component type defition includes the declaration of some 
services, these services will be available to other components.  I.e. 
for a particular application scenario where the services that are 
provided by a component are know at compile time - you just use a 
component.  However, my guess is that you want to have the services 
available from you component as a function of the configuration of the 
component.

Moving on to the example:

>
>
> IOW, I think I want something like
>
> <block>
>    <info>
>      <name>merlin-fortress-interop-demo</name>
>    </info>
>    <implementation>
>      <engine>
>        <classpath>
>          <fileset dir="lib/fortress">
>            <include name="avalon-fortress-complete-1.0.jar"/>
>          </fileset>
>        </classpath>
>      </engine>
>

A little off-topic but I would recommend using the following:

     <engine>
       <classpath>
         <repository>
           <resource id="whatever:avalon-fortress-complete" version="1.0"/>
         </repository>
       </classpath>
     </engine>

This change simply means that merlin will attempt to locate the jar file 
from the jar repository.  The current implementation defaults to a file 
based repository located in the merlin installation.  The repository 
follows the same pattern as the maven repository.

>     <container name="fortress"
>         class="org.apache.avalon.merlin.fortress.FortressContainer">
>
>         <configuration>
>          <class>org.apache.avalon.fortress.impl.DefaultContainer</class>
>          <xconf>
> <!-- fortress.xconf contents here -->
>          </xconf>
>          <xlog>
> <!-- fortress.xlog contents here -->
>          </xlog>
>         </configuration>
>      </container>


The difference between a <container> and a <component> concerns the 
container side management.  There is nothing different on the component 
side except that the component implementation has access to the engine 
via the context interface.  In your example you don't need the engine 
bacuase fortress is doing the deployment stuff therefore you should use 
the <component> directive.

In either case (component or container), if you want to provide the 
Merlin assembly system with information about available services that 
are established dynamically.  The assembly system get this information 
from Appliance.getServices().  The appliance is a regular component that 
is supplied with the deplyment information (configuration, etc.).  An 
implementation would use the configuration information (roles files etc. 
in the Fortrress case) to build the descriptions of the services it is 
capable providing. 

>
>     <component
>        name="test1"
>        class="tutorial.FortressCallingComponent"
>        activation="startup">
>
>        <dependencies>
>          <!-- what does this look like??? -->
>          <dependency key="somethinghostedinfortress" type="Component1"/>
>        </dependencies>


Merlin takes care of dependency resolution automatically.  If "test1" 
needs a service then merlin will take care of resolving that dependency.

>
>      </component>
>
>    </implementation>
>
> </block>
>
> where o.a.a.m.f.FortressContainer creates a Context that is passed to 
> f.impl.DefaultContainerManager to set up a f.impl.DefaultContainer. 
> Idea is simple, how to do it is very blurry. For example:
>
> - what is the minimum contract o.a.a.m.f.FortressContainer should support?


Nothing.

Literally - nothing.  A container implementation of the component side 
is a completely passive entity relative to the Merlin internals.  It can 
do whatever it likes.  The only real difference is that is has access to 
other appliance instances and as such it can do a lot more dynamic stuff.

> Clearly, it will not do everything a 'normal' merlin container 
> instance does. For example, it's not going to support stuff like 
> container nesting. It's just going to provide whatever it is that 
> fortress provides. 


Which is why it should be declared as a <component>, not <container>. If 
you declare it as a container then you containment side appliance has 
additional responsibilities including handling nested components, 
containers, includes, etc.

> - what interfaces should it implement besides Container? 


It can implement any interface - its just a component.

> The Container interface is all but empty; that can't be right, can it?


A container can be anything you want it to be.  Because this is on the 
client side (relative to the container) - you are completely freee to 
define whatever you want independently of any Merlin API. 

>
> - what's the deal with the Merlin DefaultContainer and StandardBlock? 
> There's next to no implementation in DefaultContainer, yet this works 
> in 'some' way 'somewhere'. 


The DefaultContainer doesn't need to do anything because all of the work 
is done behind the scenes in StandardBlock. DefaultContainer includes 
meta-info that tells the assembly system to use StandardBlock as its 
containment side manager.  You would do something similar with a dynamic 
Fortress solution - declare the appliance class to use inside the type 
descriptor, provide an implementation of appliance to do the dynamic 
service info establishment based on the supplied configuration, and 
that's about it.

> I have a feeling I'll be wanting to tell lots of assembly and 
> appliance stuff to keep out of the way... 


:-)

Throught the Merlin system there is a strict seperation of 
"containement" concerns from "component". Given that the services that 
the FortressContainerwould be providing would be a function of its 
configuration - you are taking about computation that is happening on 
the container side.

To make this easy, I have been thinking about putting in place an 
AbstractAppliance - something that contains default implementations of 
everything such that all you need to do is grab the supplied 
configuration and override the following methods:

  ServiceDescriptor[] getServices();
  Object resolve( Object source, String ref );

The getServices() method would simply build an array of 
ServiceDescriptors using the information from the configuration supplied 
to the appliance.  The resolve method would return service references 
based on the fortress implementation.

> a few pointers would be nice :d 


Hope the above helps.
Let me know if you want to go ahead with the appliance approach and I'll 
refactor things to get in place an AbstractAppliance.

Cheers, Steve.

>
>
> g'night,
>
> - LSD
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
>
>
>

-- 

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