You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Kevin Jackson <fo...@gmail.com> on 2007/06/07 08:15:55 UTC

Classloader problems

Hi all,

For obscure reasons, I have to redefine the core email task using a taskdef.
This is my build file:
<path id="jsch.path">
  <pathelement location="${src.tools.dir}/jsch/ant-jsch.jar"/>
  <pathelement location="${src.tools.dir}/jsch/jsch-0.1.33.jar"/>
</path>
<taskdef name="scp"
		classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
		classpathref="jsch.path"/>

<taskdef name="sshexec"
classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec"
classpathref="jsch.path"/>
 		
<taskdef name="mail"
		classname="org.apache.tools.ant.taskdefs.email.EmailTask">
	<classpath>
	  <pathelement location="${src.tools.dir}/mail/ant-javamail.jar"/>
	  <pathelement location="${src.tools.dir}/mail/mail.jar"/>
	</classpath>
</taskdef>

Now the strange thing is that thescp & sshexec tasks report that they
have been over-ridden by the new definitions, and with -debug enabled
I can see the correct classes being loaded.  The mail task however
just reports ' Class org.apache.tools.ant.taskdefs.email.EmailTask
loaded from parent loader (parentFirst)'.

Then finally it fails with ClassNotFoundException.  This means that
the <classpath> is ignored for the mail taskkdef, but is used
correctly for the scp/sshexec taskdefs.

I would think it would make sense to treat all taskdefs & classpaths equal...

I cannot copy the jars into ~/.ant/lib, or $ANT_HOME/lib, and I cannot
rely on a CLASSPATH variable or an external calling script.  The only
way I can make what I want to do work is via the taskdefs which honour
the <classpath> or classpathref.  Does anyone know how to work around
this?

Thanks,
Kev

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


Re: Classloader problems

Posted by Kevin Jackson <fo...@gmail.com>.
Hi,
> Initially I was thinking of using a separate classloader for
> ant tasks/types (I cannot find the e-mail or bugzilla entry),
> but currently I do not think that this is necessary as:
>    - I do not think that more 3th class dependent optional tasks
>      will be added to ant core (they will be added as antlibs)
>      (we will have jvm dependent tasks) This means that
>      there is a relatively small number of optional tasks that need to
>      be fixed.
>

True, the future of optional tasks is probably antlib based.

> The problems I have with this is that:
>   1) it uses an undocumented and non-public method in a sun implementation
>       - this may change in future releases and the method might not exist
>        in non-sun implementations of the JVM.

Ah, I didn't know this as I haven't looked at the source code.

>   2) when ant is used in a IDE, in specific netbeans, the project classloader is
>       kept from build to build. So modifiing the project classloader may have
>       strange side effects in later builds on unrelated projects.

Yes that's also a problem, so two strikes.

>
> so I believe cl:classloader should be supported as an optional antlib.
> In my build
> system at work, I use it for handling a large number of classloading
> issues - for example junit with axis and cobutura.

Thanks for pointing me to it as it fixed my problem perfectly.

Kev

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


Re: Classloader problems

Posted by Peter Reilly <pe...@gmail.com>.
On 6/8/07, Kevin Jackson <fo...@gmail.com> wrote:
> Hi,
>
> > This means that the moving ant-email.jar from $ANT_HOME/lib will
> > not work.
> >
> > The EmailTask code could be modified to allow a classpath element to be used
> > to load the MimeMailer class (with junittask like classloader tricks),
>
> Yes I looked at seeing if re-writing the EmailTask to include some
> <classpath> management code - but the changes required ala Junit were
> fairly substantial and overall it was easier to use the classloader
> task - which worked perfectly btw and meant that I wasn't re-defining
> the scp/sshexec tasks either.
Initially I was thinking of using a separate classloader for
ant tasks/types (I cannot find the e-mail or bugzilla entry),
but currently I do not think that this is necessary as:
   - I do not think that more 3th class dependent optional tasks
     will be added to ant core (they will be added as antlibs)
     (we will have jvm dependent tasks) This means that
     there is a relatively small number of optional tasks that need to
     be fixed.

  - changing classloading for all tasks/types may have strange side-effects


> After seeing the classloader task in action I'm +1 for adding it to
> the code if the author wants - which from the look of the website they
> seem to.

The problems I have with this is that:
  1) it uses an undocumented and non-public method in a sun implementation
      - this may change in future releases and the method might not exist
       in non-sun implementations of the JVM.
  2) when ant is used in a IDE, in specific netbeans, the project classloader is
      kept from build to build. So modifiing the project classloader may have
      strange side effects in later builds on unrelated projects.

