ANT - Web Services 33

publicité
Université du 7 Novembre à Carthage
Année universitaire 2006/2007
Institut National des Sciences Appliquées et de Technologie
I.N.S.A.T
Atelier de Génie Logiciel Avancée :
ANT
INTRODUCTION :
Dans cet Atelier nous allons présenter
possibilités de ant.
un jeu d’activités illustrant les différentes
INSTALLATION :






Télécharger la distribution binaire de ant (www.ant.apache.org).
Dé zipper le fichier apache-ant-1.6.5-bin.zip (un répertoire jakarta-ant-version est
créer, contenant l'outil et sa documentation) .
Ajouter le chemin complet du répertoire bin de Ant à la variable système PATH
(pour pouvoir facilement appeler Ant n’ importe où dans l'arborescence du
système).
S'assurer que la variable JAVA_HOME pointe sur le répertoire contenant le JDK.
Créer une variable d'environnement ANT_HOME qui pointe sur le répertoire
jakarta-ant-version créé lors de la décompression du fichier.
Il peut être nécessaire d'ajouter les fichiers .jar contenus dans le répertoire lib de
Ant à la variable d'environnement CLASSPATH.
Exemple 1 : Hello World
Dans cet exemple nous allons développer un fichier « build.xml » qui affiche le message
« Hello World! »
Pour commencer nous allons créer un répertoire «d:/Ant_Projects/PR_HelloWorld »
sous lequel on crée le fichier « build.xml » suivant :
<?xml version="1.0"?>
<project name="Exemple1" default="SayHello" basedir=".">
<target name="SayHello">
<echo>Hello World!</echo>
</target>
</project>
L’exécution du contenu de ce fichier est assurée par la commande :
ant [options] [cible]
Dans notre cas, si on est placé dans le même répertoire où se trouve « build.xml » :
Ant –v
Sinon :
Ant –v –buildfile %PROJECT_PATH\build.xml
L’options –v (Verbose) est utilisé pour fournir un maximum d’information lors de
l’exécution tandis que l’option –buildfile est utilisé pour préciser le nom du fichier de
configuration
Nous aurons comme résultat :
Comme vous remarquez, Ant affiche les différentes étapes d’exécutions (grâce à l’option
-v) qui sont :
-
Détection de la version de java.
Détection du SE.
Parsing du fichier build.xml.
Initialisation du répertoire racine du projet.
Création des cibles (Dans notre cas «SayHello »).
Affichage du résultat d’exécution des différentes cibles et de leurs tâches
correspondantes.
La plupart des IDE Java dispose de plugins pour utiliser ANT et c’est le cas pour Eclipse.
Exécuter ANT à partir d'un IDE permet de bénéficier de fonctionnalités supplémentaires
par rapport à un script :



Vision synthétique de l'ensemble des cibles disponibles, avec leur description.
Exécution d'une cible d'un simple clic de souris ou d'un raccourci clavier.
Possibilité de suspendre temporairement l'exécution.


Présentation de rapports d'exécution plus facilement exploitable (lien vers le code
source, gestion en arborescence, possibilité de changer de niveau de log à
posteriori, ...).
Aide à la gestion du CLASSPATH.
Reproduisons alors notre exemple sous eclipse. Pour cela il faut :



Créer un nouveau projet java.
Créer le fichier build.xml
Afficher la vue de Ant (Window>Show View>Ant).

Ajouter le fichier build.xml

Sélectionner le fichier et appuyer sur
pour exécuter.
Nous aurons ainsi le résultat suivant :
Exemple 2 : Hello World
Dans cet exemple nous allons créer un projet dans lequel il y’aura une
classe « HelloWorld» (qui affiche un message « HelloWorld! ») et notre fameux fichier
« build.xml ». La tâche de ce fichier XML consiste à :


Créer, s’il n’existe pas, un répertoire intitulé « output ».
Compiler la classe et placer le fichier « HelloWorl.class » généré dans le
répertoire « output ».


