You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Peter Donald <do...@mad.scientist.com> on 2000/06/30 05:12:45 UTC

[RFC] AbstractTestlet with extended functionality

Hi,

I have another request that I am not 100% sure about yet but are just
throwing it out for comments. A couple of my tasks are getting rediculously
large - mainly due to huge number of property setters. Also I am getting an
increasing amount of  validation code in execute method. So what I would
like to suggest is some work at delegating more responsibility to
AbstractTestlet classs and less to the other classes in Ant. Essentially
what I would like to see is that the interface for Task be reduced to simply

void execute( TaskContext context )

TaskContext would hold all parameters and also give access to functionality
like path transformation etc.

However as this would brake 100% of current tasks there may be use in
creating an AbstractTasklet that implements some of the missing
functionality. Any of the old tasks can simply inherit from AbstractTasklet
and work as they do now.

The most important things that AbstractTasklet does is implement:

void execute( TaskContext context )

It would implement it in a manner such that it gets all parameters, then
through reflection sets them all in the same way that they are set now. It
would then call init() and execute() of the task. This would mean that all
tasks would work as they do now as long as they inherited from void
AbstractTasklet. However this would allow some tasks to do all sorts of
wierd and wonderful things, including partial automatic validation. This
would greatly reduce the work needed to write a new task and similar
approaches have been taken in other frameworks. Servlets already do this
partially via Generic/HttpServlet and I do it in a few of my own frameworks
(Gamelet,Testlet etc) so it is not too radical. It just makes writing tasks
so much easier :P.

Thoughts ?


Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*

Re: [RFC] AbstractTasklet with extended functionality

Posted by Peter Donald <do...@mad.scientist.com>.
At 05:06  30/6/00 +0200, you wrote:
>>>>>> "PD" == Peter Donald <do...@mad.scientist.com> writes:
>
> >> Maybe I've misunderstood your proposal.
>
> PD> Nope. Your right there.
>
>I was afraid I would be.
>
>For those "other tasks", those not extending AbstractTasklet, would
>you want scripts to be able to work on them - setting/getting
>attributes? Or would you want the user to be aware that there are two
>kinds of tasks, those that you could manipulate and those you could
>not?

Well when we move to deferred tasks (if we do) then there is going to have
to be a rethinking on how scripting interacts with properties etc anyway.
So this point may be moot if we move to proxies. Depends on the
implementation strategy. As for scripts I have specifically created some of
these tasks so that I could do stuff declaratively rather than procedurally
so I am not sure scripting would be appropriate to them - Not sure.
Something to think about anyway.

>if (dir == null) {
>    throw new BuildException("dir attribute must be set on filesets");
>}
>
>in whatever represents filesets.
>
>This is exactly the kind of validation you want to put into
>AbstractTasklet, isn't it?

yep

>I'm not saying that a Validator class of some kind would be useless,
>quite the opposite. But put it to good use for the nested elements as
>well.

oh okay yup. I was thinking you mean all elements including targets etc :P
Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*

Re: [RFC] AbstractTasklet with extended functionality

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "PD" == Peter Donald <do...@mad.scientist.com> writes:

 >> Maybe I've misunderstood your proposal.

 PD> Nope. Your right there.

I was afraid I would be.

For those "other tasks", those not extending AbstractTasklet, would
you want scripts to be able to work on them - setting/getting
attributes? Or would you want the user to be aware that there are two
kinds of tasks, those that you could manipulate and those you could
not?

 >>  One thing you miss here IMHO is that the same problems - setting
 >> of attributes, creation of nested elements, validation of
 >> attributes - holds for all the other objects corresponding to XML
 >> elements in the buildfile as well.

 PD> true :P but the validation I was wanting to use is very very
 PD> specific and not really general like a dtd/schema etc.

Oh, but I'm talking about this simple validation. Let's assume we have
a fileset attribute like the one Arnout has described:

<jar file="jarfile.jar">
  <fileset dir="dir1tojar">
    <include ... />
    ...
  </fileset>
</jar>

Then you will certainly find

if (dir == null) {
    throw new BuildException("dir attribute must be set on filesets");
}

in whatever represents filesets.

