Prérequis
De nombreux prérequis sont nécessaires pour pouvoir faire les exercices et suivre le cours. La figure suivante vous permet de situer dans quelle partie du développement web vous travaillez.

Les minimums de l'administration système¶
Rappels Système S1¶
Plusieurs outils manipulés pour faire du Java EE lisent leur configuration dans des variables d'environnement. Il faut donc savoir manipuler les variables d'environnement.
- Les variables sont stockées dans le ficher
~/.bashrc - Une variable est lue en préfixant son nom par
$(ex.echo $HOMEaffiche le contenu de la variable$HOME) - La valeur d'une variable est spécifiée avec la syntaxe
export VARIABLE="LES VALEURS"sans espaces avant/après le = - Lorsqu'une variable contient une liste de chemins (comme
PATH), ces chemins sont séparés par le caractère: - La modification du
.bashrcn'est pas prise en compte instantanément ; il faut soit ouvrir un nouveau terminal, soit fairesource ~/.bashrc
Variables à connaître¶
HOME: répertoire personnel de l'utilisateur (ne saisissez jamais le chemin manuellement)JAVA_HOME: répertoire d'installation de la machine virtuelle JavaPATH: liste des chemins parcourus par le shell lors de sa recherche d'exécutables
Vous pouvez créer des alias de commande à l'aide de la syntaxe alias nom="la commande a executer"
Java 7 (minimum)¶
Au fil du temps, Java évolue pour être plus puissant
et agréable à utiliser. Les évolutions suivantes sont nécessaires
pour le Java moderne :
Utilisation d'annotations¶
- Structuration des sources
- Code source
Fichier DeprecatedAnnotationSample.java qui utilise une annotation qui indique la dépréciation de méthodes :
package fr.iut;
/**
* This class declares a deprecated method.
*/
public class DeprecatedAnnotationSample {
/**
* @deprecated
* explanation of why deprecatedMethod() was deprecated
*/
@Deprecated
public void deprecatedMethod() {
System.out.println("calling deprecatedMethod is deprecated");
}
/**
* explanation of nonDeprecatedMethod()
*/
public void nonDeprecatedMethod() {
System.out.println("calling nonDeprecatedMethod is well supported");
}
}
Fichier Main.java qui utilise les méthodes dépréciées :
package fr.iut;
/**
* Main entry point for demo
*/
public class Main {
public static void main(String[] args) {
DeprecatedAnnotationSample sample = new DeprecatedAnnotationSample();
sample.deprecatedMethod();
sample.nonDeprecatedMethod();
}
}
- Commandes de compilation et d'exécution
mkdir -p target/classes
cd src && javac -d ../target/classes fr/iut/*.java
cd .. && java -classpath target/classes fr.iut.Main
Exercice (15 min)
Objectif : Comprendre la construction d'un projet java. Coder les 2 classes (Main et DeprecatedAnnotationSample) et utiliser javac et java en ligne de commande.
- créer les deux classes (attention à l'organisation dossier/package)
- compiler manuellement sans utiliser d'IDE
javac... - exécuter manuellement sans utiliser d'IDE
java... - observer l'impact des annotations (voir le warning)
Types Génériques et boucles for-each¶
Equivalent des template en C++, ils évitent le recours à java.lang.Object et au casting
// Sans génériques
List oldNames = new ArrayList(); // Conteneur objets quelconques
oldNames.add("Jean");
oldNames.add("Raoul");
Iterator i = oldNames.iterator(); // Boucles objets avec itérateurs
while (i.hasNext()) {
String name = (String)i.next(); // Conversion nécessaire
System.out.println(name);
}
// Avec génériques
List<String> names = new ArrayList(); // Conteneur String
names.add("Bobine");
names.add("Ducable");
for (String name : names) { // Boucle String sans itérateurs
System.out.println(name);
}
Autoboxing / Unboxing¶
Les types primitifs ne peuvent pas être manipulés comme des objets.
Il faut donc les encapsuler pour les manipuler comme des objets grâce à leur proxie.
Cependant, sans autoboxing et unboxing la manipulation de ces proxies est fastidieuse.
Integer i = new Integer(9); // Création manuelle du proxie
Integer l = 9; // Création automatique du proxie (autoboxing)
Integer k = new Integer(4);
int l = k.intValue(); // Récupération manuelle de la valeur
int m = k; // Récupération automatique de la valeur (unboxing)
L'outillage¶
Gestionnaire de projet Java - Maven¶
Les projets Java EE sont relativement complexes et comportent de nombreuses
dépendances.
maven est un outil, parmi tant d'autres, qui permet de simplifier la gestion des projets java en adoptant la devise convention over configuration (tant que vous ne spécifiez pas le contraire, vous devez respecter un formalisme précis):
- Il génère automatiquement le squelette
standardd'un projetjava -
Il construit le programme final (compilation + archivage)
-
préparation de la construction
- nettoyage
- identification de l'emplacement du code source
- identification de la destination
- identification transitive des dependances
- téléchargement et mise en cache des dépendances
- construction des options de la compilation
- compilation
- test unitaires
- packaging (JAR, WAR, EAR)
- L'architecture en
plugindemavenfacilite l'intégration d'un grand nombre d'utilitaires (cf. plus bas JUnit, Cobertura, etc.)
-
Voici quelques commandes utiles (à retenir) :
mvn archetype:generatepour créer l'arborescence d'un projetmvn compilepour compiler un projetmvn testpour lancer les tests unitairesmvn packagepour générer l'archive du projetmvn cleanpour supprimer les fichiers générésmvn sitepour générer le site (Javadoc, etc.) du projet ainsi que différents reports (Tests unitaire, Couverture, etc.)-
mvn assembly:assemblypour construire le projet final distribuable.La page http://maven.apache.org/guides/getting-started/index.html est une courte introduction à maven et contient tout ce que vous avez besoin dans ce TD (vous devez la lire pour la séance suivante).
- BONUS La configuration de
bashà l'IUT vous permet bénéficier de l'autocomplétion des arguments de maven à l'aide de la touche<tab>. - MALUS1 La version de
maveninstallée à l'IUT est obsolète ; il est nécessaire que vous installiez votre propre version sur votre compte (ou /tmp si vous automatisez son téléchargement/installation). - MALUS2
maven(tout comme eclipse/intellij/android studio) télécharge beaucoup de données. Vous devrez faire de la place sur votre compte pour ne pas dépasser votre quota. Convernantmaven, le cache est dans le dossier~/.m2. - MALUS3 La configuration
mavenobsolète de l'IUT force à utiliser un dépôt sur un répertoire en lecture seule. Simavenrefuse de télécharger les dépendences, c'est que cette configuraiton est activée sur votre compte. Supprimez le dossier~/.m2pour résoudre le soucis.
Exercice
Objectif : Configurer les variables d'environnement (impératif pour ne pas perdre de temps aux prochaines séances!) et créer un premier projet Maven
Installer Maven sur votre compte personnel¶
- Télécharger sur le site https://archive.apache.org/dist/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gz le binaire de la version 3.5.2 (dans les archives).
- Décompresser le dans le dossier
~/opt. - Vérifier les pré-requis (
JAVA_HOMEspécifié etjavadans le$PATH) ; corriger le.bashrcsi besoin. - Modifier le
$PATHpour rajouter la commandemvn. - Vérifier son bon fonctionnement.
$ echo $JAVA_HOME ; java -version ; mvn -version
/opt/oracle-jdk
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T09:58:13+02:00)
Maven home: /mnt/roost/users/rgiot/opt/apache-maven-3.5.2
Java version: 1.8.0_181, vendor: Oracle Corporation
Java home: /opt/jdk1.8.0_181/jre
Default locale: fr_FR, platform encoding: UTF-8
OS name: "linux", version: "4.18.0-0.bpo.1-amd64", arch: "amd64", family: "unix"
- Après la configuration, le
.bashrcdevrait contenir les instructions suivantes :
export MVN_HOME=~/opt/apache-maven-3.5.2
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
export PATH=$JAVA_HOME/bin:$MVN_HOME/bin:~/.local/bin/:$PATH
- Dans un nouveau dossier de travail (
~/cours/javaee/prerequis), créer le premier projet à l'aide de la commandemvn(penser à l'autocomplétion) - Si la commande précédente a échoué, c'est que maven essaye d'installer les fichiers dans un répertoire auquel vous n'avez pas accès. Supprimez son dossier de configuration, le problème devrait être résolu (il est possible que ce problème soit récurrent en chaque début de séance).
- Aller dans le projet
exo2nouvellement créé et le construire - Créer un dépôt git pour la matière dans
~/cours/javaeeet y ajouter les fichiers sources. Ayez le réflexe de :- toujours ajouter les fichiers sources - jamais ajouter les fichiers générés - commiter régulièrement votre travail avec des messages informatifs - faire des tags en fin de séance pour suivre votre avancement
ATTENTION Avec Java EE et la programmation mobile vous risquez de remplir rapidement vos quotas. Il faudra surement qu'en fin de séance progmobile vous effaciez les dossiers générés par Android Studio et gradle et qu'en fin de séance Java EE vous effaciez les dossiers générés par maven.
Environnement de Développement Intégré pour Java¶
Bien qu'un simple éditeur de texte suffise pour faire du Java EE, il est préférable d'utiliser un IDE de qualité afin d'accélérer le développement.
Dans le cadre de ce TD, nous avons choisi IntellijIdea1 qui est une alternative à Eclipse. A souligner que l'intégration de maven dans IntelliJ est bien plus performante que dans Eclipse3.
À l'IUT, l'exécutable est idea.
Exercice
Objectif : Apprendre à utiliser l'IDE et la documentation. À l'aide de l'IDE, développer une classe utilitaire qui produit une chaîne localisée de montant à partir d'un double et de la locale.
- Nous allons à présent ouvrir le projet précédemment (exo2) créé avec
MavendansIntelliJ(les screenshots correspondent à une version différente, mais le principe reste très similaire). Il faut dansIntelliJcréer un nouveau projet à partir de source existantes (ensuite il faudra indiquer qu'il s'agit d'un projetMaven). - Créer la nouvelle classe
StringUtil - Ajouter la méthode
prettyCurrencyPrintdont voici le prototype : Voici un exemple d'utilisation de la méthode :
Dont la valeur renvoyée est 21 500,39 €.
Astuce : Jettez un œil à la classe Java NumberFormat et particulièrement la méthode getCurrencyInstance et 'format`. 2
- Ne pas oublier la Javadoc
Les tests unitaires¶
JUnit4 est un framework Java pour la mise en place de tests unitaires (rappelez vous de BOOST en C++).
L'utilisation de tests unitaires est primordiale lors du développement d'application Java EE en raison de leur complexité et de la grande difficulté de correction de bugs s'ils sont détectés trop tard. Elle fait même l'objet d'une méthodologie de développement, le TDD, Test Driven Development, où le développement du test unitaire est préalable au développement de la fonction métier.
Ne pas utiliser de test unitaire pour vérifier son code peut être considéré comme étant une faute professionnelle.
L'emplacement et l'environnement d'exécution des tests sont déjà prévus dans la template Maven.
- dossier
src/test/java - dépendance JUnit dans le
pom.xml
Exemple de test :
package com.example.foo;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/**
* Tests for {@link Foo}.
*
* @author user@example.com (John Doe)
*/
public class FooTest {
@Test
public void thisAlwaysPasses() {
assertTrue(true);
}
}
Exercice
Objectif : Apprendre à implémenter des tests unitaires. Mise en place de tests unitaires associé(s) au code précédent.
- Créer la classe
StringUtilTestdans le dossier approprié - Proposer une implémentation de test unitaire de la fonction
- Ajouter le test au dépôt.
- Exécuter le test unitaire depuis
IntelliJ - Déboguer le test unitaire depuis
IntelliJ(Il y a 99% de chances que votre implémentation de test unitaire soit mauvaise. Installer un point d'arrêt et observer les variables vous aidera à comprendre pourquoi). - Exécuter le test unitaire depuis la ligne de commande (
mvn test) etmvnqui doit retourner -si tout va bien- quelque chose comme ça :
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ exo2 ---
[INFO] Surefire report directory: /Users/fred/workspace_iut/teaching.s4_jee/00_Prerequis/exo2/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running fr.iut.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.046 sec
Running fr.iut.StringUtilTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.312s
[INFO] Finished at: Mon Feb 09 21:29:13 CET 2015
[INFO] Final Memory: 13M/247M
[INFO] ------------------------------------------------------------------------
Dans la suite du sujet nous ne spécifierons pas la nécessité d'ajouter des fichiers/commiter. À vous d'avoir le réflexe.
Limites¶
La mise en place de vrais tests unitaires est moins simple qu'il n'y parait en raison de différents points :
- L'exhaustivité des tests.
- La pertinence des tests à prouver (quid de tester des getter/setters ?).
- L'identification du périmètre à tester.
- L'isolation du test vis-à-vis des couches inférieures.
- L'environnement de test autonome et équivalent d'une exécution à l'autre.
L'utilisation de mock objects facilite l'isolation des couches en simulant et facilitant la vérification du comportement des objets développés.
Mockito est un framework qui facilite l'utilisation des mock objects. Plus de détails ici : http://blog.soat.fr/2013/07/mockito-ou-comment-faciliter-lecriture-de-tests-unitaires/
Autres tests¶
Enfin, il convient de distinguer :
- les tests unitaires (unit testing)
- les tests fonctionnels (functional testing)
- les tests d'intégration (ingration testing)
Couverture de tests unitaires¶
Les outils de mesure de la couverture des tests permettent d'identifier les parties du code qui échappent aux tests. Bien souvent, on a tendance à ne tester que les cas passants laissant intactes une bonne partie du code.

Cobertura et Jacoco sont des outils open source qui facilitent la mise en œuvre de la mesure de la couverture des tests unitaires.
Dans le cadre des TP nous allons utiliser Jacoco
Exercice
Objectif : Mesurer le taux de couverture des tests unitaires.
- modifier le
pom.xmlpour intéger automatiquement Jacoco à l'exécution des tests unitaires
<project ...>
<build>
<plugins>
...
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<!-- Précise que le plugin s'executera lors du cyle maven "verify" -->
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
</project>
- Lancer la vérification du projet et la génération du rapport grace à Maven
target/site/jacoco/index.html
1. compléter la couverture si nécessaire
Complément de lecture https://www.jacoco.org
À retenir (non exhaustif)¶
- Les variables d'environnement Linux, modification du fichier
~/.bashrc - Les commandes de bases de Maven et leur utilité
- Le rôle du fichier
pom.xmldans un projet Maven - L'architecture de base d'un projet Maven (rôle des répertoires :
site,src,target,test, ...), structuration du répertoiresrc. - L'utilité de Jacoco
- La création d'un projet Maven spécifique aidé de l'example suivant :