Créer un fichier « Hello.jar » et le placer sous le répertoire « output ».
Exécuter la classe compilée.
Le fichier « build.xml » présente le code suivant :
<project name="hello" default="Execute">
<!-- Définition du classpath du projet-->
<path id="projet.classpath">
<pathelement location="./output/hello.jar" />
</path>
<!--Création du répertoire output-->
<available property="output.exists" file="./output"/>
<!--Si le répertoire n'existe pas alors création-->
<target name="Prepare" unless="output.exists">
<mkdir dir="./output" />
</target>
<!--Sinon Afficher message-->
<target name="RepExist" if="output.exists">
<echo message="Le répertoire output existe déja" />
</target>
<!--Compilation de la classe-->
<target name="Compile" depends="Prepare,RepExist">
<javac srcdir="." destdir="./output" />
</target>
<!--Création du fichier hello.jar-->
<target name="Packaging" description="Création du hello.jar" depends="Compile">
<jar destfile="./output/hello.jar">
<zipfileset dir="output" includes="HelloWorld.class"/>
</jar>
</target>
<!--Exécution de la classe compilé-->
<target name="Execute" depends="Packaging">
<java classname="HelloWorld" fork="true">
<classpath refid="projet.classpath"/>
</java>
</target>
</project>
Après avoir ajouter le fichier « build.xml » à la vue « Ant » nous aurons :
Cette vue nous permet d’avoir une vision claire de notre fichier de configuration. En fait
« built.xml » est constitué de cinq cibles (ou targets) que nous pouvons classer en trois
groupes :
 Cibles de Préparation du répertoire destination : Prepare,
RepExist
Ces deux cibles ont pour objectif de créer, s’il n’existe pas, un répertoire « output »,
sinon afficher le message « Le répertoire output existe déjà ».
Le tag <available> permet de tester si le répertoire output existe ou pas, si oui la
propriété « output.exists » serait égale à true sinon false.
Selon la valeur de « output.exists » le target « Prepare » ou « RepExist » sera exécuté.
En effet, dans le target « Prepare » nous avons l’attribut unless donc cette cible serait
exécutée en l’absence du répertoire « output » sinon le target PrepareExist (doté de
l’attribut « if ») serait exécuté et afficherait le message « Le répertoire output existe
déjà ».
 Tâches de Préparation des fichiers nécessaires : Compile,
Packaging
Le rôle de ces deux tâches est de créer le fichier « Hello.class » ainsi que le
« hello.jar » qui sera nécessaires après pour l’exécution.
Dans la cible (target) « Compile » la compilation de « Hello.java » est réalisé par la
tâche <javac>. Cette tâche va compiler toutes les sources présentes dans le répertoire
racine du projet. Les « .class » générés seront placés dans le répertoire « output ». Donc
avant de compiler il faut que le répertoire destination soit créer, ce qui explique la
présence de l’attribut « depends » dans la cible « Compile ». En fait cet attribut exige
que les tâches « Prepare » et « RepExist » soient exécutées avec succès avant
d’entamer l’exécution des tâches du target « Compile ».
A condition que le target « Compile » soit exécuté avec succès (depends= ’Compile’ ),
la cible « Packaging » va créer le « hello.jar », cela par l’intermédiaire du task <jar>,
dans lequel nous avons spécifié l’emplacement du fichier à créer et les « .class » qui
seront archivés.
 Tâche d’exécution : Execute
Dans cette tâche nous allons exécuter la classe « Hello » déjà compilé.
Avant exécution, il faut tout d’abord ajouter au classpath les différentes ressources
nécessaires (dans notre cas « hello.jar »). Ceci est assuré par le tag <path> qui, à travers
le sous tag <pathelement> va définir le « .jar » qui sera ajoutée à la variable classpath
d’exécution. Donc l’exécution dépend de la tâche « Packaging ». Pour cela on trouve
l’attribut depends égale à « Packaging » dans la cible « Execute ».
La tâche « Execute » est assurée par le task <java> dans lequel nous avons spécifiés le
nom de la classe à exécuter. L’attribut fork égale à « true» mentionne que l'exécution se
fait dans une JVM dédiée au lieu de celle ou s'exécute « Ant ».
La définition du classpath à utiliser lors de l’exécution est réalisée par le tag fils
<classpath>.
Le résultat obtenu après exécution du build.xml :
Comme vous remarquez « Ant » commence par créer le répertoire output, ensuite
compiler le fichier « hello.java », puis créer l’archive JAR et enfin exécute la classe qui
affiche le message « Hello World ».
La tâche PrepareExiste ne s’est pas exécutée car le répertoire « output » n’existe pas.
Si on exécute une autre fois le fichier build.xml nous aurons :
Vous remarquez donc que les tâches Prepare, Compile et Packaging ne se sont pas
exécuté puisque le répertoire « output » existe déjà ainsi que « Hello.class » et
« hello.jar ».
La tâche PrepareExist s’est exécutée car le répertoire « output » existe déja.
Exemple 3 : Construction d’Application J2EE
(Calculette)
La construction d’application J2EE est l’utilisation principale de Ant. L'intérêt d'un
module de construction au sein d'une application est de garantir à tout moment une
livraison fiable de l'application sous sa forme finale (.jar, .war, .ear, …) à partir de ses
sources, voire son déploiement sur un serveur. Quand l'application est sensible, il devient
inconcevable de réaliser l'installation manuellement en raison des risques d'oubli de
livraison de fichiers ou d'opérations diverses (eg. adaptation des propriétés de
configuration, correction des caractères spéciaux CR/LF, …). Le gain de temps apporté
par une installation automatisée est également un facteur primordial, surtout quand le
mode de développement choisi requiert un rythme d'intégration élevé (cf. processus
d'intégration continue de la méthode Extreme Programming).
Dans cette exemple nous allons découvrir les différentes facilités offertes par ANT dans
le développement d’application J2EE.
L’application J2EE que nous allons construire est composé de :

