Changer son environnement fullstack en un clin d'oeil : partie 1 avec Java
Tags: environnement, java, fullstack, french
Published: 2023-02-05 08:44:15

Vous êtes un développeur consultant. Vous travaillez pour plusieurs clients. Ou tout simplement, vous travaillez à la fois pour votre employeur et pour un ou plusieurs projets open source, durant votre temps libre.

Lorsque vous passez d'un projet de développement à un autre, vous avez certainement dû changer tous vos outils et identifiants...

Changement de votre identifiant Git, de votre signature GnuPG, de vos clés SSH... Sans parler des versions des outils que vous utilisez : version de Java, de NodeJS ou de Python.

Il y a même les configurations des outils de constructions qui doivent changer comme celles de Maven ou de NPM.

Pas simple pour passer d'un contexte à l'autre.

Bonne nouvelle : j'ai déjà expérimenté plusieurs solutions pour répondre à ces besoins et je voudrais partager avec vous le résultat de mes recherches !

Je vous propose d'aborder cela sous la forme de plusieurs petits articles ciblés sur chaque astuce trouvée.

## Gérer vos versions de Java

Commençons par aborder le fait de devoir gérer plusieurs versions de Java.

Attention on ne prendra pas en compte les versions de Java antérieures à la version 8.

Si vous êtes sous Linux Debian ou un de ses dérivés (notamment Ubuntu), il existe des outils assez pratiques répondant à la problématique comme `update-alternatives` voire `update-java-alternatives`. Néanmoins, ces solutions se cantonent à un seul système et je voulais dans mes recherches trouver un outil _cross-platform_.

