J'ai une application que j'essaie d'emballer dans un jar pour faciliter le déploiement. L'application se compile et s'exécute correctement (dans une fenêtre cmd de Windows) lorsqu'elle est exécutée comme un ensemble de classes accessibles depuis le CLASSPATH. Mais lorsque je mets mes classes en jar et que j'essaie de l'exécuter avec java 1.6 dans la même fenêtre cmd, je commence à obtenir des exceptions :
C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:\myapp\libs\commons -logging-1.1.jar -server -jar DataGen.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 1 more
Ce qui est amusant, c'est que la LogFactory incriminée semble se trouver dans commons-logging-1.1.jar, qui se trouve dans le chemin de classe spécifié. Le fichier jar (oui, il est bien là) :
C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar
Volume in drive C is Local Disk
Volume Serial Number is ECCD-A6A7
Directory of C:\myapp\libs
12/11/2007 11:46 AM 52,915 commons-logging-1.1.jar
1 File(s) 52,915 bytes
0 Dir(s) 10,956,947,456 bytes free
Le contenu du fichier commons-logging-1.1.jar :
C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-logging-1.1.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/commons/
org/apache/commons/logging/
org/apache/commons/logging/impl/
META-INF/LICENSE.txt
META-INF/NOTICE.txt
org/apache/commons/logging/Log.class
org/apache/commons/logging/LogConfigurationException.class
org/apache/commons/logging/LogFactory$1.class
org/apache/commons/logging/LogFactory$2.class
org/apache/commons/logging/LogFactory$3.class
org/apache/commons/logging/LogFactory$4.class
org/apache/commons/logging/LogFactory$5.class
org/apache/commons/logging/LogFactory.class
... (more classes in commons-logging-1.1 ...)
Oui, commons-logging possède la classe LogFactory. Et enfin, le contenu du manifeste de mon jar :
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 10.0-b23 (Sun Microsystems Inc.)
Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest
Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink
.jar GroboTestingJUnit-1.2.1-core.jar junit.jar
Cela me laisse perplexe, ainsi que tous les collègues que j'ai mis sur écoute depuis plus d'un jour maintenant. Pour faire le tour des réponses, pour le moment du moins, les solutions tierces sont probablement exclues en raison des restrictions de licence et des politiques de l'entreprise (par exemple, les outils de création d'exe ou de conditionnement des jars). Le but ultime est de créer un jar qui peut être copié de ma boîte Windows de développement à un serveur Linux (avec tous les jars dépendants) et utilisé pour remplir une base de données (donc les classpaths peuvent être différents entre les environnements de développement et de déploiement). Tout indice sur ce mystère serait grandement apprécié !