Une page d’accueil « Index.html » qui présente un formulaire demandant la
saisie de deux nombre.

Une Servlet « CalculatriceServlet » qui va faire appel à un Session Bean pour
calculer la somme des deux nombres saisies dans la page d’accueil.

Un Session Bean « CalculBean » qui va s’occuper de la tâche de calcul de la
somme.

L’interface Home et Remote de Bean Session.

Fichiers XML de configuration.
Vue du projet sous eclipse :
Remarque :
-
Pour le développement de cet application, nous avons choisie JBoss
comme conteneur d’EJB.
Dans cet exemple, Nous n’allons pas expliquer comment créer les
différents composants, mais plutôt comment utiliser Ant pour automatiser
la construction de l’application.
STRUCTURE DU FICHIER DE CONFIGURATION ANT :
La construction de l’application avec Ant consiste à créer le fichier « build.xml » dont la
structure est la suivante :
Donc la construction consiste principalement à compiler nos ressources (Servlets,
EJBs…), ensuite créer les archives JAR, WAR et EAR et enfin déployer l’application sur
le serveur.
 Déclaration des propriétés :
Le tag <property> permet de définir une propriété qui pourra être utilisée dans le projet :
c'est souvent la définition d'un répertoire ou d'une variable qui sera utilisée par certaines
tâches. Leur définition en tant que propriété permet de facilement changer leur valeur une
seule fois même si la valeur de la propriété est utilisée plusieurs fois dans le projet.
Exemple la propriété « lib.Dir » a comme valeur le répertoire contenant les fichiers JAR
nécessaires pour la compilation.
 Initialisation :
La cible « init » commence par supprimer les fichiers générés suite à une exécution
antérieur du fichier « build.xml ». Après suppression un répertoire « bin » sera crée.
Notons ici l’utilisation des propriétés « output.Dir » et « deploy.Dir » qui ont pour
valeurs respectivement «bin » et «D:\Program Files\jboss4.0.4.GA\server\default\deploy\ ».
 Compilation :
Dans cette phase nous allons compiler les fichiers sources (EJB et Servlet).
La cible « compile » qui dépend de la cible « init » va compiler les fichiers présents dans
le répertoire source « src » (spécifié par la propriété « source.Dir »). Les « .class » seront
placés dans le répertoire « bin » (spécifié par la propriété « source.Dir »).
Les ressources utilisées dans la compilation sont les fichiers « .jar » présents dans le
répertoire défini par la propriété « lib.Dir ».
 Packaging :
CalculEJB.jar :
La création de « CalculEJB.jar » est réalisée après la compilation des différentes
classes.
Ce fichier d’archive contiendra les fichiers de configuration (« ejb-jar.xml » et
« jboss.xml ») ainsi que les « .class » du bean et ses interfaces qui se trouvent sous le
répertoire « bin ».
Il est annoté que les fichiers de configuration, qui se trouvent sous le répertoire
« src/META-INF », seront archivés sous le répertoire « META-INF » (prefix =
« META-INF »).
CalculWEB.war :
L’archive CalculWeb.war sera construit à partir de :



Fichiers XML de configuration (web.xml et jboss-web.xml) qui se trouvent sous
le répertoire « src/WEB-INF ». Le répertoire sous lequel seront archivés ces
fichiers est « WEB-INF ».
Servlet placée sous le répertoire « tutorial/web » et qui sera archivé sous le
répertoire « WEB-INF/classes ».
Fichiers placés sous le répertoire « docroot ».
CalculApp.ear :
C’est le dernier archive que nous allons générer il contient :

