Looking for Computer Science & Information Technology online
courses ?
Check my new web site: https://www.yesik.it !
Pour faciliter la distribution des applications Java, il est possible de réunir tous les fichiers qui la composent dans une archive .jar. Le JDK fourni un utilitaire spécifique (jar) pour cette tâche. Mais il est également possible de l'automatiser. Nous allons donc voir dans ce tutoriel comment créer une archive JAR avec Ant.
Objectifs | A la fin de ce tutoriel, vous saurez:
|
---|---|
Prérequis | |
Moyens |
Sommaire
Pourquoi empaqueter une application?
Réunir tous les fichiers (.class et fichiers de données) qui composent une application dans une seule et même archive offre plusieurs avantages. En particulier, cela:
- Facilite les échanges: il est plus simple de transférer un seul fichier que toute une arborescence;
- Améliore la fiabilité: il n'y a plus de risque d'oublier un fichier ou de le mettre dans le mauvais sous-répertoire
- Limite les problèmes de compatibilité: Tous les fichiers nécessaires étant dans une même archive, il n'y plus de risque d'incompatibilité entre fichiers de versions différentes.
On peut également noter que les archives étant compressées, elles réduisent les besoins en bande passante pour le transfert d'application. Enfin, elles peuvent également être signées numériquement, ce qui renforce la sécurité.
Créer une archive .jar
Dans le tutoriel précédent, nous avons réalisé une petite application Java, et utilisé Ant pour la compiler.
Si vous avez suivi ce tutoriel, vous devez déjà disposer de ces fichiers. Sinon, reportez-vous y pour récupérer les fichiers Banque.java, Compte.java et build.xml.
La cible dist
Dans le JDK, l'utilitaire jar permet de créer une archive .jar. Nous n'allons pas l'utiliser directement ici, mais au travers de l'outil Ant.
Pour créer une archive, il nous faut donc ajouter une nouvelle cible à notre fichier build.xml. Cette cible utilisera la tâche jar:
<target name="dist" depends="compile"> <jar destfile="${dist.dir}/app.jar" basedir="${build.dir}" /> </target>

