> -----Original Message-----
> From: Peter Donald [mailto:[EMAIL PROTECTED]
> Sent: Sunday, 3 February 2002 2:12 PM
> To: Ant Developers List
> Subject: Re: cvs commit:
> jakarta-ant/proposal/myrmidon/src/testcases/org/apache/myrmidon/componen
> ts/deployer DefaultDeployerTest.java TestConverter1.java TestType1.java
> 
> 
> On Sun, 3 Feb 2002 08:59, Adam Murdoch wrote:
> > > -----Original Message-----
> > > From: Peter Donald [mailto:[EMAIL PROTECTED]
> > > Sent: Sunday, 3 February 2002 12:17 AM
> > > To: Ant Developers List
> > > Subject: Re: cvs commit:
> > > 
> jakarta-ant/proposal/myrmidon/src/testcases/org/apache/myrmidon/componen
> > > ts/deployer DefaultDeployerTest.java TestConverter1.java 
> TestType1.java
> > >
> > > On Sat, 2 Feb 2002 23:51, [EMAIL PROTECTED] wrote:
> > > >   /**
> > > >    * A general-purpose type definition.
> > > >    *
> > > >    * @author <a href="mailto:[EMAIL PROTECTED]">Adam 
> Murdoch</a>
> > > >    */
> > > >   public class GeneralTypeDefinition
> > > >       extends TypeDefinition
> > > >   {
> > > >       private String m_name;
> > >
> > > vs
> > >
> > > >   public abstract class TypeDefinition
> > > >   {
> > >
> > > Is there any need to separate out the above two classes? From the
> > > looks of
> > > things - no - but is there something else you have in mind?
> >
> > Not particularly - I added GeneralTypeDefinition so that I could move
> > setType() and setName() out of TypeDefinition, where they were being
> > inherited by ConverterDefinition (and so visible as attributes in
> > <converter-def>).  Maybe we could rename TypeDefinition ->
> > AbstractTypeDefinition and GeneralTypeDefinition -> TypeDefinition.
> 
> Oh right - now it is clearer. However what I have gone and done 
> is made the 
> TypeDefinition immutable. I would personally like to see that all types 
> passed to a service (which includes passing stuff to deployer 
> from tasks etc) 
> is either made up of primitive types or immutable.
> 
> The reason for this is that a lot of problems in ant1.x is that 
> there was no 
> distinction between responsibilities of task and responsibilities of the 
> "service" and as such methods kept getting added on and causing 
> issues. Also 
> names/ideas/concepts and things kept getting out of sync between 
> the service 
> part and the task part.
> 
> So instead of directly exposing the insides of service you 
> instead expose an 
> adaptor. And then the tasks can change the adaptor to their 
> hearts content 
> for every user request without effecting the core service. So in 
> a way it is 
> making it possible to decouple the service from the task so that they can 
> evolve independently as needed.
> 
> Thoughts? Do you like this or is it too many layers? ;)
> 

I reckon it's a good approach, but you're going to have to explain it a little 
more.  I'm not entirely sure which bit you're calling the adaptor.  What would 
it be in the case of the Deployer service and def tasks?

It would be handy if you could work through a few examples of how you see 
services working.  How about these:  Using the exec manager to run an external 
command, using the java compiler manager to compile a bunch of files, and using 
the deployer to deploy something from a typelib.  What do the service 
interfaces look like?  What gets passed across?  How do the tasks evolve 
without affecting the services?  How do the tasks deal with different service 
implementations?  How does the user pass implementation specific properties to 
the service?

It probably also worth running through what I was planning to do with the 
Deployer, defs tasks, and services:

First up, some terminology.  I call anything contained in a typelib a "type", 
whether it's a service, task, data-type, converter, project builder, whatever.  
Types are categorised into roles (whether roles are flat like they are now, or 
heirarchical, doesn't matter).  As far as deployment goes, the role determines:

* How the type should be deployed.
* What properties are required in its definition.

Type definitions are built in the following ways:

1. The deployer builds a type definition from the typelib descriptor (a file).
2. A def task builds a type definition from the build file.
3. Type definitions are *not* built programmatically.

This suggests to me that type definitions should be meta-info driven.  All 
role-specific knowledge of how to define and deploy the types of a particular 
role would live in a specialised component, one per role.  The deployer itself, 
and the def task, would be general-purpose, and would use the meta-info 
provided by the specialised component, to build the type definition.  Here's 
how a type would be deployed from a typelib descriptor:

* Deployer determines the role of the type from the name of the element from 
the typelib descriptor.
* Deployer fetches meta-info for the type definition, from the appropriate role 
deployer component.
* Deployer builds and validates the type definition, using the meta-info and 
the contents of the element from the typelib descriptor.
* Deployer passes the type definition to the role deployer component, which 
does the work of deploying the type.

Deploying a type from a def task would work exactly the same, except the role 
might be determined differently, and the def task's model is used rather than 
an element from the typelib descriptor.  Otherwise the same.

Using a meta-info driven approach is inherently easier to evolve than one which 
explicitly models the different type definitions, and builds them 
programmatically.  We can add and remove stuff from the type definitions 
easily, we can change how types of a particular role are deployed, and we can 
add and remove roles - all without changing the deployer, or the def tasks.  A 
single deployer and single def task would handle every type.

Of course, meta-info driven definitions are a PITA to use programmatically.  If 
we do find that we need to build definitions programmatically, then we can 
expose some of the role-specific components as alternative services, for 
example.

I chose to combine the meta-info and the type definition into a single object - 
a bean (TypeDefinition and sub-classes).  The role deployer component creates 
the bean, it gets configured, and then passed back to the role deployer 
component.  Of course, I hadn't finished implementing this, so it wasn't real 
clear what the intention was.  I don't really care how the meta-info and the 
definition are represented.  We could even axe the meta-info, and simply pass a 
Configuration object through to the role deployer component.

So that was the plan.  I don't think it is incompatible with your plans - given 
that the goal was to put together a general-purpose mechanism for deploying 
stuff from both a typelib descriptor and from the build file.


> > * Add a ServiceDefinition sub-class, and deploy services from 
> the typelib
> > descriptor.  Maybe add a <service-def> task as well.  Need to think a
> > little more about what "deploy services" means.  Any problems 
> with putting
> > the service definitions in ant-descriptor.xml, rather than
> > ant-services.xml?
> 
> I would prefer to keep them separate for now. Deploying services 
> is a fairly 
> different concept to registering types. When you deploy a service 
> you have 
> things like lifecycle management, configuration and so forth to 
> worry about. 
> And services are controlled by the container which is different 
> from types 
> which can be controlled by anyone.
> 

Absolutely.  But putting the service definitions in a separate file doesn't 
help you deploy them.  It's just another thing to bother with when you're 
assembling typelibs.

If we do go with the meta-info model above, then it makes sense to put all the 
'types' (whatever we want to call them) in one spot.


> > * I'd like to axe the <converters> element in 
> ant-descriptor.xml, and move
> > the converters to the <types> element.
> 
> How do you plan to integrate them exactly ? 
> 

As above.  The problem I have with the current descriptor syntax, is that the 
<types> element contains definitions for *everything* in the typelib except for 
converters, which are in their own <converters> element.  So the semantics is 
blurry - what's so special about converters that they need their own element?  
Nothing, once you take into account all the other things that end up in the 
<types> element - data-types, tasks, project builders, build listeners, 
aspects, etc.

I'd like to clean this up a little by either:

* Moving all 'type' definitions in the <types> element, so that converters 
would go there, as would any new 'types' that we add later (e.g. services).  If 
we did this we might rename the element <content> or <manifest> or whatever.

* Replacing the <types> element with a top-level element for each role, so we 
would have <data-type>, <task>, <service>, etc elements, with the definitions 
inside.  Something like:

<antlib>

  <task>
    <property classname="..."/>
    <fail classname="..."/>
  </task>

  <type>
    <fileset classname="..."/>
  </type>

  <projectbuilder>
    <ant classname="..."/>
  </projectbuilder>

</antlib>


Adam


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

Reply via email to