Blog

Spring Boot 2.4

Spring a publié la version 2.4 de Spring Boot. Le but cet article est de faire un tour sur les principales évolutions de cette version mineure.

Spring Boot 2.4 requiert toujours un Java 8 minimum et propose un support de Java 15.

Deux versions contenant des bug fixes et des mises à jour de dépendances sont déjà disponibles : 2.4.1 et 2.4.2.

 

L’utilisation du nouveau système de numération des versions de Spring

Le premier changement concerne le numéro de version de Spring Boot qui applique le nouveau système de numérotation des versions de Spring. Ainsi la version devient 2.4.0 à la place de l’historique numéro de version qui aurait été 2.4.0.RELEASE.

 

La configuration

Plusieurs évolutions concernent la configuration.

Les raisons et le détail des changements sont décrits dans un article de blog sur Spring.io.

 

Le traitement des fichiers de configuration (.properties et .yaml)

Spring Boot 2.4 a modifié la manière dont les fichiers application.properties et application.yml sont traités. La mise à jour a été conçue pour simplifier et rationaliser la façon dont la configuration externe est chargée. Elle permet aussi de fournir de nouvelles fonctionnalités, telles que le support de l’importation de fichiers via la propriété spring.config.import.

La mise à jour restreint intentionnellement certaines combinaisons de propriétés. Il y aura peut-être la nécessité de modifier certaines choses lors de la mise à jour à partir de Spring Boot 2.3 ou d’une version antérieure.

Si la configuration n’utilise qu’un simple fichier application.properties ou application.yml, la mise à niveau devrait être facile. En revanche, si la configuration est plus complexe (avec des propriétés spécifiques au profil ou des propriétés d’activation du profil), il faudra peut-être apporter quelques modifications pour utiliser les nouvelles fonctionnalités.

Un guide de mise à jour détaillé est disponible.

Pour avoir le comportement de Spring Boot 2.3, il faut mettre la propriété spring.config.use-legacy-processing à true dans le fichier de configuration application.properties ou application.yml.

 

L’import d’arborescence de type Volume Mounted

Une nouvelle propriété spring.config.import peut être utilisée pour importer des arborescences de configuration qui sont couramment utilisés avec Kubernetes. Une arborescence de configuration est une autre façon de fournir des paires clé/valeur. Chaque paire est déclarée dans son propre fichier, le nom du fichier formant la clé de la propriété, et le contenu du fichier fournissant la valeur.

Le détail de l’utilisation et des exemples sont disponibles dans la documentation de référence.

 

Les chemins de configuration

Les chemins de configuration spécifiés via spring.config.location et spring.config.import (ajouté dans Spring Boot 2.4) n’échoueront plus silencieusement si le fichier ou le dossier n’existe pas. S’il faut importer un emplacement qui potentiellement ne sera pas trouvé, alors il est possible de préfixer le chemin avec optional:

Exemple :

spring.config.location=optional:/etc/config/app.properties

Il est possible de définir par configuration que tous les emplacements sont optionnels en utilisant :

  • Soit la propriété config.on-not-found=ignore via la méthode SpringApplication.setDefaultProperties(…​)
  • Soit avec une variable d’environnement système

 

La personnalisation du nom d’une propriété de configuration

Lors de l’utilisation de l’annotation @ConstructorBinding, le nom de la propriété est dérivé du nom du paramètre. Cela peut poser un problème si l’on utilise un mot-clé réservé en Java. Dans ce cas, il est possible d’utiliser l’annotation @Name pour préciser le nom de la propriété.

Exemple :

@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public class MaConfigurationProperties {

  private final String defaultValue;

  public MaConfigurationProperties(@Name("default") String defaultValue) {
    this.defaultValue = defaultValue;
  }
}

L’exemple ci-dessus permet d’utiliser la propriété app.default.

 

L’importation de configurations supplémentaires

Tant que le paramètre spring.config.use-legacy-processing n’est pas à true, il est possible d’importer des fichiers properties et yaml supplémentaires directement à partir de fichier de configuration principal application.properties ou application.yml.

La propriété spring.config.import permet de spécifier un ou plusieurs fichiers de configuration supplémentaires qui doivent être importés dans l’Environnement Spring.

 

L’importation de fichiers de configuration sans extensions

Certaines plates-formes Cloud ne permettent que le montage de volumes de fichiers sans extension. Si l’on a une telle contrainte, il est maintenant possible d’importer ces fichiers en fournissant une information à Spring Boot sur le type de contenu.