En fait il existe pas mal d'outils pour gérer ses différentes versions de Java : [jEnv](https://www.jenv.be/) ou encore [Jabba](https://github.com/shyiko/jabba). Pour ma part, j'ai souhaité me concentrer sur un outil plutôt plébicité pour ce besoin : [SDKMan](https://sdkman.io/).

SDKMan est un logiciel open source sous licence Apache 2.0. C'est un projet [très actif sur GitHub](https://github.com/sdkman/sdkman-cli). Il est également possible de soutenir le projet financièrement via [le site Open Collective](https://opencollective.com/sdkman).

SDKMan est centré sur la gestion des différentes versions de Java mais aussi des outils et autres technologies liées.

On pourra aussi gérer ses différentes version de Maven ou de Kotlin avec SDKMan (ce que je fais à titre personnel).

### Installer SDKMan

Pour utiliser SDKMan, vous devez disposer d'un système Linux, Windows (via WSL) ou MacOS. Il est également possible de l'installer sur FreeBSD voire Solaris !

SDKMan étant un outil en ligne de commande, il a besoin d'interagir avec votre interpréteur de ligne de commande préféré. En l'occurrence, il gère Bash et Zsh.

Pour installer SDKMan, ouvrez un terminal et tapez la commande suivante :

```sh
curl -s "https://get.sdkman.io" | bash
```

Petit _disclaimer_ sur ce type d'installation quand même, je vous invite à télécharger et à consulter le contenu de `https://get.sdkman.io` pour savoir ce que fait le script avant de confier ça à `bash` aveuglément ! Vous êtes prévenus 😄

En fonction de l'interpréteur de ligne de commande que vous utilisez, votre fichier `.bashrc` ou `.zshrc` sera modifié en conséquence pour ajouter la commande `sdk` de SDKMan.

Notez aussi que SDKMan va créer un répertoire `.sdkman` à la racine de votre répertoire utilisateur dans lequel on retrouvera non seulement l'outil `sdk` mais aussi toutes les installations de Java, Maven ou Kotlin.

### Téléchargez votre version de Java par défaut

Maintenant que SDKMan est installé, on va l'utiliser pour installer votre version de Java par défaut.

Pour obtenir la liste des versions de Java disponibles avec SDKMan, vous devez taper la commande suivante dans un terminal :

```sh
$> sdk list java
```

SDKMan pour fournira une liste des distributions disponibles pour votre architecture matérielle (vous pouvez voir les architectures matérielles supportées [ici](https://sdkman.io/vendors) au chapitre _Multi-platform binary distributions_).

Personnellement j'aime bien prendre la dernière version stable, par forcément LTS, celle d'OpenJDK de Java.net.

À l'heure où sont écrites ces lignes, il s'agit de la version `19.0.2-open`.

Si vous voulez installer cette version, il vous suffira de taper la commande suivante dans un terminal :

```sh
$> sdk install java 19.0.2-open
Downloading: java 19.0.2-open
In progress...
######################################################################### 100,0%
Repackaging Java 19.0.2-open...
Done repackaging...
Cleaning up residual files...
Installing: java 19.0.2-open
Done installing!
Do you want java 19.0.2-open to be set as default? (Y/n): Y
Setting java 19.0.2-open as default.
```

Comme illustré ci-dessus, SDKMan vous demandera si vous désirez définir cette nouvelle version téléchargée comme votre version de Java par défaut : répondez `Y` pour donner votre accord.

Vous pourrez valider que vous avez bien ce que vous désirez avec les commandes suivantes :

```sh
$> java -version
openjdk version "19.0.2" 2023-01-17
OpenJDK Runtime Environment (build 19.0.2+7-44)
OpenJDK 64-Bit Server VM (build 19.0.2+7-44, mixed mode, sharing)
```

### Installer d'autres versions de Java

Bon pour l'instant et d'après ce que je vous ai montré, SDKMan n'apporte rien par rapport à une bonne vieille installation manuelle de Java.

Justement, nous allons maintenant voir le gros avantage de cet outil : la capacité à installer plusieurs versions de Java et à passer d'une version à une autre.

Pour lister la liste des versions de Java disponibles, faites comme dans le chapitre suivant et tapez la commande suivante :

```sh
$> sdk list java
================================================================================
Available Java Versions for macOS ARM 64bit
================================================================================
 Vendor        | Use | Version      | Dist    | Status     | Identifier
--------------------------------------------------------------------------------
 Corretto      |     | 19.0.2       | amzn    |            | 19.0.2-amzn         
               |     | 19.0.1       | amzn    |            | 19.0.1-amzn         
               |     | 17.0.6       | amzn    |            | 17.0.6-amzn         
               |     | 17.0.5       | amzn    |            | 17.0.5-amzn         
               |     | 11.0.18      | amzn    |            | 11.0.18-amzn        
               |     | 11.0.17      | amzn    |            | 11.0.17-amzn        
               |     | 8.0.362      | amzn    |            | 8.0.362-amzn        
               |     | 8.0.352      | amzn    |            | 8.0.352-amzn        
 Gluon         |     | 22.1.0.1.r17 | gln     |            | 22.1.0.1.r17-gln    
               |     | 22.1.0.1.r11 | gln     |            | 22.1.0.1.r11-gln    
 GraalVM       |     | 22.3.r19     | grl     |            | 22.3.r19-grl        
               |     | 22.3.r17     | grl     |            | 22.3.r17-grl        
               |     | 22.3.r11     | grl     |            | 22.3.r11-grl        
               |     | 22.3.1.r19   | grl     |            | 22.3.1.r19-grl      
               |     | 22.3.1.r17   | grl     |            | 22.3.1.r17-grl      
               |     | 22.3.1.r11   | grl     |            | 22.3.1.r11-grl      
               |     | 22.2.r17     | grl     |            | 22.2.r17-grl        
               |     | 22.2.r11     | grl     |            | 22.2.r11-grl        
               |     | 22.1.0.r17   | grl     |            | 22.1.0.r17-grl      
               |     | 22.1.0.r11   | grl     |            | 22.1.0.r11-grl      
 Java.net      |     | 21.ea.8      | open    |            | 21.ea.8-open        
               |     | 21.ea.7      | open    |            | 21.ea.7-open        
               |     | 21.ea.6      | open    |            | 21.ea.6-open        
               |     | 21.ea.5      | open    |            | 21.ea.5-open        
               |     | 21.ea.4      | open    |            | 21.ea.4-open        
               |     | 20.ea.34     | open    |            | 20.ea.34-open       
               |     | 20.ea.33     | open    |            | 20.ea.33-open       
               |     | 20.ea.32     | open    |            | 20.ea.32-open       
               |     | 20.ea.31     | open    |            | 20.ea.31-open       
               |     | 20.ea.30     | open    |            | 20.ea.30-open       
               | >>> | 19.0.2       | open    | installed  | 19.0.2-open         
               |     | 19.0.1       | open    |            | 19.0.1-open         
 Liberica      |     | 19.0.2.fx    | librca  |            | 19.0.2.fx-librca    
               |     | 19.0.2       | librca  |            | 19.0.2-librca       
               |     | 19.0.1.fx    | librca  |            | 19.0.1.fx-librca    
               |     | 19.0.1       | librca  |            | 19.0.1-librca       
               |     | 17.0.6.fx    | librca  |            | 17.0.6.fx-librca    
               |     | 17.0.6       | librca  |            | 17.0.6-librca       
               |     | 17.0.5.fx    | librca  |            | 17.0.5.fx-librca    
               |     | 17.0.5       | librca  |            | 17.0.5-librca       
               |     | 11.0.18.fx   | librca  |            | 11.0.18.fx-librca   
               |     | 11.0.18      | librca  |            | 11.0.18-librca      
               |     | 11.0.17.fx   | librca  |            | 11.0.17.fx-librca   
               |     | 11.0.17      | librca  |            | 11.0.17-librca      
               |     | 8.0.362.fx   | librca  |            | 8.0.362.fx-librca   
               |     | 8.0.362      | librca  |            | 8.0.362-librca      
               |     | 8.0.352.fx   | librca  |            | 8.0.352.fx-librca   
               |     | 8.0.352      | librca  |            | 8.0.352-librca      
 Liberica NIK  |     | 22.3.r17     | nik     |            | 22.3.r17-nik        
               |     | 22.3.r11     | nik     |            | 22.3.r11-nik        
               |     | 22.3.1.r17   | nik     |            | 22.3.1.r17-nik      
               |     | 22.3.1.r11   | nik     |            | 22.3.1.r11-nik      
               |     | 22.2.r17     | nik     |            | 22.2.r17-nik        
               |     | 22.2.r11     | nik     |            | 22.2.r11-nik
 Microsoft     |     | 17.0.6       | ms      |            | 17.0.6-ms           
               |     | 17.0.5       | ms      |            | 17.0.5-ms           
               |     | 11.0.18      | ms      |            | 11.0.18-ms          
               |     | 11.0.17      | ms      |            | 11.0.17-ms          
 Oracle        |     | 19.0.2       | oracle  |            | 19.0.2-oracle       
               |     | 19.0.1       | oracle  |            | 19.0.1-oracle       
               |     | 17.0.6       | oracle  |            | 17.0.6-oracle       
               |     | 17.0.5       | oracle  |            | 17.0.5-oracle       
 SapMachine    |     | 19.0.2       | sapmchn |            | 19.0.2-sapmchn      
               |     | 19.0.1       | sapmchn |            | 19.0.1-sapmchn      
               |     | 17.0.6       | sapmchn |            | 17.0.6-sapmchn      
               |     | 17.0.5       | sapmchn |            | 17.0.5-sapmchn      
               |     | 11.0.18      | sapmchn |            | 11.0.18-sapmchn     
               |     | 11.0.17      | sapmchn |            | 11.0.17-sapmchn     
 Semeru        |     | 18.0.2       | sem     |            | 18.0.2-sem          
               |     | 17.0.5       | sem     |            | 17.0.5-sem          
               |     | 17.0.4.1     | sem     |            | 17.0.4.1-sem        
               |     | 11.0.17      | sem     |            | 11.0.17-sem         
               |     | 11.0.16.1    | sem     |            | 11.0.16.1-sem       
 Temurin       |     | 19.0.2       | tem     |            | 19.0.2-tem          
               |     | 19.0.1       | tem     |            | 19.0.1-tem          
               |     | 17.0.6       | tem     |            | 17.0.6-tem          
               |     | 17.0.5       | tem     |            | 17.0.5-tem          
               |     | 11.0.18      | tem     |            | 11.0.18-tem         
               |     | 11.0.17      | tem     |            | 11.0.17-tem         
 Zulu          |     | 19.0.2       | zulu    |            | 19.0.2-zulu         
               |     | 19.0.2.fx    | zulu    |            | 19.0.2.fx-zulu      
               |     | 19.0.1       | zulu    |            | 19.0.1-zulu         
               |     | 19.0.1.fx    | zulu    |            | 19.0.1.fx-zulu      
               |     | 17.0.6       | zulu    |            | 17.0.6-zulu         
               |     | 17.0.6.fx    | zulu    |            | 17.0.6.fx-zulu      
               |     | 17.0.5       | zulu    |            | 17.0.5-zulu         
               |     | 17.0.5.fx    | zulu    |            | 17.0.5.fx-zulu      
               |     | 11.0.18      | zulu    |            | 11.0.18-zulu        
               |     | 11.0.18.fx   | zulu    |            | 11.0.18.fx-zulu     
               |     | 11.0.17      | zulu    |            | 11.0.17-zulu        
               |     | 11.0.17.fx   | zulu    |            | 11.0.17.fx-zulu     
               |     | 8.0.362      | zulu    |            | 8.0.362-zulu        
               |     | 8.0.362.fx   | zulu    |            | 8.0.362.fx-zulu     
               |     | 8.0.352      | zulu    |            | 8.0.352-zulu        
               |     | 8.0.352.fx   | zulu    |            | 8.0.352.fx-zulu     
================================================================================
Omit Identifier to install default version 17.0.6-tem:
    $ sdk install java
Use TAB completion to discover available versions
    $ sdk install java [TAB]
Or install a specific version by Identifier:
    $ sdk install java 17.0.6-tem
Hit Q to exit this list view
================================================================================
(END)
```

Comme vous pouvez éventuellement le remarquer, il s'agit des version disponibles pour l'architecture ARM 64bits de MacOS (j'utilise actuellement un MacBook Air M2)... Et il y en a **beaucoup**.

Je ne vous ferais pas aujourd'hui un comparatif des différentes déclinaisons de Java selon les différents fournisseurs (ça fera peut-être partie d'un futur article ?) mais de mon côté, j'utilise pour mes versions _non bleeding edge_, celles de Zulu.

En l'occurrence, ce qui me plait dans les versions de Zulu sont le [compilateur JIT Falcon basé sur LLVM](https://llvm.org/devmtg/2017-10/slides/Reames-FalconKeynote.pdf)et le [_garbage collector_ C4](https://www.azul.com/c4-white-paper/).

Chez le client pour lequel je travaille, on retrouve des projets développés pour Java 8, 11 et plus récemment 17.

J'ai donc installé la version `17.0.6-zulu`, à l'aide de la commande suivante :

```sh
$> sdk install java 17.0.6-zulu
Downloading: java 17.0.6-zulu
In progress...
########################################################################## 100,0%
Repackaging Java 17.0.6-zulu...
Done repackaging...
Installing: java 17.0.6-zulu
Done installing!
Do you want java 17.0.6-zulu to be set as default? (Y/n): n
```

Et cette fois, contrairement à la première fois, j'ai préféré ne pas changer la version par défaut avec cette version de Java.

La démarche n'est pas très différente pour les versions  `11.0.18-zulu` et `8.0.362-zulu` :

```sh
$> sdk install java 11.0.18-zulu
(...)
$> sdk install java 8.0.362-zulu
(...)
```

Et vous voilà avec les trois dernières versions LTS de Java d'installées sur votre poste !

### Passer d'une version de Java à une autre

Pour changer la version en cours de Java, vous devrez utiliser la commande suivante (ici illustrée avec la version `17.0.6-zulu`) :

```sh
$> sdk use java 17.0.6-zulu

Using java version 17.0.6-zulu in this shell.
```

Une petite vérification de la version en cours permet de confirmer le bon fonctionnement de l'opération :

```sh
$> java -version
openjdk version "17.0.6" 2023-01-17 LTS
OpenJDK Runtime Environment Zulu17.40+19-CA (build 17.0.6+10-LTS)
OpenJDK 64-Bit Server VM Zulu17.40+19-CA (build 17.0.6+10-LTS, mixed mode, sharing)
```

### Changement automatique de la version de Java

Il est possible, à l'aide de SDKMan d'enregistrer la version en cours d'utilisation de Java pour un projet en particulier.

Imaginons que vous avez un projet _legacy_ de votre client qui utilise encore du Java 8.

Pour associer cette version de java avec ledit projet, il vous faudra vous rendre dans ce projet, changer la version de java et lancer la commande `sdk env init` :

```sh
~ $> cd devel/mon_client/projet_java8
~/devel/mon_client/projet_java8 $> sdk use java 8.0.362-zulu
Using java version 8.0.362-zulu in this shell.
~/devel/mon_client/projet_java8 $> sdk env init
.sdkmanrc created.
~/devel/mon_client/projet_java8 $> java -version
openjdk version "1.8.0_362"
OpenJDK Runtime Environment (Zulu 8.68.0.19-CA-macos-aarch64) (build 1.8.0_362-b08)
OpenJDK 64-Bit Server VM (Zulu 8.68.0.19-CA-macos-aarch64) (build 25.362-b08, mixed mode)
```

Maintenant, avec cette configuration, il suffira de lancer la commande `sdk env` au sein du répertoire configuré pour que la version correcte de Java soit sélectionnée !

```sh
~ $> cd devel/mon_client/projet_java8
~/devel/mon_client/projet_java8 $> sdk env
Using java version 8.0.362-zulu in this shell.
```

Maintenant encore mieux : il est possible de faire en sorte que la version de Java change **automatiquement** lorsque vous entrez dans le répertoire dudit projet configuré !

Pour cela, vous allez devoir modifier la configuration de SDKMan en éditant le fichier `~/.sdkman/etc/config` et assigner la variable de configuration `sdkman_auto_env` à `true`.

Il est possible de le faire en une ligne sur MacOS à l'aide de la commande suivante :

```sh
$> sed 's/sdkman_auto_env=false/sdkman_auto_env=true/g' ~/.sdkman/etc/config > /tmp/sdkman-cfg && cat /tmp/sdkman-cfg > ~/.sdkman/etc/config
```

Sous GNU Linux, c'est plus simple :

```sh
$> sed -i 's/sdkman_auto_env=false/sdkman_auto_env=true/g' ~/.sdkman/etc/config
```

Maintenant, un petit tour dans le répertoire de votre projet en Java 8 et le changement est automatique (attention il faut ouvrir un nouveau terminal pour que ça soit effectif) :

```sh
~ $> cd devel/mon_client/projet_java8
Using java version 8.0.362-zulu in this shell.
```

## Gérer vos versions de Maven et de Kotlin

En réalité, je n'utilise pas vraiment SDKMan pour jongler entre plusieurs versions de Maven ou Kotlin mais il s'agit surtout d'un outil très pratique pour les installer facilement et rapidement.

### Installation de Maven

Si comme moi, vous ne vous souciez pas plus que ça de la version de Maven que vous aller récupérer à partir du moment que c'est la dernière en date, tapez juste la commande suivante dans un terminal :

```sh
$> sdk install maven
Downloading: maven 3.8.7
In progress...
########################################################################## 100,0%
Installing: maven 3.8.7
Done installing!
```

### Installation de Kotlin

Pour Kotlin c'est un peu différent.

Ce langage est assez récent pour que la chance (ou la malchance) de devoir gérer plusieurs version de Kotlin est faible.

Cependant, vous pourrez, comme java, connaître les différentes version de Kotlin disponibles avec la commande suivante :

```sh
$> sdk list kotlin
================================================================================
Available Kotlin Versions
================================================================================
 > * 1.8.0               1.4.0               1.2.60              1.1.3          
     1.7.21              1.3.72              1.2.51              1.1.2-5        
     1.7.20              1.3.71              1.2.50              1.1.2-2        
     1.7.10              1.3.70              1.2.41              1.1.2          
     1.7.0               1.3.61              1.2.40              1.1.1          
     1.6.21              1.3.60              1.2.31              1.1            
     1.6.20              1.3.50              1.2.30              1.0.7          
     1.6.10              1.3.41              1.2.21              1.0.6          
     1.6.0               1.3.40              1.2.20              1.0.5-2        
     1.5.31              1.3.31              1.2.10              1.0.5          
     1.5.30              1.3.30              1.2.0               1.0.4          
     1.5.21              1.3.21              1.1.61              1.0.3          
     1.5.10              1.3.20              1.1.60              1.0.2          
     1.5.0               1.3.11              1.1.51              1.0.1-2        
     1.4.31              1.3.10              1.1.50              1.0.1-1        
     1.4.30              1.3.0               1.1.4-3             1.0.1          
     1.4.21              1.2.71              1.1.4-2             1.0.0          
     1.4.20              1.2.70              1.1.4                              
     1.4.10              1.2.61              1.1.3-2                            

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
(END)
```

Vous remarquerez d'ailleurs que j'ai déjà installé la dernière version (`1.8.0` à l'heure où sont écrites ces lignes) sur mon poste.

Pour installer Kotlin dans sa dernière version, il vous suffira de taper en ligne de commande :

```sh
$> sdk install kotlin
```

Pour avoir une version spécifique comme la version `1.2.71` :

```sh
$> sdk install kotlin 1.2.71
```

Pour passer d'une version à une autre, c'est identique à ce que l'on a appris avec Java.

## Et la suite ?

Dans mon prochain article, je vous expliquerais comment j'ai réussi à changer **complètement** de configuration Maven en fonction du répertoire où je me trouve...

Si ça vous intéresse, demandez-moi en contact ou suivez-moi sur LinkedIn !

J'aimerais aussi terminer en vous expliquer rapidement qui je suis 😄

Je m'appelle Hoani CROSS. Je suis originaire de Polynésie Française.

Passionné d'informatique depuis toujours (j'ai commencé à développer en CP, il y a environ 40 ans), j'ai évolué dans beaucoup d'environnements et occupé de nombreux poste, jusqu'à celui de DSI...

Aujourd'hui je suis manager et backend architect chez [SFEIR](https://sfeir.com), une Néo-ESN française. Une des particularités de SFEIR, c'est que les managers sont également des exécutants en mission chez des clients. On comprend ce que font les employés qu'on manage et croyez-moi, ça fait une sacré différence ! Et enfin, ce qui nous relie tous chez SFEIR, c'est la passion pour l'informatique... Étant donné qu'elle me suit depuis 40 ans, autant vous dire que je suis tombé au bon endroit !..

D'ailleurs, si vous êtes passionné.e comme moi, il y certainement une mission de rêve qui vous attend chez SFEIR alors n'hésitez pas à me contacter si vous voulez changer d'horizon.

Enfin, je suis aussi le propriétaire du blog [Geek & Rentable](https://geeketrentable.fr), dont je vous conseille la visite. Avec ce blog, je souhaite aider les développeurs ou autre acteurs de la tech, passionnés mais malheureusement incompris, afin de faire évoluer leur condition de travail voire leur carrière.

À très bientôt.