CalculEJB.jar et CalculWeb.war

Le fichier de configuration « application.xml » situé sous le répertoire
« src/META-INF » et qui sera archivé sous le préfix « META-INF ».
 Déploiement :
La phase de déploiement consiste à copier le fichier « CalculApp.ear » sous le
répertoire de déploiement du serveur. Dans notre cas « D:\Program Files\jboss4.0.4.GA\server\default\deploy\ ».
Vérifions maintenant le bon déroulement de l’exécution du « build.xml » :
Exemple 4 : Création de tasks Ant
Personnalisables
Dans cet exemple nous allons créer une tâche Ant qui va générer un fichier personnalisé.
Ce dernier va être utilisé par une autre application comme étant un fichier de
configuration dans lequel nous trouverons les informations concernant les utilisateurs.
Ces informations seront de type « Object ».
Voici un exemple d’utilisation du task développé :
Comme vous remarquez, il faut définir :

D’abord, la tâche personnalisé, cela en précisant dans le task <taskdef> le nom de
la tâche, le nom de sa classe et l’emplacement exacte du fichier compilé (.class)
qui sont dans notre cas, respectivement « Config », « Custom_Config » et le
répertoire racine du projet.

Ensuite, les différents attributs de notre task : Dans cet exemple, le fichier de
configuration généré sera intitulé « out.txt ». Ce fichier sera placé sous le
répertoire « D:\Ant_Projects\ANT_CUSTOM_TAG ».
Puis, les nœuds qui représentent les différents utilisateurs.

Pour la création du task, il faut d’abord commencer par créer la classe :
Custom_Config.java :
import org.apache.tools.ant.BuildException;
import java.io.*;
import java.util.*;
public class Custom_Config extends org.apache.tools.ant.Task{
private String APPDir = null;
private ArrayList nodes = new ArrayList();
private String outputfile = null;
public void setAPPDir(String APPDir) {
this.APPDir = APPDir;
}
public void setOutputfile (String outputfile) {
this.outputfile = outputfile ;
}
public void execute() throws BuildException {
FileOutputStream fo = null;
ObjectOutputStream oo = null;
try {
fo = new FileOutputStream(APPDir + "/"+outputfile);
oo = new ObjectOutputStream(fo);
oo.writeObject(nodes);
oo.close();
fo.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void addConfiguredUser(User n) {
nodes.add(n);
}
}
La classe « Costum_Config » hérite de la classe « org.apache.tools.ant.Task ». Elle est
constitué de :




Les différents attributs qui seront spécifiés après dans l’appel de la tâche.
Les Méthodes Setters des attributs de la tâche.
La méthode execute() qui présente le cœur de la tâche à créer. Dans cette
méthode il y a création du fichier de configuration et stockage des noeuds du task
(Les informations concernant les utilisateurs).
La méthode addConfiguredUser(User n) : Ant exécute cette méthode chaque
fois qu’il rencontre un nœud. A chaque exécution le nœud rencontré va être ajouté
à l’objet « nodes » de type ArrayList.
Les informations que contiennent les nœuds seront stockées dans une classe User
Serialisable.
import java.io.*;
public class User implements Serializable {
private static final long serialVersionUID = -259332824550744321L;
private int id = 0;
private String username;
private String password;
public void setID(int id) {
this.id = id;
}
public void setUsername(String username) { this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public int getID() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
Cette classe est constitué des :
 Attributs du noeud user.
 Méthodes Getter et Setter correspondant à ces attributs.
Testons maintenant notre task :
Après exécution un fichier « out.txt » serait généré. Pour tester que les données
stockés sont bien les données spécifiés dans le fichier XML, nous avons réalisé un
petit programme qui va lire le fichier généré et extraire les données qu’il contient.
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class Recup_Conf {
private static ArrayList nodes = new ArrayList();
public static void main(String[] args) {
FileInputStream fo = null;
ObjectInputStream oo = null;
try {
fo = new FileInputStream("out.txt");
oo = new ObjectInputStream(fo);
nodes=(ArrayList) oo.readObject();
for (int i=0 ; i<nodes.size();i++)
{ User n=(User) nodes.get(i);
System.out.println("ID : "+n.getID()+"\nUser Name :
"+n.getUsername()+"\nPassword : "+n.getPassword());
System.out.println("------------------------------------------------------------");
}
oo.close();
fo.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Voici le résultat d’exécution de ce programme :
Téléchargement