so I believe cl:classloader should be supported as an optional antlib.
In my build
system at work, I use it for handling a large number of classloading
issues - for example junit with axis and cobutura.

Peter

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

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


Re: Classloader problems

Posted by Kevin Jackson <fo...@gmail.com>.
Hi,

> This means that the moving ant-email.jar from $ANT_HOME/lib will
> not work.
>
> The EmailTask code could be modified to allow a classpath element to be used
> to load the MimeMailer class (with junittask like classloader tricks),

Yes I looked at seeing if re-writing the EmailTask to include some
<classpath> management code - but the changes required ala Junit were
fairly substantial and overall it was easier to use the classloader
task - which worked perfectly btw and meant that I wasn't re-defining
the scp/sshexec tasks either.

After seeing the classloader task in action I'm +1 for adding it to
the code if the author wants - which from the look of the website they
seem to.

Kev

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


Re: Classloader problems

Posted by Peter Reilly <pe...@gmail.com>.
On 6/8/07, Kevin Jackson <fo...@gmail.com> wrote:
> Hi,
>
> > I was supprised that the <taskdef> you described
> > worked for scp, I think that you have removed the
> > ant-jsch.jar from from $ANT_HOME/lib.
>
> Yes as the classloader will find the ant-jsch.jar iin $ANT_HOME/lib
> and try to load the jsch code from there.  I moved it to a different
> location and <csp> worked fine - I expected the same behaviour with
> <mail>, but instead I've had some problems.
<looking at the code and the ant 1.7.0 jars files>
The ant-email.jar file does not contain the mail task. <mail> is
not an "optional" task. and is located in ant.jar, however if mime
types are used, the EmailTask code will attempt to load MimeMailer
(which is in ant-email.jar) by doing the following:
         mailer = (Mailer) ClasspathUtils.newInstance(
                       "org.apache.tools.ant.taskdefs.email.MimeMailer",
                            EmailTask.class.getClassLoader(), Mailer.class);

Which seems a bit pointless from a deployment point of view, but it
does allow the EmailTask to get compiled without depending on
javamail.jar in the classpath.

This means that the moving ant-email.jar from $ANT_HOME/lib will
not work.

The EmailTask code could be modified to allow a classpath element to be used
to load the MimeMailer class (with junittask like classloader tricks),
but in the meantime,
one  can use the cl:classloader task.

Peter

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


Re: Classloader problems

Posted by Kevin Jackson <fo...@gmail.com>.
Hi,

> I was supprised that the <taskdef> you described
> worked for scp, I think that you have removed the
> ant-jsch.jar from from $ANT_HOME/lib.

Yes as the classloader will find the ant-jsch.jar iin $ANT_HOME/lib
and try to load the jsch code from there.  I moved it to a different
location and <csp> worked fine - I expected the same behaviour with
<mail>, but instead I've had some problems.

> I tryed the following without removing ant-jsch.jar from
> $ANT_HOME/lib and got the expected build failure.
> build.xml:
> <project default="x">
>   <target name="x">
>     <property name="src.tools.dir" location="${user.home}/apps"/>
>     <path id="jsch.path">
>       <pathelement location="${src.tools.dir}/jsch/ant-jsch.jar"/>
>       <pathelement location="${src.tools.dir}/jsch/jsch-0.1.33.jar"/>
>     </path>
>     <taskdef
>       name="scp"
>       classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
>       classpathref="jsch.path"/>
>
>     <scp hello="world"/>
>   </target>
> </project>
>
> result:
> BUILD FAILED
> /work/reilly/learning/a/jsch/build.xml:11: taskdef A class needed by
> class org.apache.tools.ant.taskdefs.optional.ssh.Scp cannot be found:
> com/jcraft/jsch/UserInfo
>
>

> They are for <taskdef>.
>
> In ant1.7.0 only junit has been coded to allow the dependent classes
> to be defined in an embedded classpath.
> In ant1.7.1 this has been extended to the <script> family.
>
> The code involved uses classloader tricks that are not too
> easy to generalize to the other class dependent optional tasks.

It may be worth looking at though. It's strange to have one task work
as expected and another break when configuring them in the same way.
Principle of least surprise and all that

> See http://ant.apache.org/faq.html#delegating-classloader
> for a description of the problem.

I spent a while yesterday looking at that and reviewing what I could
do about it - I thought that since the scp task worked my moving all
the dependent jars and re-defining it, then the other tasks would too.

