Est-il possible de spécifier un Java classpath
qui inclut un fichier JAR contenu dans un autre fichier JAR?
Est-il possible de spécifier un Java classpath
qui inclut un fichier JAR contenu dans un autre fichier JAR?
Réponses:
Si vous essayez de créer un seul fichier jar contenant votre application et ses bibliothèques requises, il existe deux façons (à ma connaissance) de le faire. Le premier est One-Jar , qui utilise un chargeur de classe spécial pour permettre l'imbrication des fichiers JAR. Le second est UberJar , (ou Shade ), qui explose les bibliothèques incluses et place toutes les classes dans le fichier jar de niveau supérieur.
Je dois également mentionner que UberJar et Shade sont des plugins pour Maven1 et Maven2 respectivement. Comme mentionné ci-dessous, vous pouvez également utiliser le plugin d'assemblage (qui en réalité est beaucoup plus puissant, mais beaucoup plus difficile à configurer correctement).
Vous ne souhaitez PAS utiliser ces solutions «exploser le contenu JAR». Ils rendent définitivement plus difficile de voir les choses (puisque tout est explosé au même niveau). De plus, il peut y avoir des conflits de noms (cela ne devrait pas se produire si les gens utilisent des packages appropriés, mais vous ne pouvez pas toujours contrôler cela).
La fonctionnalité que vous recherchez est l'une des 25 meilleures RFE Sun : RFE 4648386 , que Sun, dans son infinie sagesse, a désignée comme étant de faible priorité. On ne peut qu'espérer que Sun se réveille ...
En attendant, la meilleure solution que j'ai rencontrée (que je souhaite que Sun copie dans le JDK) est d'utiliser le chargeur de classe personnalisé JarClassLoader .
activation.jar
).
Après quelques recherches, j'ai trouvé une méthode qui ne nécessite pas maven ou une extension / programme tiers.
Vous pouvez utiliser "Class-Path" dans votre fichier manifeste.
Par exemple:
Créer le fichier manifeste MANIFEST.MF
Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass
Compilez toutes vos classes et exécutez jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar
c
signifie créer une archive
f
indique que vous voulez spécifier le fichier
v
est pour une entrée verbeuse
m
signifie que nous allons transmettre un fichier manifeste personnalisé
Assurez-vous que vous avez inclus lib dans le package jar. Vous devriez pouvoir exécuter jar de la manière habituelle.
basé sur: http://www.ibm.com/developerworks/library/j-5things6/
toutes les autres informations dont vous avez besoin sur le chemin des classes vous trouvez ici
custom_lib.jar
, le pot ne peut plus être exécuté :(
Utilisez la balise zipgroupfileset (utilise les mêmes attributs qu'une balise d'ensemble de fichiers ); il décompressera tous les fichiers du répertoire et les ajoutera à votre nouveau fichier d'archive. Plus d'informations: http://ant.apache.org/manual/Tasks/zip.html
C'est un moyen très utile de contourner le problème du jar-in-a-jar - je le sais parce que j'ai recherché sur Google cette question exacte de StackOverflow tout en essayant de savoir quoi faire. Si vous voulez empaqueter un jar ou un dossier de jars dans votre jar construit avec Ant, alors oubliez tout ce chemin de classe ou ce plugin tiers, tout ce que vous avez à faire est ceci (dans Ant):
<jar destfile="your.jar" basedir="java/dir">
...
<zipgroupfileset dir="dir/of/jars" />
</jar>
Si vous construisez avec ant (j'utilise ant from eclipse), vous pouvez simplement ajouter les fichiers jar supplémentaires en disant à fourmi de les ajouter ... Ce n'est pas nécessairement la meilleure méthode si vous avez un projet géré par plusieurs personnes mais cela fonctionne pour un projet de personne et c'est facile.
par exemple, ma cible qui construisait le fichier .jar était:
<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
<manifest>
<attribute name="Author" value="ntg"/>
................................
<attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
</manifest>
</jar>
Je viens d'ajouter une ligne pour le faire:
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
où
<property name="external-lib-dir"
value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
était le dir avec les pots externes. Et c'est tout...
Pour ce faire, vous devez créer un chargeur de classe personnalisé ou une bibliothèque tierce qui prend en charge cela. Votre meilleur pari est d'extraire le fichier jar du runtime et de l'ajouter au classpath (ou de les ajouter déjà au classpath).
J'utilise maven pour mes builds java qui a un plugin appelé le plugin d'assemblage maven .
Il fait ce que vous demandez, mais comme certaines des autres suggestions le décrivent - en faisant exploser tous les pots dépendants et en les recombinant en un seul pot
Si vous avez eclpise IDE, il vous suffit d'exporter votre JAR et de choisir "Package Requis des bibliothèques dans le JAR généré". eclipse ajoutera automatiquement les JAR dépendants requis dans le JAR généré et générera également un chargeur de classe personnalisé eclipse qui chargera ces JAR automatiquement.
J'étais sur le point de conseiller d'extraire tous les fichiers au même niveau, puis de créer un pot à partir du résultat, car le système de paquetage devrait les garder soigneusement séparés. Ce serait la méthode manuelle, je suppose que les outils indiqués par Steve le feront très bien.
Winstone est plutôt bon http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/ . Mais pas pour les sites complexes. Et c'est dommage car il suffit d'inclure le plugin.
Eh bien, il existe un moyen très simple si vous utilisez Eclipse.
Exportez votre projet en tant que fichier Jar "Runnable" (cliquez avec le bouton droit sur le dossier du projet depuis Eclipse, sélectionnez "Exporter ..."). Lorsque vous configurez les paramètres d'exportation, assurez-vous de sélectionner «Extraire les bibliothèques requises dans le fichier Jar généré». N'oubliez pas, sélectionnez "Extraire ..." et non "Package requis bibliothèques ...".
De plus : vous devez sélectionner une configuration d'exécution dans vos paramètres d'exportation. Ainsi, vous pouvez toujours créer un main () vide dans une classe et l'utiliser pour votre configuration d'exécution.
Quoi qu'il en soit, il n'est pas garanti de fonctionner à 100% du temps - comme vous remarquerez un message contextuel vous demandant de vous assurer de vérifier les licences des fichiers Jar que vous incluez et de ne pas copier les fichiers de signature. Cependant, je fais cela depuis des années et je n'ai jamais rencontré de problème.
Extraire dans un Uber-dir fonctionne pour moi car nous devrions tous utiliser root: \ java et avoir du code de sortie dans des packages avec versioning. Ie ca.tecreations-1.0.0. La signature est correcte car les pots sont intacts depuis leur emplacement téléchargé. Signatures tierces intactes, extraire vers c: \ java. Il y a mon projet dir. exécuter à partir du lanceur donc java -cp c: \ java Launcher