Exemple de fichier qui sera considéré comme du YAML

spring.config.import=/etc/maconfig[.yaml]

 

Les propriétés de configuration de Logback

Les propriétés de configuration spécifiques à Logback ont été renommées pour refléter le fait qu’elles sont spécifiques à Logback. Les noms précédents ont été dépréciés.

Les propriétés concernées sont :

Avant Spring Boot 2.4 A partir de Spring Boot 2.4
logging.pattern.rolling-file-name logging.logback.rollingpolicy.file-name-pattern
logging.file.clean-history-on-start logging.logback.rollingpolicy.clean-history-on-start
logging.file.max-size logging.logback.rollingpolicy.max-file-size
logging.file.total-size-cap logging.logback.rollingpolicy.total-size-cap
logging.file.max-history logging.logback.rollingpolicy.max-history

Les variables d’environnement système concernées sont :

Avant Spring Boot 2.4 A partir de Spring Boot 2.4
ROLLING_FILE_NAME_PATTERN LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN
LOG_FILE_CLEAN_HISTORY_ON_START LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START
LOG_FILE_MAX_SIZE LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE
LOG_FILE_TOTAL_SIZE_CAP LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP
LOG_FILE_MAX_HISTORY LOGBACK_ROLLINGPOLICY_MAX_HISTORY

 

L’interface Origin

L’interface Origin contient une nouvelle méthode getParent() qui permet de fournir le chaînage complet de l’origine de l’élément.

Par exemple, lors de l’utilisation de spring.config.import dans le fichier application.properties pour importer un autre fichier, l’origine des propriétés chargées à partir de ce second fichier aura un parent qui renvoie à la déclaration d’importation originale.

Les endpoints /env et /configprops de l’Actuator utilisent ces informations.

 

http / web

Plusieurs évolutions concernent le web.

 

L’enregistrement de la servlet par défaut

Spring Boot 2.4 n’enregistre plus la DefaultServlet fournie par le conteneur de servlets utilisé. Dans la plupart des applications, il n’est pas utilisé puisque la DispatcherServlet de Spring MVC est la seule servlet nécessaire.

Vous pouvez configurer la propriété server.servlet.register-default-servlet avec la valeur true si vous avez besoin de la servlet par défaut.

 

Les classes annotées avec @WebListeners peuvent elles-mêmes enregistrer des servlets et des filtres

Les classes annotées avec @WebListener sont désormais enregistrées de telle sorte qu’elles peuvent elles-mêmes enregistrer des servlets et des filtres.

Dans les versions précédentes de Spring Boot, il fallait les enregistrer manuellement en utilisant javax.servlet.Registration.Dynamic.

A partir de Spring Boot 2.4, nous n’utilisons plus l’enregistrement dynamique et il est donc sûr d’appeler event.getServletContext().addServlet(…​) et event.getServletContext.addFilter(…​) dans la méthode ServletContextListener.contextInitialized().

 

Les nouvelles propriétés de configuration web

De nouvelles propriétés ont été ajoutées pour prendre en charge la configuration de Locale et l’emplacement des ressources avec Spring MVC ou Spring WebFlux :

  • web.locale
  • web.locale-resolver
  • web.resources.*

Une nouvelle propriété a été ajoutée pour prendre en charge la configuration du endpoint de gestion des actuators via une servlet ou la pile web réactive :

  • server.base-path

Les propriétés spécifiques de Spring MVC et de servlet ci-dessous ont été dépréciées au profit de ces nouvelles propriétés qui supportent l’une ou l’autre des piles web :

  • mvc.locale
  • mvc.locale-resolver
  • resources.*
  • server.servlet.context-path

 

Actuator

Plusieurs évolutions concernent l’Actuator.

 

Le nouveau endpoint startup

Un nouveau endpoint nommé startup permet d’obtenir des informations sur la séquence de démarrage de l’application. Ce endpoint peut aider à identifier les beans dont le démarrage est plus long que prévu.

Il s’appuie sur une fonctionnalité de Spring Framework 5.3.

Pour invoquer le endpoint, il faut faire un POST sur l’url actuator/startup.

$ curl 'http://localhost:8080/actuator/startup' -i -X POST

 

Les en-têtes HTTP relatives aux cookies dans les traces HTTP

