====== Prise en main de Maven, Mercurial et Redmine ====== Ce TP est à réaliser de préférence sous Linux (accès à ''mvn''((pour maven)) et ''hg''((pour mercurial)) en ligne de commande). L'utilisation d'IDEs est interdite pour ce TP. On éditera les fichiers via gedit/kate/notepad++/emacs/vim, etc. Warning SSL: voir la [[http://forge.univ-lyon1.fr/projects/forge/wiki/FAQ|FAQ de la forge]] === Maven === Il est important de configurer correctement maven: [[enseignement:aide:logiciels#maven|voir l'aide]]. Sous linux: si maven n'est pas installé: Ajouter le répertoire suivant à votre PATH: export PATH=$PATH:/home/tpetu/Enseignants/emmanuel.coquery/binetu Ou bien télécharger [[http://mirror.bbln.org/apache/maven/maven-3/3.2.3/binaries/apache-maven-3.2.3-bin.tar.gz|apache-maven-3.2.3-bin.tar.gz]] et extraire l'archive dans /tmp. Ajouter /tmp/apache-maven-3.2.3/bin dans votre PATH: cd /tmp wget http://mirror.bbln.org/apache/maven/maven-3/3.2.3/binaries/apache-maven-3.2.3-bin.tar.gz tar xzf apache-maven-3.2.3-bin.tar.gz export PATH=/tmp/apache-maven-3.2.3/bin:$PATH cd ===== Démarrage ===== Créer un nouveau projet sur la forge (http://forge.univ-lyon1.fr -> Projets -> Nouveau Projet). Si vous vous connectez pour la première fois, le système vous permettra de vérifier/modifier les informations qui vous concernent, idem pour votre éventuel binôme. Ajouter ce dernier comme développeur de votre projet (Configuration -> Membres) Clonez votre dépôt mercurial dans un répertoire ''work1''. L'URL de votre dépôt est accessible dans Redmine depuis votre projet via Configuration -> Dépôt: hg clone https://......... work1 Se placer dans le répertoire ''work1'' et récupérer des modifications depuis le projet ''inf1006m-mmr'': hg pull https://forge.univ-lyon1.fr/hg/inf1006m-mmr puis mettre à jour à la dernière version hg update Ce projet est constitué d'un projet maven (nommé ''base'' dans le fichier pom.xml) contenant un module nommé ''bonjour'', ce dernier étant lui aussi un projet maven. Par la suite on nommera ''base'' le projet à la racine du répertoire de travail et ''bonjour'' le sous-projet de l'application/module bonjour. Reverser cette mise à jour dans votre projet forge: hg push Dans le navigateur, naviguer dans le dépôt: vous pouvez voir les révisions déjà présentes et même regarder le code source en ligne, ainsi que les différences entre les révisions. ===== Invocation de maven ===== Regarder le code de la classe ''bonjour.App'' du module ''bonjour'' (bonjour/src/main/java/bonjour/App.java). Invoquer mvn compile à la racine du projet ''base'' (répertoire work1) et constater que la construction du projet ''bonjour'' est bien déclenchée. Le répertoire ''bonjour/target'' contient tout ce qui est généré par maven concernant le projet ''bonjour''. Explorer le contenu du répertoire, puis invoquer mvn clean Regarder ce qui a été supprimé. ===== Correction de code ===== Exécuter les tests unitaires:mvn test La construction échoue. Pour comprendre quelle est le problème, regarder le fichier ''bonjour/target/surefire-reports/bonjour.AppTest.txt'' Corriger la classe ''bonjour.App'' pour générer le bon message et passer le test unitaire. Vérifier que la construction complète passe: mvn install puis lancer l'application en ligne de commande: java -cp bonjour/target/bonjour-1.0-SNAPSHOT.jar bonjour.App S'il n'y a pas d'erreur, enregistrer((commit)) les modifications, puis poussez les vers votre dépôt: hg commit -m "un message explicatif ici" hg push Constater que les modifications sont visibles depuis site de votre projet forge. Si mercurial se plain que vous n'avez pas spécifié de nom d'utlisateur, deux choix: * Utiliser l'argument ''-u "mon nom "'' * Modifier votre configuration mercurial en ajoutant au fichier ''~/.hgrc'' ([[http://mercurial.selenic.com/wiki/QuickStart|doc]]) [ui] username = John Doe ===== hgignore et gestion d'un ticket ===== Depuis le projet forge, créer une nouvelle demande intitulée: "ignorer le répertoire target". Accéder à la liste des demandes de votre projet, puis à la demande précédente. Modifier cette demande en assignant un des membres du projet à cette tâche, passez son status à "In progress" et valider. Noter le numéro #xxxx de la demande. Dans le répertoire de travail, lancer hg status Il y a pleins de fichiers non gérés ((indiqués par ? )) sous le répertoire ''target''. Créer un fichier ''.hgignore'' à la base du répertoire de travail work1: syntax: glob target ce fichier contient la liste des fichiers à ignorer par mercurial. hg status n'affiche à présent plus les fichiers dans target, mais affiche le fichier ''.hgignore''. Ajouter ce fichier dans les fichiers versionnés: hg add .hgignore puis valider en indiquant le numéro de la demande #xxxx dans le message de commit: hg commit -m "Gestion des fichier à ignorer (bug #xxxx)" puis faire le push hg push Dans le projet forge, allez voir le dépôt et cliquez sur le dernier commit et ajouter une demande liée en spécifiant votre numéro de ticket. Cliquer ensuite sur le lien vers la demande depuis le message de commit. Passer le statut de la demande à "closed" en indiquant le numéro de la révision précédé de la lettre r((à priori r4)) ou le hash du commit précédé de ''commit:'' dans les notes de mise à jour((utiliser la prévisualisation pour vérifier que les liens sont correctement faits)). ===== Gestion de branches et de conflits ===== ==== Work2: commons-cli ==== Cloner à nouveau votre projet dans un deuxième répertoire de travail ''work2''. hg clone https://..... work2 Ajouter la dépendance vers apache-commons-cli au bon endroit dans le pom.xml du projet ''bonjour'': commons-cli commons-cli 1.2 Consulter la [[http://commons.apache.org/proper/commons-cli/usage.html|documentation]] et utiliser la bibliothèque commons-cli pour ajouter un argument en ligne de commande correspondant au nom de la personne à saluer. Le traitement des options se fera dans une méthode ''public void init(String [] args)'' de la classe Bonjour. Dans le main l'appel ''app.setPersonne("Toto")'' sera remplacé par un appel à ''app.init(args)''. Utiliser un ''new BasicParser();'' Le package de commons-cli est ''org.apache.commons.cli'' L'exécution via le jar comme précédement ne fonctionne plus. A la place on peut utiliser la commande suivante depuis le projet ''bonjour'': mvn exec:java -Dexec.mainClass=bonjour.App L'affichage se fait bien ... mais est perdu dans les logs. Nous verrons plus loin comment fabriquer un .jar contenant les dépendances. Pour passer les arguments en ligne de commande, ajouter ''-Dexec.args="-foo bar"'', exemple: mvn exec:java -Dexec.mainClass=bonjour.App -Dexec.args="-u Titi" Valider les modifications: hg commit -m 'ajout de commons-cli' Ne pas faire de push à ce niveau ==== Work1: slf4j ==== Dans le répertoire ''work1'' (qui ne contient pas les modifications précédentes) ajouter au projet ''bonjour'' les dépendances vers [[http://www.slf4j.org/|slf4j]] et [[http://logback.qos.ch/|logback]]: * slf4j-api pour la compilation (et l'exécution) org.slf4j slf4j-api 1.7.5 Chercher ''logback-classic'' sur http://search.maven.org/ , sélectionner la version 1.0.13 et ajouter les informations de dépendances (visibles à gauche de la page). Ajouter ''runtime'' pour limiter l'inclusion de cette dépendance à l'exécution. L'utilisation de slf4j dans ses versions récentes nécessite une version de java >= 1.5 Ajouter à l'élément ''project'' du pom du projet bonjour le code suivant pour configurer le plugin de compilation: org.apache.maven.plugins maven-compiler-plugin 3.1 1.5 1.5 Modifier la classe ''bonjour.App'' pour faire l'affichage via un logger slf4j (c.f. [[http://www.slf4j.org/manual.html|documentation]]). Valider les modifications hg commit -m 'affichage via slf4j' Utiliser ''mvn exec:java'' pour lancer votre application L'affichage diffère d'un System.out.println() ==== Work1: fusion des modifications ==== Toujours depuis le répertoire ''work1'', faire un pull des modifications du dépôt local ''work2'':hg pull ../work2 Mercurial se plain de l'apparition d'une nouvelle tête anonyme correspodant à une nouvelle branche. Lancer la fusion des deux branches avec hg merge Cette commande importe les modification de la branche crée lors du pull dans la branche courante. Cette modification créée des conflits sur la classe ''bonjour.App'' et sur le fichier ''pom.xml'' du projet ''bonjour''. ''hg status'' les signale comme étant modifiés avec la lettre ''M''. Editer ces fichiers pour intégrer de manière cohérente les modifications effectuées dans le deux branches. Une fois les modifications effectuées, si la construction ''mvn install'' fonctionne, indiquer ques les conflits sont résolus via hg resolve -m le_fichier_concerne (voir la [[http://mercurial.selenic.com/wiki/TutorialConflict|doc]]). Valider et transmettre les modifications: * Valider avec ''commit''. * Faire un push sur le dépôt de la forge. * Dans ''work2'', faire un pull depuis la forge * Dans ''work2'', faire un pull depuis ''work1'' et constater qu'aucune modification supplémentaire n'est transmise. * Dans ''work2'', faire ''hg update'' pour avoir une copie de travail à jour de la dernière version. ===== Packaging ===== Configurer le plugin ''maven-assembly-plugin'' pour générer un jar exécutable incluant les bibliothèques utilisées ([[http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven|voir ici]]). Tester en lancer java via java -jar target/bonjour-1.0-SNAPSHOT-jar-with-dependencies.jar ===== 2eme module ===== Lancer mvn archetype:generate depuis le projet de base. Utiliser les réponses par défaut aux 2 premières questions (numéro d'archetype et numéro de version). Pour les questions suivantes: * groupId: bonjour * artifactId: salut * version: 1.0-SNAPSHOT * package: salut * Y Cette commande créée un nouveau module ''salut''. Modifier le pom de salut pour y intégrer la partie ''build'' du pom de ''bonjour''. Ajouter une dépendance vers le projet bonjour dans le pom du projet salut. Renommer la classe salut.App en salut.Salut et modifier la mainClass dans la configuration du plugin d'assembly. Faire que la classe salut.Salut étende la classe bonjour.App en changeant le comportement de getMessage pour afficher Salut au lieu de Bienvenue. Changer le main de la classe salut.Salut pour imiter le comportement du main de bonjour.Bonjour, mais en utilisant un objet Salut. Lancer ''mvn clean'' puis ''mvn install'' depuis le projet base et constater que les projet sont construit suivant l'ordre de leur dépendances relatives((i.e. bonjour avant salut)). Vérifier que le jar avec dépendances de salut fonctionne correctement.