This is exactly the kind of validation you want to put into
AbstractTasklet, isn't it?

I'm not saying that a Validator class of some kind would be useless,
quite the opposite. But put it to good use for the nested elements as
well.

Stefan

Re: [RFC] AbstractTasklet with extended functionality

Posted by Peter Donald <do...@mad.scientist.com>.
At 04:16  30/6/00 +0200, you wrote:
> PD> well as I said you can keep the same design contract but now it
> PD> is handled by AbstractTasklet rather than by the parser.
>
>But only for those extending AbstractTasklet. I thought your goal was
>to get tasks without setters by extending your changed Task directly
>and retrieve all the parameters from the TaskContext.

>Maybe I've misunderstood your proposal.

Nope. Your right there. I agree that in most (ie almost all) tasks this
simple behaviour is wanted/desired/acceptable but for some more complex
tasks it quickly becomes unmanageable fast - quite a few of my tasks have
in excess of 9 attributes. I already have to implement mutators, if I want
scripting I also have to implement accesors. Then I have to validate the
attributes and make sure each is correct format/value/has been set etc.
Anything that can reduce the amount of work I have to do to shoehorn my
tasks to the ant way is going to be good :P. What I have proposed keeps
identical functionality as we have now if task inherits from
AbstractTasklet but it is also free to implement it more efficiently if it
wants to.

> >> So a task that wants this validation would initialize
> >> AbstractTasklet with a list of acceptable properties, ...
>
> PD> As I said there is 0 cost if you don't want/need it.
>
>Don't get me wrong, I'm just trying to fully understand what you are
>after.

:P~

> PD> true the functionality can be placed somewhere outside the class
> PD> but the particular rules are associated with the task (and
> PD> therefore I think they should be inside it).
>
>One thing you miss here IMHO is that the same problems - setting of
>attributes, creation of nested elements, validation of attributes -
>holds for all the other objects corresponding to XML elements in the
>buildfile as well. This is not a unique problem of tasks and all the
>other "nested" objects don't share a parent class apart from Object,
>at least I wouldn't want to restrict them to.

>Therefore this functionality - if it can be generalized - should
>better be placed outside of the Task hierarchy IMHO.

true :P but the validation I was wanting to use is very very specific and
not really general like a dtd/schema etc. Validation of other components of
build file may be possible but making the validator that general would
require a lot more work than I was willing to put in :P and it would just
end up creating a dynamic schema-dtd-like thing which I prefer not to go
through :P

Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*

Re: [RFC] AbstractTasklet with extended functionality

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "PD" == Peter Donald <do...@mad.scientist.com> writes:

 PD> well as I said you can keep the same design contract but now it
 PD> is handled by AbstractTasklet rather than by the parser.

But only for those extending AbstractTasklet. I thought your goal was
to get tasks without setters by extending your changed Task directly
and retrieve all the parameters from the TaskContext.

Maybe I've misunderstood your proposal.

 >> So a task that wants this validation would initialize
 >> AbstractTasklet with a list of acceptable properties, ...

 PD> As I said there is 0 cost if you don't want/need it.

Don't get me wrong, I'm just trying to fully understand what you are
after.

 PD> true the functionality can be placed somewhere outside the class
 PD> but the particular rules are associated with the task (and
 PD> therefore I think they should be inside it).

One thing you miss here IMHO is that the same problems - setting of
attributes, creation of nested elements, validation of attributes -
holds for all the other objects corresponding to XML elements in the
buildfile as well. This is not a unique problem of tasks and all the
other "nested" objects don't share a parent class apart from Object,
at least I wouldn't want to restrict them to.

Therefore this functionality - if it can be generalized - should
better be placed outside of the Task hierarchy IMHO.

Stefan

Re: [RFC] AbstractTasklet with extended functionality