Les en-têtes de requête Cookie et les en-têtes de réponse Set-Cookie ne sont plus inclus par défaut dans les traces HTTP.

Pour rétablir le comportement de Spring Boot 2.3, il faut définir la propriété management.trace.http.include avec les valeurs cookies, errors, request-headers, response-headers

 

Filtrage dans le endpoint prometheus

Le endpoint prometheus prend désormais en charge un paramètre de requête nommé includedNames qui peut être utilisé pour filtrer les informations incluses dans la réponse.

Pour invoquer le endpoint, il faut un GET sur l’url actuator/prometheus avec un paramètre de requête includedNames.

$ curl 'http://localhost:8080/actuator/prometheus?includedNames=jvm_memory_used_bytes%2Cjvm_memory_committed_bytes' -i -X GET

 

Buildpack / Docker

Plusieurs évolutions concernent la génération d’image Docker via Buildpack en utilisant Spring Boot.

 

La publication dans un registre Docker

Le goal Maven spring-boot:build-image et la tâche bootBuildImage du plugin Gradle peuvent maintenant publier l’image générée dans un registre Docker.

<project>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<image>
						<name>docker.oxiane.com/library/${project.artifactId}</name>
						<publish>true</publish>
					</image>
					<docker>
						<publishRegistry>
							<username>user</username>
							<password>secret</password>
							<url>https://registry.oxiane.com/</url>
							<email>user@oxiane.com</email>
						</publishRegistry>
					</docker>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

 

L’authentification sur un registre privé Docker pour le build

Lors de la création d’une image Docker avec Spring Boot, il est maintenant possible d’obtenir les images requises par le build à partir d’un registre Docker privé avec authentification. L’authentification par nom d’utilisateur/mot de passe et par jeton est prise en charge.

Exemple avec Maven

<project>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<docker>
						<builderRegistry>
							<username>user</username>
							<password>secret</password>
							<url>https://registry.oxiane.com/</url>
							<email>user@oxiane.com</email>
						</builderRegistry>
					</docker>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

 

Layered jar activé par défaut

Spring Boot 2.4 active les layered jars par défaut et inclut les layertools. Cela devrait améliorer l’efficacité de l’image générée utilisant le buildpack.

Out-of-the-box, plusieurs couches sont définies :

  • dependencies : pour les dépendances
  • spring-boot-loader : pour ce qui est dans org/springframework/boot/loader
  • snapshot-dependencies : pour les dépendances snapshot
  • application: pour l’application (classes et ressources)

Cela permet d’optimiser l’image générée en définissant un index du contenu de chaque couche.

 

L’image Paketo de Buildpack

Le constructeur d’images utilisé par le goal Maven spring-boot:build-image et la tâche Gradle bootBuildImage de Gradle a été mis à jour pout utiliser les dernières images Paketo.

Le registre des images Paketo a été modifié pour le Docker Hub à la place de Google Container Registry pour une meilleure accessibilité.

 

Les dépendances d’un projet multi-modules dans Maven

Le goal spring-boot:build-image de Maven ajoute maintenant toutes les dépendances d’un projet multi-modules dans la couche « application ».

Deux nouveaux tags XML <includeModuleDependencies> et <excludeModuleDependencies> permettent de configurer les couches dans le fichier de configuration.

 

Les dépendances d’un projet multi-modules dans Gradle

La tâche bootBuildImage de Gradle ajoute maintenant toutes les dépendances d’un projet multi-modules dans la couche « application ».

Il est possible d’utiliser includeProjectDependencies() et excludeProjectDependencies() dans le DSL pour configurer les couches.

 

Mises à jour des dépendances

Spring Boot 2.4 a mis à jour plusieurs versions des dépendances vers des projets Spring :

Spring Boot 2.4 a aussi a mis à jour plusieurs versions des dépendances vers des projets tiers :

  • Artemis 2.13
  • AssertJ 3.18
  • Cassandra Driver 4.7
  • Elasticsearch 7.9
  • Flyway 7
  • Jersey 2.31
  • JUnit 5.7
  • Liquibase 3.10
  • Lettuce 6.0
  • Micrometer 1.6
  • Mockito 3.4
  • MongoDB 4.1
  • Oracle Database 19.7
  • Reactor 2020.0
  • RSocket 1.1
  • Undertow 2.2

 

Le support des dépendances tierces

Plusieurs évolutions concernent le support de certaines dépendances tierces.

 

