Java Ant 找不到外部定义的 taskdef 所需的类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/482303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:13:27  来源:igfitidea点击:

Ant cannot find a class needed by an externally defined taskdef

javaantclasspathaxis

提问by Ryan Ahearn

I am trying to use the axis-java2wsdl ant task to create a wsdl from one of my java classes, but I cannot get the classpath correct.

我正在尝试使用 axis-java2wsdl ant 任务从我的一个 java 类创建 wsdl,但我无法获得正确的类路径。

I am using Ubuntu's libaxis-java package which installs axis-ant.jar in $ANT_HOME/lib and axis.jar in /usr/share/java. The interesting parts of my build.xml look like this:

我正在使用 Ubuntu 的 libaxis-java 包,它在 $ANT_HOME/lib 中安装axis-ant.jar,在/usr/share/java 中安装axis.jar。我的 build.xml 中有趣的部分如下所示:

<property name="library.dir" value="lib"/>
<property name="system.library.dir" value="/usr/share/java"/>
<path id="libraries">
    <fileset dir="${library.dir}">
        <include name="*.jar"/>
    </fileset>
    <fileset dir="${system.library.dir}">
        <include name="*.jar"/>
    </fileset>
</path>

<target name="genwsdl" depends="compile">
    <taskdef resource="axis-tasks.properties" classpathref="libraries"/>
    <axis-java2wsdl>
            details omitted
    </axis-java2wsdl>
</target>

Running ant genwsdlresults in:

运行ant genwsdl结果:

/build.xml:50: taskdef A class needed by class
org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask
cannot be found: org/apache/axis/utils/DefaultAuthenticator

Ant is able to find the definition of the axis-java2wsdl task, because axis-ant.jar is in $ANT_HOME/lib, but it cannot find classes in axis.jar, even though that jar is on the path defined by "libraries"

Ant 能够找到axis-java2wsdl 任务的定义,因为axis-ant.jar 位于$ANT_HOME/lib 中,但是它在axis.jar 中找不到类,即使该jar 位于“libraries”定义的路径上

I know it's a classpath issue because I was able to get past DefaultAuthenticator to other class's not found by symlinking axis.jar into $ANT_HOME/lib. How can I get the taskdef to recognize jar files in /usr/share/lib or my project's local lib directory without symlinking everything into $ANT_HOME/lib?

我知道这是一个类路径问题,因为我能够通过将 axis.jar 符号链接到 $ANT_HOME/lib 来绕过 DefaultAuthenticator 到其他类。如何让 taskdef 识别 /usr/share/lib 或我的项目的本地 lib 目录中的 jar 文件,而无需将所有内容符号链接到 $ANT_HOME/lib 中?

EDIT:

编辑:

I was finally able to successfully generate the wsdl with this line:

我终于能够用这一行成功生成 wsdl:

ant -lib /usr/share/java/axis.jar -lib /usr/share/java/jaxrpc.jar -lib /usr/share/java/wsdl4j.jar -lib /usr/share/java/commons-logging.jar -lib /usr/share/java/commons-discovery.jar -lib build genwsdl

I would still very much appreciate if somebody could tell me what I'm doing wrong in not being able to define those libraries in build.xml

如果有人能告诉我无法在 build.xml 中定义这些库,我做错了什么,我仍然非常感激

采纳答案by VonC

In general, this works. But you need to check very carefully which classes are where.

一般来说,这是有效的。但是你需要非常仔细地检查哪些类在哪里。

If your task class can be loaded in a classloader higher up in the classloader hierarchy (like CLASSPATH or ANT_HOME/lib) then your classpathref will simply get ignored.

如果您的任务类可以在类加载器层次结构中更高的类加载器中加载(如 CLASSPATH 或 ANT_HOME/lib),那么您的 classpathref 将被忽略

Read the FAQ entryfor more details.

阅读常见问题条目了解更多详情。

Ant's class loader implementation uses Java's delegation model

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When called upon to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the bootstrap class loader, does not itself have a parent but may serve as the parent of a ClassLoader instance.

Ant 的类加载器实现使用Java 的委托模型

ClassLoader 类使用委托模型来搜索类和资源。ClassLoader 的每个实例都有一个关联的父类加载器。当调用查找类或资源时,ClassLoader 实例将在尝试查找类或资源本身之前将类或资源的搜索委托给其父类加载器。虚拟机的内置类加载器,称为引导类加载器,它本身没有父级,但可以作为 ClassLoader 实例的父级。

Note: running ant -diagnosticscan help too.

注意:跑步ant -diagnostics也有帮助

回答by OscarRyz

Ant mechanismfor adding libraries is:

Ant添加库的机制是:

  • via command line argument -lib
  • adding to ${user.home}/.ant/lib
  • adding to ${ant.home}/lib
  • 通过命令行参数 -lib
  • 添加到 ${user.home}/.ant/lib
  • 添加到 ${ant.home}/lib

Only. The manualdoesn't mention anything about using the system.library.dirproperty. Probably it pretty much ignored for this purpose.

仅有的。该手册没有提到有关使用system.library.dir属性的任何内容。为此目的,它可能几乎被忽略了。

Also, run ant in verbose mode ( and -verbose ) to see what is doing under the hood.

此外,以详细模式(和 -verbose )运行 ant 以查看幕后执行的操作。

