You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ivy-user@ant.apache.org by Xavier Hanin <xa...@gmail.com> on 2007/05/10 09:12:51 UTC

Re: "ant call trigger can only be used from an ant build" from ant build

On 5/9/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Hi All,
>
> I'm struggling with ivy 2.0.0-alpha-1 and ant (1.6.5/1.7.0) over Java
> 1.5.0_10/_11 and have run out of ideas for now. Hope someone might help
> with this.
>
> The scenario:
>
> I wanted to make a simple build system with ant/ivy. For that i used
> triggers on pre-resolve-dependency (ant-call). A trigger checks if given
> module is available (ivy:findrevision) and if not it calls a build on
> appropriate project (I know it is not a perfect solution - just
> started). Of course those sub-projects are also ivy-configured and use
> the same mechanism.
>
> I have tried running this scenario with the same project state (clearly
> checked out of SVN) and the results were something like that:
> machine | ant version | ant options | result - first run | second run
> A       | 1.6.5       |             | FAILURE            | SUCCESS
> A       | 1.6.5       | -verbose    | FAILURE            | SUCCESS
> A       | 1.6.5       | -debug      | SUCCESS            |
> B       | 1.6.5       |             | FAILURE            | SUCCESS
> B       | 1.7.0       |             | FAILURE (50%)      | SUCCESS
> B       | 1.6.5       | -verbose    | SUCCESS            |
> B       | 1.6.5       | -debug      | SUCCESS            |
>
> All failures are caused by ivy:resolve failing to find matching
> dependencies in internal projects. I have tried to debug this with ivy
> source - but then the scenario always succeeds.
> I've found following information in the ant logs for the failed
> scenarios:
>
> [ivy:resolve] ant call trigger can only be used from an ant build.
> Ignoring.
>
> And this is strange.
> From the source of ivy the ant project context is taken from ivy
> context. IvyContext is taken from ThreadLocal variable initialized on
> the first call to it or on demand.
>
> From the situation I guess that IvyContext is not initialized while the
> trigger should be called. This might mean that one of the sub calls are
> threaded by ant (antcall/ant/macro ?) for some reason and IvyContext for
> that thread has of course no context set - and therefore no ant project
> is available for ivy:resolve.
> But this is only a loose guess.
>
> Any ideas on how to solve this ?