La détection des bases de données embarquées

La manière dont une base de données embarquée est détectée a été affinée pour considérer qu’une base de données n’est embarquée que si elle est en mémoire.

Ce changement a deux conséquences si l’on utilise la persistance basée sur les fichiers ou le mode serveur avec H2, HSQL et Derby :

  • L’utilisateur sa n’est plus configuré par défaut. Il faut maintenant le définir explicitement en définissant dans la configuration la propriété datasource.username=sa
  • Ces bases de données ne seront plus initialisées au démarrage car elles ne sont plus considérées comme embarquées. Pour le faire il faut utiliser la propriété datasource.initialization-mode

 

Une propriété de configuration pour le mot de passe admin de la console web H2

Une nouvelle propriété de configuration, spring.h2.console.settings.web-admin-password permet de configurer le mot de passe administrateur de la console web H2.

 

Neo4j

Spring Boot 2.4 apporte une mise à jour significative du support de Neo4j. Un certain nombre de propriétés spring.data.neo4j.* ont été supprimées et le support de Neo4j OGM a également été supprimé.

La configuration du pilote Neo4j se fait via l’espace de noms spring.neo4j.* bien que l’URI et l’authentification de base à partir de l’espace de noms data soient toujours supportés de manière dépréciée.

Cette version apporte le support des reactive repositories et repose sur une auto-configuration séparée pour le driver Neo4j. Il est donc maintenant possible d’utiliser Neo4j avec ou sans Spring Data.

Pour utiliser @Transactional avec une utilisation réactive, il faut configurer explicitement le bean Neo4jReactiveTransactionManager.

@Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
public ReactiveTransactionManager reactiveTransactionManager(Driver driver, ReactiveDatabaseSelectionProvider databaseNameProvider){
   returnnewReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}

 

Hazelcast 4

Spring Boot 2.4 utilise Hazelcast 4 tout en conservant la compatibilité avec Hazelcast 3.2.x. Si vous n’êtes pas prêt à passer à Hazelcast 4, il faut utiliser la propriété hazelcast.version dans la configuration du build.

 

Elasticsearch RestClient

Le bean Elasticsearch RestClient n’est plus auto-configuré par Spring Boot. Le bean RestHighLevelClient est toujours auto-configuré.

 

R2DBC

L’infrastructure de base de R2DBC est passée dans Spring Framework dans un nouveau module spring-r2dbc. L’utilisation de cette infrastructure nécessite de migrer les accès dépréciés vers le nouveau support de base.

Un R2dbcEntityTemplate est disponible pour simplifier l’utilisation de Reactive R2DBC par les entités.

 

Redis Cache Metrics

Lors de l’utilisation du cache Redis, il est possible d’exposer les statistiques du cache via Micrometer. Les mesures enregistrées comprennent le nombre de puts, de gets et de deletes, ainsi que le nombre de hits/misses. Le nombre de demandes en attente et la durée d’attente du verrouillage sont également enregistrés.

Pour activer cette fonctionnalité, il faut définir la propriété spring.cache.redis.enable-statistics avec la valeur true.

 

Les tests automatisés

Plusieurs évolutions concernent les tests automatisés.

 

Le Vintage Engine de JUnit 5 est retiré de spring-boot-starter-test

A partir de spring Boot 2.4, le starter spring-boot-starter-test n’inclut plus le moteur d’exécution des tests JUnit 4 (Vintage Engine) dans JUnit 5.

Si la migration des tests vers JUnit 5 n’est pas envisagée, il faut rajouter manuellement la dépendance.

Exemple avec Maven :

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Exemple avec Gradle :

testImplementation("org.junit.vintage:junit-vintage-engine") {
    excludegroup:"org.hamcrest",module:"hamcrest-core"
}

 

L’exportation des métriques dans les tests d’intégration

L’annotation @SpringBootTest ne configure plus les systèmes de surveillance disponibles et ne fournit que MeterRegistry en mémoire. Si l’on exportait des métriques dans le cadre d’un test d’intégration, il est possible d’ajouter l’annotation @AutoConfigureMetrics aux tests pour rétablir le comportement précédent.

 

Conclusion

Spring Boot poursuit son évolution au travers de cette version mineure. La migration vers cette nouvelle version pourra dans certains cas nécessiter quelques adaptations.

Jean-Michel Doudoux

Written by

CTO OXiane