jar ou jar?
Ne confondez-pas:
- La commande jar du JDK qui permet de créer une archive
- La tâche jar de Ant qui permet de créer une archive
- Le fichier .jar qui est l'archive elle-même
Deux choses à noter ici:
- Tout d'abord, comme il est nécessaire de compiler l'application avant de pouvoir créer l'archive, la cible dist dépend de la cible compile;
- Ensuite, nous utilisons ici une nouvelle propriété (dist.dir) pour spécifier le répertoire dans lequel va être stocké l'archive .jar. Celle-ci doit bien entendu être initialisée:
<property name="dist.dir" value="dist" />
Puisque nous introduisons un nouveau répertoire, il nous faut également modifier les cibles init et clean respectivement pour créer et supprimer ce répertoire:
<target name="init"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> </target> <target name="clean" description="Fait le menage"> <delete dir="${build.dir}" /> <delete dir="${dist.dir}" /> </target>
Construire l'archive
Maintenant que le fichier build.xml a été modifié, contruire l'archive se fait simplement en utilisant la commande ant à partir du répertoire racine du projet:
sh$ ant dist
Buildfile: build.xml init: [mkdir] Created dir: /Users/sylvain/ProjetBanque/build [mkdir] Created dir: /Users/sylvain/ProjetBanque/dist compile: [javac] Compiling 2 source files to /Users/sylvain/ProjetBanque/build dist: [jar] Building jar: /Users/sylvain/ProjetBanque/dist/app.jar BUILD SUCCESSFUL Total time: 4 seconds
On peut facilement vérifier que l'archive a bien été produite:
sh$ ls dist app.jar
Puisque l'interpréteur Java est capable d'exécuter un programme stocké dans une archive JAR, nous pouvons tenter d'exécuter notre programme:
sh$ cd dist sh$ java -jar app.jar Failed to load Main-Class manifest attribute from app.jar
Oups! Visiblement, quelque chose manque...
Le manifeste
En plus des fichiers spécifiques à notre projet, une archive jar doit toujours contenir un manifeste. C'est un fichier spécial qui fourni des informations sur l'archive (des méta-informations). Par exemple, c'est le manifeste qui indique à l'interpréteur java quelle est la classe principale (celle qui contient le main) d'une application.
Si l'on regarde à l'aide de la commande jar le contenu de notre archive, nous pouvons constater qu'un fichier MANIFEST.MF a automatiquement été généré dans le sous-répertoire META-INF:
sh$ jar tvf app.jar
0 Sat Oct 06 22:01:26 CEST 2007 META-INF/ 106 Sat Oct 06 22:01:24 CEST 2007 META-INF/MANIFEST.MF 0 Sat Oct 06 22:01:24 CEST 2007 fr/ 0 Sat Oct 06 22:01:24 CEST 2007 fr/esicom/ 0 Sat Oct 06 22:01:24 CEST 2007 fr/esicom/exemples/ 513 Sat Oct 06 22:01:24 CEST 2007 fr/esicom/exemples/Banque.class 568 Sat Oct 06 22:01:24 CEST 2007 fr/esicom/exemples/Compte.class
Lors de la création de l'archive, Ant a généré un manifeste par défaut. Nous pouvons en visualiser le contenu:
sh$ jar xf app.jar META-INF/MANIFEST.MF sh$ cat META-INF/MANIFEST.MF Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7.0 Created-By: 1.3.1_03-74 ("Apple Computer, Inc.")
Tout ce qui manque à ce manifeste pour permettre à l'interpréteur java d'utiliser notre archive est l'information qui précise que la classe principale de notre programme est fr.esicom.exemples.Banque. Il existe plusieurs manières de fournir cette information, mais le plus simple est de l'indiquer à Ant, dans la tâche jar. La cible dist devient alors:
<target name="dist" depends="compile"> <jar destfile="${dist.dir}/app.jar" basedir="${build.dir}"> <manifest> <attribute name="Main-Class" value="fr.esicom.exemples.Banque" /> </manifest> </jar> </target>
Nous pouvons maintenant reconstruire notre archive (en faisant avant un peu de ménage pour effacer les fichiers que nous avons laissé traîner dans build):
sh$ cd... sh$ ant clean dist Buildfile: build.xml clean: [delete] Deleting directory /Users/sylvain/ProjetBanque/build [delete] Deleting directory /Users/sylvain/ProjetBanque/dist init: [mkdir] Created dir: /Users/sylvain/ProjetBanque/build [mkdir] Created dir: /Users/sylvain/ProjetBanque/dist compile: [javac] Compiling 2 source files to /Users/sylvain/ProjetBanque/build dist: [jar] Building jar: /Users/sylvain/ProjetBanque/dist/app.jar BUILD SUCCESSFUL Total time: 4 seconds
Un coup d'oeil dans le manifeste de l'archive nous confirme que la classe principale est bien indiquée:
sh$ cd dist sh$ jar xf app.jar META-INF/MANIFEST.MF sh$ cat META-INF/MANIFEST.MF Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7.0 Created-By: 1.3.1_03-74 ("Apple Computer, Inc.") Main-Class: fr.esicom.exemples.Banque
Maintenant que cette information est présente, l'interpréteur java peut exécuter le programme stocké dans l'archive:
sh$ java -jar app.jar Le solde du compte est de 1800.0
Et voilà! Nous disposons d'une archive qui contient tous les fichiers nécessaires pour faire fonctionner notre application. Pour la diffuser ou la déployer, il suffit maintenant de fournir le fichier app.jar.
De plus, comme l'archive est générée par Ant, reconstruire l'archive tout en s'assurant qu'elle contiendra bien la toute dernière version des fichiers compilés se fait simplement en tapant ant dist à l'invite du shell.