Well, I think we'd need more information about your build itself. As you
have noticed, the context is attached to a thread local, but ant doesn't
create threads that often. So maybe this is due to the way you call Ivy (and
this is a bug in any case, but I'm just trying to narrow the problem).

For the while I have a "workaround"
> based on a handcrafted version of ivy compiled by hand that behaves
> correctly in all situations (I don't know why).


What did you change in your own ivy version?

And more general - maybe a ThreadLocal is not a good place for keeping
> IvyContext in ant environment ? Any thread created by ant is out of the
> scope of IvyContext at once (or am I wrong ?).


We have two kind of context in Ivy:
- ant based context, stored as ant references, which is used as context
between several ant tasks
- thread based context, which is used during a single call to one ivy
operation, to avoid passing some information all along all methods
We are suppose to be somewhat in control of threads created during an Ivy
operation... except when we call a plugin. We should document somewhere to
reattach the ivy context when creating a thread in an Ivy plugin, IF you
want this thread to be attached witht the current Ivy context, which is not
necessarily the case. In your case I think the problem happens before the
ant call in the trigger, so it seems we have a problem of context attachment
in Ivy itself.

BTW, did you try with Ivy 1.4.1? We have done quite a lot of refactoring in
Ivy 2.0, and it would help to know if it was working before or not.

Xavier

Best Regards.
>
> --jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Hello,
>
> Unfortunately I made a mistake in a patch-2. Didn't double check it
> against my full build and
> introduced a bug.
>
> In IvyContext.pop(String,Object) I've put checking on the expectedValue
> too early. A patch on the patch is in attachment IVY-497-3.


I've applied it, you can use the trunk version now.

I hope there are no more errors in that - but will be testing it
> extensively in the next days.


Great, keep us informed if you have further problems. Thanks a lot for your
contribution.

Xavier

Best Regards.
>
> --jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Jarosław Wypychowski <J....@icm.edu.pl>.
Hello,

Unfortunately I made a mistake in a patch-2. Didn't double check it against my full build and 
introduced a bug.

In IvyContext.pop(String,Object) I've put checking on the expectedValue
too early. A patch on the patch is in attachment IVY-497-3.

I hope there are no more errors in that - but will be testing it
extensively in the next days.

Best Regards.

--jw

-- 
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
jarwyp@icm.edu.pl

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Dnia 10-05-2007, czw o godzinie 16:24 +0200, Xavier Hanin napisał(a):
> > On 5/10/07, Gilles Scokart <gs...@gmail.com> wrote:
> > >
> > > Personally I prefer the abstract doExecute and the final execute
> because
> > > it
> > > make it clear which code is executed before and after the task.  I
> fear
> > > that
> > > an event handler registered to the project will not be so clear.
> >
> >
> > I agree it is more clear, but I was looking for some kind of life cycle
> > already handled by Ant, and found only these events. But maybe using our
> own
> > life cycle of execute makes more sense.
> >
> > Any other opinion?
> I think that You are talking about BuildListener. I don't like the idea
> of controlling the reference stack with generic listeners. First - do
> they control only subclasses of IvyTask ?
>
> I would suggest that we make a different thing:
> IvyTask{
>         final execute(){
>                 try{
>                         prepareTask();
>                         doExecute();
>                 } finally {
>                         finalizeTask();
>                 }
>         }
>         public void prepareTask(){
>                 stackAdd
>         }
>         public void finalizeTask(){
>                 stackRemove
>         }
> }
>
> Then it would be clear that if you want to take advantage of default Ivy
> mechanisms you have to follow the 3 step task management.
>
> As for top against peek - I didn't thought of Stack interface - feel
> free to correct that. I can modify the sources according to the above
> and change top into peek.


+1 :-)

Xavier

--jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Jarosław Wypychowski <J....@icm.edu.pl>.
Dnia 10-05-2007, czw o godzinie 16:24 +0200, Xavier Hanin napisał(a):
> On 5/10/07, Gilles Scokart <gs...@gmail.com> wrote:
> >
> > Personally I prefer the abstract doExecute and the final execute because
> > it
> > make it clear which code is executed before and after the task.  I fear
> > that
> > an event handler registered to the project will not be so clear.
> 
> 
> I agree it is more clear, but I was looking for some kind of life cycle
> already handled by Ant, and found only these events. But maybe using our own
> life cycle of execute makes more sense.
> 
> Any other opinion?
I think that You are talking about BuildListener. I don't like the idea
of controlling the reference stack with generic listeners. First - do
they control only subclasses of IvyTask ? 

I would suggest that we make a different thing:
IvyTask{
	final execute(){
		try{
			prepareTask();
			doExecute();
		} finally {
			finalizeTask();
		}
	}
	public void prepareTask(){
		stackAdd
	}
	public void finalizeTask(){
		stackRemove
	}
}
		
Then it would be clear that if you want to take advantage of default Ivy
mechanisms you have to follow the 3 step task management. 

As for top against peek - I didn't thought of Stack interface - feel
free to correct that. I can modify the sources according to the above
and change top into peek.

--jw

-- 
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
jarwyp@icm.edu.pl

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Gilles Scokart <gs...@gmail.com> wrote:
>
> Personally I prefer the abstract doExecute and the final execute because
> it
> make it clear which code is executed before and after the task.  I fear
> that
> an event handler registered to the project will not be so clear.


I agree it is more clear, but I was looking for some kind of life cycle
already handled by Ant, and found only these events. But maybe using our own
life cycle of execute makes more sense.

Any other opinion?

Xavier

Gilles
>
> > -----Original Message-----
> > From: Xavier Hanin [mailto:xavier.hanin@gmail.com]
> > Sent: jeudi 10 mai 2007 15:23
> > To: ivy-user@incubator.apache.org; J.Wypychowski@icm.edu.pl
> > Subject: Re: "ant call trigger can only be used from an ant build" from
> > ant build
> >
> > On 5/10/07, Xavier Hanin <xa...@gmail.com> wrote:
> > >
> > > There is however a slight problem - this makes the API incompatible
> with
> > > > 2.0.0-alpha-1. It is possible to make doExecute not abstract in
> > IvyTask
> > > > and therefore validate all the other tasks that are kept by people,
> > but
> > > > this can lead to hard to find errors.
> > >
> > >
> > > breaking the API is not a major problem, Ivy 2.0 is already breaking a
> > lot
> > > of API, and we named our last release alpha because it is still
> subject
> > to
> > > API break (I tihnk we warn users against that in the release notes).
> So
> > I
> > > prefer having things like this, we may even declare execute final to
> > make
> > > sure it isn't overridden improperly. I'll review your patch soon and
> > apply
> > > it.
> > >
> >
> > I may have found another way of doing things before and after the task
> is
> > executed without breaking the API and the conventions when writing ant
> > task.
> > Indeed Ant fire events before starting a task and after finishing it
> (see
> > the perform method). So we may register as a listener of the project in
> > the
> > init method of IvyTask, then push on task started and pop on task
> > finished.
> > Each task would be responsible for its own events only.
> > The drawback of this approach is that if someone calls execute directly
> (a
> > public method) instead of perform, we won't get the correct context.
> This
> > is
> > not what programs are supposed to do, so I don't know if it's really a
> > problem or not (I realize I usually call execute instead of perform,
> which
> > is not a good thing :-( ).
> >
> > So, what do you think?
> >
> > Xavier
> >
> > Xavier
> > >
> > > Best Regards.
> > > >
> > > > --jw
> > > >
> > > > --
> > > > Jaroslaw Wypychowski
> > > > Interdyscyplinarne Centrum Modelowania Matematycznego i
> Komputerowego
> > UW
> > > >
> > > > jarwyp@icm.edu.pl
> > > >
> > > >
> > >
> > >
> > > --
> > > Xavier Hanin - Independent Java Consultant
> > > Manage your dependencies with Ivy!
> > > http://incubator.apache.org/ivy/
> > >
> >
> >
> >
> > --
> > Xavier Hanin - Independent Java Consultant
> > Manage your dependencies with Ivy!
> > http://incubator.apache.org/ivy/
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

RE: "ant call trigger can only be used from an ant build" from ant build

Posted by Gilles Scokart <gs...@gmail.com>.
Personally I prefer the abstract doExecute and the final execute because it
make it clear which code is executed before and after the task.  I fear that
an event handler registered to the project will not be so clear.



Gilles

> -----Original Message-----
> From: Xavier Hanin [mailto:xavier.hanin@gmail.com]
> Sent: jeudi 10 mai 2007 15:23
> To: ivy-user@incubator.apache.org; J.Wypychowski@icm.edu.pl
> Subject: Re: "ant call trigger can only be used from an ant build" from
> ant build
> 
> On 5/10/07, Xavier Hanin <xa...@gmail.com> wrote:
> >
> > There is however a slight problem - this makes the API incompatible with
> > > 2.0.0-alpha-1. It is possible to make doExecute not abstract in
> IvyTask
> > > and therefore validate all the other tasks that are kept by people,
> but
> > > this can lead to hard to find errors.
> >
> >
> > breaking the API is not a major problem, Ivy 2.0 is already breaking a
> lot
> > of API, and we named our last release alpha because it is still subject
> to
> > API break (I tihnk we warn users against that in the release notes). So
> I
> > prefer having things like this, we may even declare execute final to
> make
> > sure it isn't overridden improperly. I'll review your patch soon and
> apply
> > it.
> >
> 
> I may have found another way of doing things before and after the task is
> executed without breaking the API and the conventions when writing ant
> task.
> Indeed Ant fire events before starting a task and after finishing it (see
> the perform method). So we may register as a listener of the project in
> the
> init method of IvyTask, then push on task started and pop on task
> finished.
> Each task would be responsible for its own events only.
> The drawback of this approach is that if someone calls execute directly (a
> public method) instead of perform, we won't get the correct context. This
> is
> not what programs are supposed to do, so I don't know if it's really a
> problem or not (I realize I usually call execute instead of perform, which
> is not a good thing :-( ).
> 
> So, what do you think?
> 
> Xavier
> 
> Xavier
> >
> > Best Regards.
> > >
> > > --jw
> > >
> > > --
> > > Jaroslaw Wypychowski
> > > Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego
> UW
> > >
> > > jarwyp@icm.edu.pl
> > >
> > >
> >
> >
> > --
> > Xavier Hanin - Independent Java Consultant
> > Manage your dependencies with Ivy!
> > http://incubator.apache.org/ivy/
> >
> 
> 
> 
> --
> Xavier Hanin - Independent Java Consultant
> Manage your dependencies with Ivy!
> http://incubator.apache.org/ivy/


Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Xavier Hanin <xa...@gmail.com> wrote:
>
> There is however a slight problem - this makes the API incompatible with
> > 2.0.0-alpha-1. It is possible to make doExecute not abstract in IvyTask
> > and therefore validate all the other tasks that are kept by people, but
> > this can lead to hard to find errors.
>
>
> breaking the API is not a major problem, Ivy 2.0 is already breaking a lot
> of API, and we named our last release alpha because it is still subject to
> API break (I tihnk we warn users against that in the release notes). So I
> prefer having things like this, we may even declare execute final to make
> sure it isn't overridden improperly. I'll review your patch soon and apply
> it.
>

I may have found another way of doing things before and after the task is
executed without breaking the API and the conventions when writing ant task.
Indeed Ant fire events before starting a task and after finishing it (see
the perform method). So we may register as a listener of the project in the
init method of IvyTask, then push on task started and pop on task finished.
Each task would be responsible for its own events only.
The drawback of this approach is that if someone calls execute directly (a
public method) instead of perform, we won't get the correct context. This is
not what programs are supposed to do, so I don't know if it's really a
problem or not (I realize I usually call execute instead of perform, which
is not a good thing :-( ).

So, what do you think?

Xavier

Xavier
>
> Best Regards.
> >
> > --jw
> >
> > --
> > Jaroslaw Wypychowski
> > Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> >
> > jarwyp@icm.edu.pl
> >
> >
>
>
> --
> Xavier Hanin - Independent Java Consultant
> Manage your dependencies with Ivy!
> http://incubator.apache.org/ivy/
>



-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Hello again.
>
> As You suggested this is now in JIRA (IVY-497)
>
> > Well, the problem of your solution is that it makes IvyContext depend on
> an
> > Ant class, which we have to avoid to keep Ivy core independent of Ant.
> Sure - it was a proof of my concept
>
> > So I see two possible solutions:
> > * keep IvyContext as is, and set ANT_PROJECT_CONTEXT_KEY to a Stack
> instead
> > of a Project. In this case all classes dealing with
> ANT_PROJECT_CONTEXT_KEY
> > will have to be aware it's a Stack. Maybe adding a static method like
> > getCurrentProject() in IvyTask could centralize all the management of
> this
> > Stack.
> > * add methods to manage a Stack in IvyContext, because other classes may
> > have to deal with the same kind of problem. We could add a push, pop and
> > peek method, and use these methods instead of set and get from IvyTask,
> > AntCallTrigger and AntBuildTrigger.
> > Centralizing the management in IvyTask can make sense in either case. I
> have
> > a slight preference for the second one for its reusability, but it's
> only a
> > slight preference.
> I liked the second one better as well.
>
> Added
> void IvyContext.push(String,Object)
> Object IvyContext.pop(String)
> Object IvyContext.top(String)


Any reason why you chose top instead of peek (which is the name used in
java.util.Stack, and is thus pretty well known)?

they are kept without weakrefs.


Indeed, I think when you use a stack you are responsible for calling pop as
many times as push.

void IvyTask.execute() throws BuildException
> abstract void IvyTask.doExecute() throws BuildException.
>
> tasks and triggers fixed accordingly.
>
> > using regular svn diff is appropriate. Please create a JIRA issue for
> > attaching the patch, it's better to track the problem and to clear legal
> > issues while applying your patch (you have a box to check when attaching
> the
> > patch to allow us to apply it).
> Attached already. All rights granted. Review it whenever You like. The
> patch is done
> against latest trunk.


Great, thanks a lot!

Did not add additional JUnit test for it but it works in my environment
> and all current tests are passed.
>
> There is however a slight problem - this makes the API incompatible with
> 2.0.0-alpha-1. It is possible to make doExecute not abstract in IvyTask
> and therefore validate all the other tasks that are kept by people, but
> this can lead to hard to find errors.


breaking the API is not a major problem, Ivy 2.0 is already breaking a lot
of API, and we named our last release alpha because it is still subject to
API break (I tihnk we warn users against that in the release notes). So I
prefer having things like this, we may even declare execute final to make
sure it isn't overridden improperly. I'll review your patch soon and apply
it.

Xavier

Best Regards.
>
> --jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Jarosław Wypychowski <J....@icm.edu.pl>.
Hello again.

As You suggested this is now in JIRA (IVY-497)

> Well, the problem of your solution is that it makes IvyContext depend on an
> Ant class, which we have to avoid to keep Ivy core independent of Ant.
Sure - it was a proof of my concept

> So I see two possible solutions:
> * keep IvyContext as is, and set ANT_PROJECT_CONTEXT_KEY to a Stack instead
> of a Project. In this case all classes dealing with ANT_PROJECT_CONTEXT_KEY
> will have to be aware it's a Stack. Maybe adding a static method like
> getCurrentProject() in IvyTask could centralize all the management of this
> Stack.
> * add methods to manage a Stack in IvyContext, because other classes may
> have to deal with the same kind of problem. We could add a push, pop and
> peek method, and use these methods instead of set and get from IvyTask,
> AntCallTrigger and AntBuildTrigger.
> Centralizing the management in IvyTask can make sense in either case. I have
> a slight preference for the second one for its reusability, but it's only a
> slight preference.
I liked the second one better as well.

Added 
void IvyContext.push(String,Object)
Object IvyContext.pop(String)
Object IvyContext.top(String)
they are kept without weakrefs.

void IvyTask.execute() throws BuildException
abstract void IvyTask.doExecute() throws BuildException.

tasks and triggers fixed accordingly.

> using regular svn diff is appropriate. Please create a JIRA issue for
> attaching the patch, it's better to track the problem and to clear legal
> issues while applying your patch (you have a box to check when attaching the
> patch to allow us to apply it).
Attached already. All rights granted. Review it whenever You like. The patch is done 
against latest trunk. 

Did not add additional JUnit test for it but it works in my environment
and all current tests are passed.

There is however a slight problem - this makes the API incompatible with
2.0.0-alpha-1. It is possible to make doExecute not abstract in IvyTask
and therefore validate all the other tasks that are kept by people, but
this can lead to hard to find errors.

Best Regards.

--jw

-- 
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
jarwyp@icm.edu.pl

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Fixed.
>
> I did found the source of problem - and the solution.
>
> The problem is in fact architectural.
>
> In my scenario there is a chain of events:
>
> ant->ivy:resolve->ant-call-trigger->ant->ivy:resolve->ant-call-trigger->ant->...
>
> The whole process is in a single Thread.
> so when we are in first ant-call - we override the parent Project
> settings. When we are in second - we override the parent Project. Ant
> build call creates a new project internally in execute of <ant/> task.
> So in the original scenario it would fail if the task already finished
> and GC cleaned the project. So the comment in my proposal was cleanly
> accidental in its help.
> Unfortunately going from WeakRef to direct save will not help either -
> as we will again override parent's project. There needs to be a complete
> change in the way the Project is kept within context.



You might not like my solution - so please tell me how it should look
> like to fit Your design.
>
> I've added specialized methods into the IvyContext:
>         public void setAntProject(Project project){
>                 List l=(List)_contextMap.get(
> IvyTask.ANT_PROJECT_CONTEXT_KEY);
>                 if(l==null){
>                         l=new ArrayList();
>                         _contextMap.put(IvyTask.ANT_PROJECT_CONTEXT_KEY,
> l);
>                 }
>                 l.add(0,project);
>         }
>
>         public void unsetAntProject(Project project){
>                 List l=(List)_contextMap.get(
> IvyTask.ANT_PROJECT_CONTEXT_KEY);
>                 if(l==null){
>                         return;
>                 }
>                 l.remove(project);
>         }
>
>         public void unsetAntProject(){
>                 List l=(List)_contextMap.get(
> IvyTask.ANT_PROJECT_CONTEXT_KEY);
>                 if(l==null){
>                         return;
>                 }
>                 l.remove(0);
>         }
>
>         public Project getAntProject(){
>                 List l=(List)_contextMap.get(
> IvyTask.ANT_PROJECT_CONTEXT_KEY);
>                 if(l==null || l.size()==0){
>                         return null;
>                 }
>                 return (Project)l.get(0);
>         }
>
>
> And modified get(String) into:
>
>         public Object get(String key) {
>                 if(IvyTask.ANT_PROJECT_CONTEXT_KEY.equals(key)) return
> getAntProject();
>                 if(_contextMap.get(key) instanceof WeakReference){
>                         WeakReference ref = (WeakReference)
> _contextMap.get(key);
>                         return ref == null ? null : ref.get();
>                 } else {
>                         return _contextMap.get(key);
>                 }
>         }
>
> Next I added doExecute as You suggested and made it stack a project on
> and off in the IvyTask.execute():
>     public void execute() throws BuildException {
>         IvyContext.getContext().setAntProject(getProject());
>         doExecute();
>         IvyContext.getContext().unsetAntProject(getProject());
>     }
>
>
> Now Projects are stacked during the execution of IvyTasks in single
> thread and removed when not needed anymore. Now all my tasks are going
> without errors.

Personally I don't really like the solution above (it mixes IvyTask with
> IvyContext) - so please suggest a better way.


Well, the problem of your solution is that it makes IvyContext depend on an
Ant class, which we have to avoid to keep Ivy core independent of Ant.

So I see two possible solutions:
* keep IvyContext as is, and set ANT_PROJECT_CONTEXT_KEY to a Stack instead
of a Project. In this case all classes dealing with ANT_PROJECT_CONTEXT_KEY
will have to be aware it's a Stack. Maybe adding a static method like
getCurrentProject() in IvyTask could centralize all the management of this
Stack.
* add methods to manage a Stack in IvyContext, because other classes may
have to deal with the same kind of problem. We could add a push, pop and
peek method, and use these methods instead of set and get from IvyTask,
AntCallTrigger and AntBuildTrigger.
Centralizing the management in IvyTask can make sense in either case. I have
a slight preference for the second one for its reusability, but it's only a
slight preference.

And If You would like me to finish the patch - what format of the patch
> would you like ? (diff params ?)


using regular svn diff is appropriate. Please create a JIRA issue for
attaching the patch, it's better to track the problem and to clear legal
issues while applying your patch (you have a box to check when attaching the
patch to allow us to apply it).

Thanks for your contribution!

Xavier


Best Regards
>
> --jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Jarosław Wypychowski <J....@icm.edu.pl>.
Fixed.

I did found the source of problem - and the solution.

The problem is in fact architectural. 

In my scenario there is a chain of events:
ant->ivy:resolve->ant-call-trigger->ant->ivy:resolve->ant-call-trigger->ant->...

The whole process is in a single Thread. 
so when we are in first ant-call - we override the parent Project
settings. When we are in second - we override the parent Project. Ant
build call creates a new project internally in execute of <ant/> task.
So in the original scenario it would fail if the task already finished
and GC cleaned the project. So the comment in my proposal was cleanly
accidental in its help. 
Unfortunately going from WeakRef to direct save will not help either -
as we will again override parent's project. There needs to be a complete
change in the way the Project is kept within context.

You might not like my solution - so please tell me how it should look
like to fit Your design.

I've added specialized methods into the IvyContext:
	public void setAntProject(Project project){
		List l=(List)_contextMap.get(IvyTask.ANT_PROJECT_CONTEXT_KEY);
		if(l==null){
			l=new ArrayList();
			_contextMap.put(IvyTask.ANT_PROJECT_CONTEXT_KEY, l);
		}
		l.add(0,project);
	}
	
	public void unsetAntProject(Project project){
		List l=(List)_contextMap.get(IvyTask.ANT_PROJECT_CONTEXT_KEY);
		if(l==null){
			return;
		}
		l.remove(project);
	}

	public void unsetAntProject(){
		List l=(List)_contextMap.get(IvyTask.ANT_PROJECT_CONTEXT_KEY);
		if(l==null){
			return;
		}
		l.remove(0);
	}
	
	public Project getAntProject(){
		List l=(List)_contextMap.get(IvyTask.ANT_PROJECT_CONTEXT_KEY);
		if(l==null || l.size()==0){
			return null;
		}
		return (Project)l.get(0);
	}


And modified get(String) into:

	public Object get(String key) {
		if(IvyTask.ANT_PROJECT_CONTEXT_KEY.equals(key)) return
getAntProject();
		if(_contextMap.get(key) instanceof WeakReference){
			WeakReference ref = (WeakReference) _contextMap.get(key);
			return ref == null ? null : ref.get();
		} else {
			return _contextMap.get(key);
		}
	}

Next I added doExecute as You suggested and made it stack a project on
and off in the IvyTask.execute():
    public void execute() throws BuildException {
    	IvyContext.getContext().setAntProject(getProject());
    	doExecute();
    	IvyContext.getContext().unsetAntProject(getProject());
    }


Now Projects are stacked during the execution of IvyTasks in single
thread and removed when not needed anymore. Now all my tasks are going
without errors.

Personally I don't really like the solution above (it mixes IvyTask with
IvyContext) - so please suggest a better way. 
And If You would like me to finish the patch - what format of the patch
would you like ? (diff params ?)

Best Regards

--jw

-- 
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
jarwyp@icm.edu.pl

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Xavier Hanin <xa...@gmail.com>.
On 5/10/07, Jarosław Wypychowski <J....@icm.edu.pl> wrote:
>
> Hello,
>
> Thanks for quick reply.
>
> Dnia 10-05-2007, czw o godzinie 09:12 +0200, Xavier Hanin napisał(a):
> > Well, I think we'd need more information about your build itself. As you
> > have noticed, the context is attached to a thread local, but ant doesn't
> > create threads that often. So maybe this is due to the way you call Ivy
> (and
> > this is a bug in any case, but I'm just trying to narrow the problem).
>
> I did some more research (dumping Thread.currentThread(),
> IvyContext.getContext() and IvyContext.getContext().get(IvyTask.ANT...)
> at miscellaneous places and narrowed it to the WeakReference keeping the
> Project in the IvyContext._contextMap. As for Threads - all was going on
> in a single thread.


OK, so not a Thread but a WeakReference problem. Interesting. And that's why
the problem is occuring in an undeterministic way, because it's related to
when the GC is called.

IvyContext{
> ...
> public Object get(String key) {
>         WeakReference ref = (WeakReference) _contextMap.get(key);
> //      System.out.println("ICTX GET "+key+" | "+ref
> +"|"+Thread.currentThread()+"|"+this);
>         return ref == null ? null : ref.get();
> }
> ...
> }
> With comment turned off the WeakReference is dead sometimes (though it
> shouldn't be as the Ant Project for sure is still accessible by the main
> Ant process).

Indeed, this is really weird, since we do not leave the ant build.

With comment turned on the WeakReference is alive when it
> is expected to be alive and everything passes smoothly.
> Funny thing is that adding a comment in the getContext() new context
> creation block also helps.


Yes, this is strange too, but it might be side effect on the GC only, GC
calls are not predictable, it may happen that it just change the memory
consumption.

I'm not sure whether this is a problem with jvm or something else. The
> WeakReference seems like a good idea to me for keeping Project, though
> it might be stored directly with
>
> Ivy*(IvyTask){
> ...
>   execute(){
>         setProjectInContext
>         realwork
>         unsetProjectInContext
>   }
> ...
> }
> Unless there are things in the background of Ivy that last past the
> execute task and we need it to be Ant project aware.


No, nothing like that. For the ant project we can do something like this,
it's pretty easy because we are in control of all Ivy tasks, and clearly
know all entry points. We could do that by refactoring ivy tasks like that:

IvyTask {
execute() {
        setProjectInContext
        doExecute();
        unsetProjectInContext
  }
abstract doExecute();
}

then in all Ivy tasks we can rename execute to doExecute, when we're done.

The problem is that it will be very difficult to add a unit test for this
bug, since we do not really understand why the reference is lost. But at
least you are able to reproduce the problem, so maybe you would be the best
person to implement this fix, test it and submit a patch? :-)

Xavier

> What did you change in your own ivy version?
> Added a random comment. But now it is more predictable.
>
> > BTW, did you try with Ivy 1.4.1? We have done quite a lot of refactoring
> in
> > Ivy 2.0, and it would help to know if it was working before or not.
> No - and as for now it seems to me like no Ivy problem.
>
>
> As for my build:
> structure of the project:
> lib/
>         #static repository in the SVN
> build/
>         #local ivy cache
>         #temporary repo for integration things
> yadda-common/trunk/
>         # subproject with no internal deps
> yadda-services/trunk/
>         # subproject with yadda-commmon as internal dep
> DeskLight/trunk
>         #project with yadda-services as internal dep.
>
> ivysettings:
> <ivysettings>
> <!--  <properties file="build.properties"/>-->
>   <settings defaultResolver="yadda" defaultCache="${ivy.cache.dir}"/>
>   <triggers>
>     <ant-call target="trigger" event="pre-resolve-dependency"
> prefix="event."/>
>   </triggers>
>   <resolvers>
>     <chain name="yadda">
>       <filesystem name="local">
>          <ivy
> pattern="${ivy.repo.dir
> }/[organisation]/[module]/ivys/ivy-[revision].xml"/>
>          <artifact
> pattern="${ivy.repo.dir
> }/[organisation]/[module]/[type]s/[artifact]-[revision].[type]"/>
>       </filesystem>
>       <filesystem name="libraries">
>         <artifact
> pattern="${yadda.lib.repo}/bin/[artifact]-[revision].[ext]" />
>       </filesystem>
>     </chain>
>   </resolvers>
> </ivysettings>
>
> target trigger in both DeskLight and yadda-services:
> <target name="trigger" depends="init">
>   <var name="ivy.revision" unset="true"/>
>   <var name="revision" unset="true"/>
>   <ivy:findrevision organisation="${event.organisation}"
> module="${event.module}" revision="${event.revision}"
> property="revision"/>
>   <if>
>     <not><isset property="revision"/></not>
>     <then>
>         <echo message="BUILDING"/>
>         <delete>
>           <fileset dir="../lib">
>              <include name="${module}-*"/>
>           </fileset>
>         </delete>
>         <ant dir="${root.dir}/${event.module}/trunk/build/"
> antfile="build.xml"  target="${event.module}.publish"
> inheritall="false">
>            <property name="mode" value="local"></property>
>          </ant>
>      </then>
>      <else>
>        <echo message="found revision for ${event.module} :
> ${revision}"/>
>      </else>
>    </if>
> </target>
>
> and the publication task depends on standard resolve,retrieve - and
> therefore is recursive from the point of view of build.
>
> Best Regards.
>
> --jw
>
> --
> Jaroslaw Wypychowski
> Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
> jarwyp@icm.edu.pl
>
>