Posted by Peter Donald <do...@mad.scientist.com>.
At 01:50  30/6/00 +0200, you wrote:
>>>>>> "PD" == Peter Donald <do...@mad.scientist.com> writes:
>
> PD> At 10:08 30/6/00 +0200, you wrote:
>
> >> I'm very much fond of the way attributes and nested elements are
> >> reflected into tasks. It would probably also break scripting
> >> support.
>
> PD> you want to keep it ? Easy keep it.
>
>No, I want it as the contract of Task - and that I can't keep if we
>switch to your proposed TaskContext. Correct me if I'm wrong.
>
>All attributes that can be set from outside the task (or a nested
>element that gets the same treatment from ProjectHelper BTW) are
>detected by a specific Ant design pattern - which happens to be the
>same as for beans.

well as I said you can keep the same design contract but now it is handled
by AbstractTasklet rather than by the parser. The only difference is where
it is handled - and that handling it via AbstractTasklet allows other
design patterns when they are appropriate.

> PD> It is just that most of my tasks are scattered with things like
>
> PD> if( null == m_someProperty ) { 
> PD>     throw new BuildException("Property 'someProperty' not set");
> PD> }
>
>So a task that wants this validation would initialize AbstractTasklet
>with a list of acceptable properties, a list of required properties, a
>list of properties that are not allowed to be combined, a list ...

As I said there is 0 cost if you don't want/need it. If you don't want/need
it then you don't define the schema and no rules nothing is validated and
your task is processed exactly as it is now.

>I see this - the reoccuring parameter validation blocks - as a problem
>as well, but don't feel that reusing some kind of abstract rule
>validator by inheriting from it is the right way. If you can come up
>with an easy to configure validator, it'd be better used by the task
>than inherited from IMHO.

true the functionality can be placed somewhere outside the class but the
particular rules are associated  with the task (and therefore I think they
should be inside it). The way I do similar things in other like classes is
something like

protected SchemaRule[] getRules() { return null; }

public void execute( TaskContext context )
{
  m_context = context;
  final SchemaRule[] rules = getRules();  
  final Hashtable parameters = context.getParameters();

  if( null != rules ) validateParameters( parameters );
  processParameters( parameters );
  execute();
}

whether the validation occurs inside or outside the class is not important
but what is important is that if you define a schema (via overiding
getRules) then it is automatically applied otherwise it is not.

Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*

Re: [RFC] AbstractTasklet with extended functionality

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "PD" == Peter Donald <do...@mad.scientist.com> writes:

 PD> At 10:08 30/6/00 +0200, you wrote:

 >> I'm very much fond of the way attributes and nested elements are
 >> reflected into tasks. It would probably also break scripting
 >> support.

 PD> you want to keep it ? Easy keep it.

No, I want it as the contract of Task - and that I can't keep if we
switch to your proposed TaskContext. Correct me if I'm wrong.

All attributes that can be set from outside the task (or a nested
element that gets the same treatment from ProjectHelper BTW) are
detected by a specific Ant design pattern - which happens to be the
same as for beans.

The same is true for nested sub elements of tasks (or of sub elements
again), you can identify them because there is an Ant internal design
pattern - method without arguments that returns an object type and
whose name starts with "create".

 PD> It is just that most of my tasks are scattered with things like

 PD> if( null == m_someProperty ) { 
 PD>     throw new BuildException("Property 'someProperty' not set");
 PD> }

So a task that wants this validation would initialize AbstractTasklet
with a list of acceptable properties, a list of required properties, a
list of properties that are not allowed to be combined, a list ...

This might become even more cumbersome if a task inherits from a
subclass of AbstractTasklet.

I see this - the reoccuring parameter validation blocks - as a problem
as well, but don't feel that reusing some kind of abstract rule
validator by inheriting from it is the right way. If you can come up
with an easy to configure validator, it'd be better used by the task
than inherited from IMHO.

Stefan

Re: [RFC] AbstractTasklet with extended functionality

Posted by Peter Donald <do...@mad.scientist.com>.
At 10:08  30/6/00 +0200, you wrote:
>Peter, I'm not sure I've fully understood you intention.
>
>I gather that you want to reduce the Task interface to achieve two
>goals, (1) get rid of the setter methods for attributes and (2) get
>some kind of automatic validation of the attributes.

essentially. Plus it becomes closer to all other similar sub-process apis
as a benefit :P

>For (1) I'm all against it, really. I'm very much fond of the way
>attributes and nested elements are reflected into tasks. It would
>probably also break scripting support.

