Cameron:


The declaration of an <api> classloader set (under the classloader or under a service export directive) is basically stating to the container that to use service X, you need to have in you classloader jar files A, B and C. Problem here is that the your going to express A, B and C in terms of jar artifact references as opposed to specification references.

What we want to be able to say - for a particular service export - is ... "to use this service the consumer's classloader needs to provide support for specification X". If we look at the consumer's classloader we can check manifest entries for the Extension-Name combined with a compatibility check relative to Specification-Version.

Example Manifest:

  Extension-Name: urn:apache:widget
  Specification-Version: 2.1

Example <service> declaration.

   <services>
     <service type="org.apache.Widget>
       <specification>
         <name>urn:apache:widget</name>
         <version>2.1</version>
         <artifact>apache/widget#2.1</artifact>
       </specification>
     </service>
   </services>

In the above example the <specification> elements is basically saying:

  1. any consumer of this service should exist within a classloader
     that provides support for the "urn:apache:widget" specification
     version 2.1.

  2. when constructing the classloader, if the parent classloader
     does not provide support for the specification, then add the
     supplied artifact to the classloader.

This also implies that the "apache/widget#2.1" artifact should not be declared in the <classloader> declaration.

The above becomes possible *if* (a) the repository maintains a cache or extension ids and versions, (b) container classloader construction is moved to the repository code, (c) optional extension management that is currently handled in the classloader model is moved to the repository classloader builder implementation, and (d) packages actually declare specification versions.

Taking the approach of declaring specific artifacts as in the service definition is IMO the wrong approach because this ties the block definition to a particular artifact (e.g. "apache/widget#2.1") when for example the actual artifact in a parent classloader could be "apache/widget#2.1.2".

WDYT?

Cheers, Stephen.


Cameron Fieber wrote:
I was thinking about a new feature to partition the classpath into
public and private (or api and impl) sections in the block.xml. This
would allow a block.xml that is exporting one or more services to define
the jars for its service's APIs in a public section of the classpath. Then, if that block.xml or jar was included in a higher level container,
that container would include the public section of the included block's
classpath in it's classpath.


This would ensure is that the classes for a service API would be defined
in the correct classloader so that any client of that service would be
able to access it without running into classloader grief.

A potential complication could arise if a container includes a block,
then exports services from that included block.  I haven't fully thought
through how that would work, but it doesn't seem too bad to solve.

My main motivation is to allow me to define groups of components in
jars, and be able to include them into higher level containers without
(preferably) having to modify the classpath of that higher level
container.

Any thoughts or opinions?  I'll try to take a stab at an implementation
this weekend to flesh out my example a bit better.

Example:  A FooService is specified in the block.xml included in
foo-impl-1.0.jar.  FooService's interface is defined in foo-api-1.0.jar,
and it uses a data object defined in foo-bean-1.0.jar.  Since these are
defined in the api section of the block's classpath, when the block is
included in the the root container, those artifacts are promoted to the
root container's classpath.

root-block.xml:
<container name="root">

  <classpath>
    <impl>
      <repository>
        <resource id="bar:foouser-impl" version="1.0"/>
        <!-- ... -->
      </repository>
    </impl>
  </classpath>

<include name="fooService" id="bar:foo-impl" version="1.0"/>

<component name="fooUser" class="com.bar.foouser.impl.FooUserImpl"/>

</container>

nested-block.xml:
<container name="nested">
  <services>
    <service type="com.bar.foo.FooService">
      <source>fooService</source>
    </service>
  </services>

  <classloader>
    <api>
      <repository>
        <resource id="bar:foo-api" version="1.0"/>
        <resource id="bar:foo-bean" version="1.0"/>
      </repository>
    </api>
    <impl>
      <repository>
        <resource id="bar:foo-impl" version="1.0"/>
        <!-- ... -->
      </repository>
    </impl>
  </classloader>

  <component name="fooService" class="com.bar.foo.impl.FooServiceImpl"/>
</container>


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]




--

|---------------------------------------|
| Magic by Merlin                       |
| Production by Avalon                  |
|                                       |
| http://avalon.apache.org              |
|---------------------------------------|

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to