-- 
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Re: "ant call trigger can only be used from an ant build" from ant build

Posted by Jarosław Wypychowski <J....@icm.edu.pl>.
Hello,

Thanks for quick reply.

Dnia 10-05-2007, czw o godzinie 09:12 +0200, Xavier Hanin napisał(a):
> Well, I think we'd need more information about your build itself. As you
> have noticed, the context is attached to a thread local, but ant doesn't
> create threads that often. So maybe this is due to the way you call Ivy (and
> this is a bug in any case, but I'm just trying to narrow the problem).

I did some more research (dumping Thread.currentThread(),
IvyContext.getContext() and IvyContext.getContext().get(IvyTask.ANT...)
at miscellaneous places and narrowed it to the WeakReference keeping the
Project in the IvyContext._contextMap. As for Threads - all was going on
in a single thread.
IvyContext{
...
public Object get(String key) {
	WeakReference ref = (WeakReference) _contextMap.get(key);
//	System.out.println("ICTX GET "+key+" | "+ref
+"|"+Thread.currentThread()+"|"+this);
	return ref == null ? null : ref.get();
}
...
}
With comment turned off the WeakReference is dead sometimes (though it
shouldn't be as the Ant Project for sure is still accessible by the main
Ant process). With comment turned on the WeakReference is alive when it
is expected to be alive and everything passes smoothly. 
Funny thing is that adding a comment in the getContext() new context
creation block also helps.

I'm not sure whether this is a problem with jvm or something else. The
WeakReference seems like a good idea to me for keeping Project, though
it might be stored directly with 

Ivy*(IvyTask){
...
  execute(){
	setProjectInContext
	realwork
	unsetProjectInContext
  }
...
}
Unless there are things in the background of Ivy that last past the
execute task and we need it to be Ant project aware.

> What did you change in your own ivy version?
Added a random comment. But now it is more predictable.

> BTW, did you try with Ivy 1.4.1? We have done quite a lot of refactoring in
> Ivy 2.0, and it would help to know if it was working before or not.
No - and as for now it seems to me like no Ivy problem.


As for my build:
structure of the project:
lib/
	#static repository in the SVN
build/
	#local ivy cache
	#temporary repo for integration things
yadda-common/trunk/
	# subproject with no internal deps
yadda-services/trunk/
	# subproject with yadda-commmon as internal dep
DeskLight/trunk
	#project with yadda-services as internal dep.

ivysettings:
<ivysettings>
<!--  <properties file="build.properties"/>-->
  <settings defaultResolver="yadda" defaultCache="${ivy.cache.dir}"/>
  <triggers>
    <ant-call target="trigger" event="pre-resolve-dependency"
prefix="event."/>
  </triggers>
  <resolvers>
    <chain name="yadda">
      <filesystem name="local">
         <ivy
pattern="${ivy.repo.dir}/[organisation]/[module]/ivys/ivy-[revision].xml"/>
         <artifact
pattern="${ivy.repo.dir}/[organisation]/[module]/[type]s/[artifact]-[revision].[type]"/>
      </filesystem>
      <filesystem name="libraries">
        <artifact
pattern="${yadda.lib.repo}/bin/[artifact]-[revision].[ext]" />
      </filesystem>
    </chain>
  </resolvers>
</ivysettings>

target trigger in both DeskLight and yadda-services:
<target name="trigger" depends="init">
  <var name="ivy.revision" unset="true"/>
  <var name="revision" unset="true"/>
  <ivy:findrevision organisation="${event.organisation}"
module="${event.module}" revision="${event.revision}"
property="revision"/>
  <if>
    <not><isset property="revision"/></not>
    <then>
        <echo message="BUILDING"/>
        <delete>
          <fileset dir="../lib">
             <include name="${module}-*"/>
          </fileset>
        </delete>
        <ant dir="${root.dir}/${event.module}/trunk/build/"
antfile="build.xml"  target="${event.module}.publish"
inheritall="false">
           <property name="mode" value="local"></property>
         </ant>
     </then>
     <else>
       <echo message="found revision for ${event.module} :
${revision}"/>
     </else>
   </if>
</target>

and the publication task depends on standard resolve,retrieve - and
therefore is recursive from the point of view of build.

Best Regards.

--jw

-- 
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
jarwyp@icm.edu.pl