you want to keep it ? Easy keep it. In 90% of cases you can keep it and
inherit from AbstractTasklet. AbstractTasklet will then perform all the
reflection and setting of properties etc that is currently done in other
classes (currently it is scattered through parser). This will become even
more useful when we move to deferred instantaition of tasks. 

So in effect you can ignore it and as long as you inherit from
AbstractTasklet it will behave exactly as it does now. However in cases
where it is innapropriate then you can overide the behaviour. 

So you have choice how it should behave.

>For (2), I don't get it. How would that work? What kind of validation
>could TaskContext (I assume it should happen there) provide?

The validation is done by the AbstractTasklet and can be done any number of
ways. Mainly it is of the form parameter X is required and parameter Y is
required if parameter Z is set etc. Nothing complicated but extremely
simple syntactical validation. I have something similar that validates cmd
line arguments and is a life saver. But again if you don't want to use it
don't and the Task will behave identically to how it does now.

However if you need to it then it is there. It is just that most of my
tasks are scattered with things like

if( null == m_someProperty )
{
  throw new BuildException("Property 'someProperty' not set");
}

and combine that with the large numbers of mutators (and soon to be
accesors if you need scripting) and you get large amounts of non-dense code
that is really annoying :P


Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*

Re: [RFC] AbstractTestlet with extended functionality

Posted by Stefan Bodewig <bo...@bost.de>.
Peter, I'm not sure I've fully understood you intention.

I gather that you want to reduce the Task interface to achieve two
goals, (1) get rid of the setter methods for attributes and (2) get
some kind of automatic validation of the attributes.

For (1) I'm all against it, really. I'm very much fond of the way
attributes and nested elements are reflected into tasks. It would
probably also break scripting support.

For (2), I don't get it. How would that work? What kind of validation
could TaskContext (I assume it should happen there) provide?

Stefan

Re: [RFC] AbstractTasklet with extended functionality

Posted by Peter Donald <do...@mad.scientist.com>.
Uggggg. I said Testlet in many places where I should of said Tasklet. Fixed
now I hope :P

At 01:12  30/6/00 +1000, you wrote:
>Hi,
>
>I have another request that I am not 100% sure about yet but are just
>throwing it out for comments. A couple of my tasks are getting rediculously
>large - mainly due to huge number of property setters. Also I am getting an
>increasing amount of  validation code in execute method. So what I would
>like to suggest is some work at delegating more responsibility to
>AbstractTasklet class and less to the other classes in Ant. Essentially
>what I would like to see is that the interface for Task be reduced to simply
>
>void execute( TaskContext context )
>
>TaskContext would hold all parameters and also give access to functionality
>like path transformation etc.
>
>However as this would brake 100% of current tasks there may be use in
>creating an AbstractTasklet that implements some of the missing
>functionality. Any of the old tasks can simply inherit from AbstractTasklet
>and work as they do now.
>
>The most important things that AbstractTasklet does is implement:
>
>void execute( TaskContext context )
>
>It would implement it in a manner such that it gets all parameters, then
>through reflection sets them all in the same way that they are set now. It
>would then call init() and execute() of the task. This would mean that all
>tasks would work as they do now as long as they inherited from void
>AbstractTasklet. However this would allow some tasks to do all sorts of
>wierd and wonderful things, including partial automatic validation. This
>would greatly reduce the work needed to write a new task and similar
>approaches have been taken in other frameworks. Servlets already do this
>partially via Generic/HttpServlet and I do it in a few of my own frameworks
>(Gamelet,Testlet etc) so it is not too radical. It just makes writing tasks
>so much easier :P.
>
>Thoughts ?
>
>
>Cheers,
>
>Pete
>
>*------------------------------------------------------*
>| "Nearly all men can stand adversity, but if you want |
>| to test a man's character, give him power."          |
>|       -Abraham Lincoln                               |
>*------------------------------------------------------*
>
Cheers,

Pete

*------------------------------------------------------*
| "Nearly all men can stand adversity, but if you want |
| to test a man's character, give him power."          |
|       -Abraham Lincoln                               |
*------------------------------------------------------*