Rappels sur les éléments externes à Spring
Codage equals et hashCode
L’égalité entre objets est importante dans Spring, notamment pour les architectures utilisant Spring en conjonction avec un mapping objet-relationnel (en anglais Object-Relational Mapping ou ORM) comme Hibernate et JPA.
Il y a en effet, comme nous le détaillerons par la suite, dans Spring, Hibernate et JPA des notions de proxy. Quand nous aurons deux objets en mémoire, nous devrons faire attention à ne pas comparer un proxy avec l’objet qu’il proxyfie.
De même, deux objets pourront être identiques d’un point de vue métier alors qu’ils sont présents dans deux objets distincts en mémoire. Nous verrons que cet aspect est crucial lors de l’utilisation de collections.
Une définition selon Java nous présente ce que l’on attend des méthodes equals et hashCode. À partir de cette définition, nous verrons comment adapter ce concept pour une utilisation dans une architecture qui utilise massivement les proxy et les listes comme celle de Spring, JPA et Hibernate.
Dans ce chapitre, nous dirons le "equals" pour désigner la méthode equals et le "hashcode" pour désigner la méthode hashCode.
Une traduction approximative de la documentation officielle pour equals et hashCode est présentée ci-dessous.
equals
public boolean equals(Object obj)
Indique si un objet est égal à celui passé en paramètre.
La méthode equals implémente une relation d’équivalence entre deux références d’objets non nulles.
Elle est réflexive : pour toute référence d’une valeur non nulle x, x.equals(x) doit retourner true.
Elle est symétrique : pour toute référence d’une valeur non nulle x et y, x.equals(y) retourne true si et seulement si y.equals(x) retourne true.
Elle est transitive : pour toute référence d’une valeur non nulle x, y et z, si x.equals(y) retourne true et si y.equals(z) retourne true alors x.equals(z) doit retourner true.
Elle est consistante : pour toute référence d’une valeur non nulle x et y, de multiples invocations de x.equals(y) retournent toujours true ou de façon consistante toujours false, si aucune information fournie utilisée dans les comparaisons...
Projet Lombok
La librairie du projet Lombok (https://projectlombok.org/) simplifie beaucoup la conception des POC car elle minimise le code. La majorité de mes clients l’utilisent en production tout comme les exemples de code de cet ouvrage afin de réduire la taille du code. Il est très facile de l’enlever et d’utiliser les facilités de génération de code de son IDE (Integrated Development Environment ou environnement de développement intégré en français), c’est-à-dire en général Eclipse ou IntelliJ IDEA, et d’ajouter le cas échéant la déclaration du logger.
En effet, grâce à cette librairie nous pouvons utiliser des annotations qui injectent du code à la volée pour effectuer des tâches courantes comme les logs, les accesseurs, les constructeurs et bien d’autres choses utiles.
Pour utiliser la librairie du projet Lombok, il faut ajouter la dépendance dans le fichier pom.xml :
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
Si on utilise Eclipse, il faut ensuite patcher son environnement Eclipse, comme l’indique le site du projet Lombok. Pour cela, lancez le JAR de la librairie...
Les systèmes de log
Log4j, SLF4J et Logback
Nous avons utilisé durant de longues années, traditionnellement, le système de log Log4j pour la journalisation des messages d’information, de débug et d’erreur. Cependant, la nouvelle librairie Logback (http://logback.qos.ch/) est bien plus puissante que Log4j.
Avec Log4j, il faut faire attention aux problèmes de sécurité qui ont été détectés dans la version antérieure à la version 2.17.
Historiquement, la JCL (Jakarta Common Logging) fut une des premières API concurrentes mais elle restait très restreinte. Vers 2006, de gros projets comme Hibernate adoptèrent l’API SLF4J (http://www.slf4j.org/) ce qui la popularisa. Cependant, malgré de bons débuts, SLF4J n’a pas totalement éclipsé Log4j.
Pourtant, grâce à SLF4J, il est possible de centraliser dans un seul ensemble de fichiers de logs les appels qui sont faits par les différentes API de journalisation comme JCL, Log4j, JUL (http://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html)...
Les logs issus des appels aux API de logs sont alors regroupés et il devient possible de choisir quelle implémentation de journalisation utiliser. Contrairement à JCL qui charge les librairies à l’exécution avec le classloader, SLF4J choisit l’implémentation...
Bases de données H2
1. Description de la problématique
Il existe aujourd’hui beaucoup de bases de données relationnelles, dans le monde SQL, qui s’inscrivent dans des contextes d’utilisation très variés. Les versions commerciales les plus connues sont Oracle, DB2, SQL Server et Sybase. Il existe d’autres bases de données libres comme Derby, Firebird, HSQLDB, H2, Ingres, MariaDB, MySQL et PostgreSQL, pour ne citer que les plus connues.
Nous utiliserons souvent HSQLDB et H2 pour leurs possibilités d’utilisation très étendues. Cela nous permet en effet d’avoir la base de données SQL la plus simple possible pour faire une application légère et réaliser des tests. Ces bases peuvent s’exécuter en mémoire ou avec des fichiers, elles offrent des consoles pour effectuer des opérations sur la base et sont très frugales en termes d’occupation mémoire ou d’espace disque.
Nous travaillerons de préférence avec H2 qui apporte quelques avantages précieux comme le support de compatibilité SQL avec Oracle, DB2 et MySQL. Spring utilise, depuis les premières versions, en natif HSQLB pour nous aider à faire nos tests unitaires, mais nous verrons comment utiliser H2 à la place.
2. Mise en œuvre
a. Installation
Téléchargez la base de données...
Projets Maven
Le framework Java offre de base un JDK très fourni en API, ce qui permet de créer facilement des librairies et de les partager. De nombreuses librairies ont vu le jour.
Ces librairies utilisent d’autres librairies et nous nous retrouvons avec des dépendances. Les choses se compliquent quand nous avons par exemple deux librairies qui utilisent toutes deux d’autres librairies, mais dans des versions différentes. Le jeu consiste alors à trouver la bonne combinaison. L’ordre de chargement importe beaucoup aussi, car dans les serveurs JEE les librairies du serveur sont prioritaires sur les librairies de l’application.
Il est bien sûr possible d’inverser la priorité en chargeant en priorité les librairies de l’application avant celles du serveur, mais nous perdons alors le support du fournisseur du serveur d’application. Nous avons généralement un répertoire pour les librairies du serveur et un répertoire pour les librairies de chaque projet.
1. Description de la problématique
Au-delà d’un certain nombre de projets, une gestion des dépendances devient rapidement indispensable. De nombreux outils de gestion de dépendances essaient de répondre à ces problématiques. Nous utilisions au départ des makefiles qui furent remplacés par Ant (http://ant.apache.org/ : un makefile évolué) qui fut à son tour remplacé par Maven. Gradle (https://gradle.org/) est aussi utilisé mais plutôt pour les projets Android ou des projets nécessitant de la finesse au niveau des actions à effectuer avant, pendant et après les phases de build, test et packaging. Malgré le fait que le framework Spring utilise Gradle pour la gestion de ses dépendances en interne, nous utiliserons Maven dans les exemples du livre dans un objectif de simplification.
2. Mise en œuvre
Maven est compatible entre Windows, Mac et Unix (Linux). Il permet comme un makefile de produire des binaires et accessoirement de les packager à partir d’un ensemble de fichiers sources. Il utilise un concept nommé POM (Project Object Model) qui décrit un projet modulaire et les étapes nécessaires pour sa compilation, son test, son packaging, son installation et son déploiement.
Maven centralise...
Spring et les versions de Java
Les versions de Spring ont toujours été compatibles avec les versions de Java actives au moment de la publication de la version. Parfois, Spring était légèrement en avance.
Java
Année |
Version |
Fin de vie |
1995 |
JDK Beta |
|
... |
... |
|
Fev 2002 |
J2SE 1,4 |
Oct 2008 |
Sept 2004 |
Java SE 5 |
Nov 2009 |
Dec 2006 |
Java SE 6 |
Avr 2013 |
Juil 2011 |
Java SE 7 |
Juil 2019 |
Mars 2014 |
Java SE 8 (LTS) |
Dec 2030 |
Sept 2017 |
Java SE 9 |
Mars 2018 |
Mars 2018 |
Java SE 10 |
Sept 2018 |
Sept 2018 |
Java SE 11 (LTS) |
Sept 2026 |
Mars 2019 |
Java SE12 |
Sept 2019 |
Sept 2019 |
Java SE 13 |
Mars 2020 |
Mars 2020 |
Java SE 14 |
Sept 2020 |
Sept 2020 |
Java SE 15 |
Mars 2021 |
Mars 2021 |
Java SE 16 |
Sept 2021 |
Sept 2021 |
Java SE 17 (LTS) |
Sept 2029 |
Mars 2022 |
Java SE 18 |
Sept 2022 |
Sept 2022 |
Java SE 19 |
Mars 2023 |
Mars 2023 |
Java SE 20 |
Sept 2023 |
Sept 2023 |
Java SE 21 (LTS) |
Sept 2028 |
Spring
Année |
Version |
2003 |
1.0 |
2006 |
1.0 |
2009 |
3.0 |
Jan 2019 |
3.2 |
Dec 2020 |
4.3 |
9 dec 2020 |
5.0 |
2020 |
5.3 |
2017 |
5.0 |
2020 |
5.3 |
Dans le GitHub de Spring, il est spécifié pour les versions prises en charge :
La version 5.3.x est la dernière feature branch de la 5e génération et la dernière ligne de produit (GA à partir d’octobre 2020), avec un support à long terme fourni sur JDK 8, JDK 11 et JDK 17.
La version 5.2.x est la ligne de produit précédente (GA à partir de septembre 2019), qui sera activement prise en charge jusqu’à la fin de 2021.
Les versions 5.1.x et 5.0.x ne sont plus activement prises en charge, remplacées par 5.2.x et 5.3.x à partir de décembre 2020.
La version 4.3.x a atteint sa fin de vie (EOL) officielle le 31 décembre 2020. Aucun autre correctif de maintenance et de sécurité n’est prévu dans cette ligne.
La version 3.2.x a atteint sa fin de vie (EOL) officielle le 31 décembre 2016. Aucun autre correctif de maintenance et de sécurité n’est prévu dans cette ligne.
À ce stade, Spring nous recommande de mettre à niveau vers la dernière version de Spring Framework 5.3.x à partir de Maven Central.
Gamme de versions du JDK :
Spring Framework 6.0.x : JDK 17-21 (attendu)
Spring Framework 5.3.x : JDK 8-19 (attendu)
Spring Framework 5.2.x : JDK 8-15
Spring Framework 5.1.x : JDK 8-12
Spring Framework 5.0.x : JDK 8-10
Spring Framework 4.3.x : JDK 6-8
Spring teste et prend entièrement...
Points clés
-
Le framework Spring en version 5 demande au moins Java 8.
-
Les méthodes equals et hashCode doivent être adaptées pour une utilisation avec Spring, Hibernate et JPA.
-
Nous utilisons le projet Lombok pour économiser du code dans les exemples.
-
Nous utilisons Logback pour avoir de bons logs.
-
La base H2 est retenue dans les exemples pour sa simplicité d’utilisation.
-
Il faut suivre les montées de version pour minimiser la dette technique et contrer les failles de sécurité.
-
Nous utilisons Maven dans sa forme la plus simple pour les exemples.