回答by matt b

Why not just take the simplest option and specify the classpath in your <taskdef>?

为什么不采用最简单的选项并在您的<taskdef>?

<taskdef resource="axis-tasks.properties">
    <classpath>
        <fileset file="/path/to/axis/jars"/>
    </classpath>
</taskdef>

Or create a second <classpath>entry that subsets library.dir?

或者创建一个<classpath>子集的第二个条目library.dir

<path id="axis-tools-classpath">
    <fileset dir="/path/to/axis/home">
        <include name="*.jar"/>
    </fileset>
    <path refid="library.dir"/>
</path>

Messing around with ${ant.home}/libis not such a good idea and can almost always be avoided.

乱搞${ant.home}/lib不是一个好主意,几乎总是可以避免的。

回答by Ralf

It works for me to specify the classpath directly in the taskdef task, as menstioned by matt b. For my project I find it useful to include the taskdef library in the project folder and specify the classpath in the ant build file, to simply setup on other development pcs. I use the following taskdef:

它适用于我直接在 taskdef 任务中指定类路径,正如matt b所提到的。对于我的项目,我发现在项目文件夹中包含 taskdef 库并在 ant 构建文件中指定类路径很有用,以便在其他开发 PC 上进行简单设置。我使用以下任务定义:

<taskdef resource="antenna.properties" classpath="${myprojectroot}/lib/antenna-bin-1.2.1-beta.jar"/>

Note that this might not work for versions of ant earlier than 1.7.0.

请注意,这可能不适用于早于 1.7.0 的 ant 版本。

回答by Kieveli

Using the answers from here and all the partial information, I came up with a solution. I added the jar the ant file needed to a lib folder in the project (specifically mysql jdbc drivers). Then I run a setup task in ant that copies to the user's home .ant/lib folder, and then fails ant with a message to restart. It only fails once for a user, and then works every time. It might be tricky if you update the jar to a new version...

使用这里的答案和所有部分信息,我想出了一个解决方案。我将ant文件所需的jar添加到项目中的lib文件夹中(特别是mysql jdbc驱动程序)。然后,我在 ant 中运行一个安装任务,该任务复制到用户的主 .ant/lib 文件夹,然后使 ant 失败并显示重新启动的消息。它只对用户失败一次,然后每次都有效。如果您将 jar 更新到新版本可能会很棘手...

Here's the ant build.xml:

这是ant build.xml:

<project name="data_source" default="build">

  <!-- BUILD PROPERTIES -->
  <property file="build.properties"/>

  <!-- SQL Server Properties -->
  <property name="sql.driver" value="org.gjt.mm.mysql.Driver"/>
  <property name="sql.url" value="jdbc:mysql://127.0.0.1/datastore"/>
  <property name="sql.user" value="user"/>
  <property name="sql.pass" value="password"/>

  <!-- FILE LOCATIONS  -->
  <property name="sql.dir" location="sql"/>

  <!-- INITIALIZE PROJECT -->
  <target name="init" description="Initialize the project">
      <available property="no.ant.lib.dir" file="${user.home}/.ant/lib/" type="dir" />
  </target>

  <!-- SETUP MYSQL -->
  <target name="setup_mysql" description="Copy the lib so ant can see it" unless="no.ant.lib.dir">
      <mkdir dir="${user.home}/.ant"/>
      <mkdir dir="${user.home}/.ant/lib"/>
      <copy file="lib/mysql-connector-java-5.1.13-bin.jar" todir="${user.home}/.ant/lib"/>

      <!-- ant already missed picking up the jar - we have to restart -->
      <fail message="JDBC mysql class copied to ${user.dir}/.ant/lib/ - please restart ant" />
  </target>

  <!-- BUILD DATA SOURCES -->
  <target name="build" depends="init,setup_mysql,clean_data" description="Create and populate tables">

    <sql driver="${sql.driver}" url="${sql.url}" userid="${sql.user}" password="${sql.pass}" >
      <transaction src="${sql.dir}/create_tables.sql"/>
      <transaction src="${sql.dir}/insert_data.sql"/>
    </sql>
  </target>

   <!-- CLEAN PROJECT -->
  <target name="clean" description="Cleans up project build">
    <!-- Don't clean data sources here - may get called by accident -->
  </target>

  <!-- Delete all tables and data -->
  <target name="clean_data" description="Deletes all data and tables">
    <echo>Dropping all database tables in ${sql.schema}...</echo>
    <property name="exec.command" value="mysqldump -u${sql.user} -p${sql.pass} --add-drop-table --no-data ${sql.schema} | grep ^DROP | mysql -u${sql.user} -p${sql.pass} ${sql.schema}" />
    <exec executable="sh">
      <arg value = "-c"/>
      <arg value="${exec.command}"/>
    </exec>

  </target>

</project>

Hope this helps

希望这可以帮助

回答by Andrew

I met the same problem when I copy a *.jar to the {ant.home}/libs, then i user the -lib to locate the *.jar, it's runs ok! I consider it's the new jars can't be loaded, then i'll test it!

当我将 *.jar 复制到 {ant.home}/libs 时遇到了同样的问题,然后我使用 -lib 来定位 *.jar,它运行正常!我认为是新的罐子无法加载,然后我会测试它!