>
> In my build files, I use the excellent
> [antlib:net.jtools.classloadertask]classloader
> task:
>
> from http://enitsys.sourceforge.net/ant-classloadertask/
>     <typedef uri="antlib:net.jtools.classloadertask"
>              resource="net/jtools/classloadertask/antlib.xml">
>       <classpath>
>         <fileset
>           dir="${user.home}/tools/ant-classloader"
>                includes="*.jar"/>
>       </classpath>
>     </typedef>
>
>
>     <cl:classloader loader="project">
>       <classpath>
>         <fileset dir="${src.tools.dir}/jsch/" includes="js*.jar"/>
>       </classpath>
>     </cl:classloader>
>     <scp hello="world"/>
>

Thanks Peter, unless there's another work-around I will have to follow
your lead and use the same classloader task.

Kev

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


Re: Classloader problems

Posted by Peter Reilly <pe...@gmail.com>.
I was supprised that the <taskdef> you described
worked for scp, I think that you have removed the
ant-jsch.jar from from $ANT_HOME/lib.

I tryed the following without removing ant-jsch.jar from
$ANT_HOME/lib and got the expected build failure.
build.xml:
<project default="x">
  <target name="x">
    <property name="src.tools.dir" location="${user.home}/apps"/>
    <path id="jsch.path">
      <pathelement location="${src.tools.dir}/jsch/ant-jsch.jar"/>
      <pathelement location="${src.tools.dir}/jsch/jsch-0.1.33.jar"/>
    </path>
    <taskdef
      name="scp"
      classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
      classpathref="jsch.path"/>

    <scp hello="world"/>
  </target>
</project>

result:
BUILD FAILED
/work/reilly/learning/a/jsch/build.xml:11: taskdef A class needed by
class org.apache.tools.ant.taskdefs.optional.ssh.Scp cannot be found:
com/jcraft/jsch/UserInfo



On 6/7/07, Kevin Jackson <fo...@gmail.com> wrote:
> Hi all,
>
> For obscure reasons, I have to redefine the core email task using a taskdef.
> This is my build file:
> <path id="jsch.path">
>   <pathelement location="${src.tools.dir}/jsch/ant-jsch.jar"/>
>   <pathelement location="${src.tools.dir}/jsch/jsch-0.1.33.jar"/>
> </path>
> <taskdef name="scp"
>                 classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
>                 classpathref="jsch.path"/>
>
> <taskdef name="sshexec"
> classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec"
> classpathref="jsch.path"/>
>
> <taskdef name="mail"
>                 classname="org.apache.tools.ant.taskdefs.email.EmailTask">
>         <classpath>
>           <pathelement location="${src.tools.dir}/mail/ant-javamail.jar"/>
>           <pathelement location="${src.tools.dir}/mail/mail.jar"/>
>         </classpath>
> </taskdef>
>
> Now the strange thing is that thescp & sshexec tasks report that they
> have been over-ridden by the new definitions, and with -debug enabled
> I can see the correct classes being loaded.  The mail task however
> just reports ' Class org.apache.tools.ant.taskdefs.email.EmailTask
> loaded from parent loader (parentFirst)'.
>
> Then finally it fails with ClassNotFoundException.  This means that
> the <classpath> is ignored for the mail taskkdef, but is used
> correctly for the scp/sshexec taskdefs.
>
> I would think it would make sense to treat all taskdefs & classpaths equal...
They are for <taskdef>.

In ant1.7.0 only junit has been coded to allow the dependent classes
to be defined in an embedded classpath.
In ant1.7.1 this has been extended to the <script> family.

The code involved uses classloader tricks that are not too
easy to generalize to the other class dependent optional tasks.

>
> I cannot copy the jars into ~/.ant/lib, or $ANT_HOME/lib, and I cannot
> rely on a CLASSPATH variable or an external calling script.  The only
> way I can make what I want to do work is via the taskdefs which honour
> the <classpath> or classpathref.  Does anyone know how to work around
> this?

See http://ant.apache.org/faq.html#delegating-classloader
for a description of the problem.

In my build files, I use the excellent
[antlib:net.jtools.classloadertask]classloader
task:

from http://enitsys.sourceforge.net/ant-classloadertask/
    <typedef uri="antlib:net.jtools.classloadertask"
             resource="net/jtools/classloadertask/antlib.xml">
      <classpath>
        <fileset
          dir="${user.home}/tools/ant-classloader"
               includes="*.jar"/>
      </classpath>
    </typedef>


    <cl:classloader loader="project">
      <classpath>
        <fileset dir="${src.tools.dir}/jsch/" includes="js*.jar"/>
      </classpath>
    </cl:classloader>
    <scp hello="world"/>


Peter

>
> Thanks,
> Kev
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
> For additional commands, e-mail: dev-help@ant.apache.org
>
>

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