web-dev-qa-db-fra.com

Ant ne peut pas trouver une classe nécessaire à un taskdef défini en externe

J'essaie d'utiliser la tâche de construction axis-Java2wsdl pour créer un fichier WSDL à partir de l'une de mes classes Java, mais je ne peux pas obtenir le chemin d'accès aux classes correct.

J'utilise le paquetage libaxis-Java d'Ubuntu qui installe axis-ant.jar dans $ ANT_HOME/lib et axis.jar dans/usr/share/Java. Les parties intéressantes de mon build.xml ressemblent à ceci:

<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>

Exécuter ant genwsdl entraîne:

/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 est capable de trouver la définition de la tâche axis-Java2wsdl, car axis-ant.jar est dans $ ANT_HOME/lib, mais il ne peut pas trouver de classes dans axis.jar, même si ce fichier jar se trouve sur le chemin défini par "libraries".

Je sais que c'est un problème de chemin de classe parce que j'ai pu aller au-delà de DefaultAuthenticator pour que d'autres classes ne soient pas trouvées par symlinking axis.jar dans $ ANT_HOME/lib. Comment faire en sorte que taskdef reconnaisse les fichiers jar dans/usr/share/lib ou le répertoire lib local de mon projet sans tout connecter dans $ ANT_HOME/lib?

MODIFIER:

J'ai finalement réussi à générer le wsdl avec cette ligne:

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

J'apprécierais toujours beaucoup si quelqu'un pouvait me dire ce que je fais de mal en étant incapable de définir ces bibliothèques dans build.xml

14
Ryan Ahearn

En général, cela fonctionne. Mais vous devez vérifier très attentivement quelles classes sont où. 

Si votre classe de tâches peut être chargée dans un chargeur de classes plus haut dans la hiérarchie du chargeur de classes (comme CLASSPATH ou ANT_HOME/lib), votre classpathref sera simplement ignoré

Lisez l'entrée FAQ pour plus de détails. 

L'implémentation du chargeur de classes d'Ant utilise le modèle de délégation de Java

La classe ClassLoader utilise un modèle de délégation pour rechercher des classes et des ressources. Chaque instance de ClassLoader a un chargeur de classe parent associé. Lorsqu'elle est appelée pour rechercher une classe ou une ressource, une instance de ClassLoader déléguera la recherche de la classe ou de la ressource à son chargeur de classe parent avant de tenter de trouver la classe ou la ressource elle-même. Le chargeur de classes intégré à la machine virtuelle, appelé chargeur de classes d'amorçage, n'a pas de père, mais peut servir de parent à une instance de ClassLoader.

Remarque: exécuter ant -diagnosticspeut également vous aider .

15
VonC

Ant mécanisme pour l'ajout de bibliothèques est:

  • via l'argument de ligne de commande -lib
  • ajouter à $ {user.home} /. ant/lib
  • ajouter à $ {ant.home}/lib

Seulement. Le manual ne mentionne rien sur l'utilisation de la propriété system.library.dir. Probablement, c'est à peu près ignoré à cette fin.

En outre, exécutez ant en mode verbose (et -verbose) pour voir ce qui se passe sous le capot.

5
OscarRyz

En utilisant les réponses d’ici et toutes les informations partielles, j’ai trouvé une solution. J'ai ajouté le fichier jar dont le fichier ant avait besoin dans un dossier lib du projet (en particulier les pilotes mysql jdbc). Ensuite, j'exécute une tâche d'installation dans ant qui copie dans le dossier .ant/lib de l'utilisateur, puis échoue avec un message à redémarrer. Il échoue seulement une fois pour un utilisateur, puis fonctionne à chaque fois. Cela peut être délicat si vous mettez à jour le bocal vers une nouvelle version ...

Voici le build.xml ant:

<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>

J'espère que cela t'aides

1
Kieveli

Pourquoi ne pas simplement prendre l’option la plus simple et spécifier le chemin de classe dans votre <taskdef>?

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

Ou créez une deuxième entrée <classpath> qui sous-définit library.dir?

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

S'amuser avec ${ant.home}/lib n'est pas une si bonne idée et peut presque toujours être évité.

1
matt b

Cela me permet de spécifier le classpath directement dans la tâche taskdef, comme indiqué dans matt b . Pour mon projet, je trouve utile d'inclure la bibliothèque taskdef dans le dossier du projet et de spécifier le chemin d'accès aux classes dans le fichier de construction ant, afin de le configurer simplement sur d'autres ordinateurs de développement. J'utilise le taskdef suivant:

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

Notez que cela pourrait ne pas fonctionner pour les versions de ant antérieures à 1.7.0. 

1
Ralf

J'ai rencontré le même problème lorsque je copie un fichier * .jar dans {ant.home}/libs, puis j'utilise la bibliothèque pour localiser le fichier * .jar, il fonctionne correctement! Je considère que les nouveaux bocaux ne peuvent pas être chargés, alors je vais le tester!

0
Andrew