Skip to content

Commit 674efcc

Browse files
committed
Version Gradle du template Java 25
1 parent d431b4d commit 674efcc

File tree

12 files changed

+154
-110
lines changed

12 files changed

+154
-110
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ run-app: ## Lancer l'application localement
1212
run-installed-app: .check-install-dir ## Lancer l'application installée
1313
PATH=$(DEST_DIR)/$(APP_DIR)/bin:$(PATH) $(APP_NAME).sh --language French
1414

15+
test: ## Exécuter les tests
16+
./gradlew test
17+
1518
clean: ## Nettoyer le répertoire de construction
1619
rm --force --recursive $(BUILD)
1720

README.md

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,43 @@
1-
# Un template d'Application en Ligne de Commande (CLI) avec Java 23 et les JEP 458 et 477
1+
# Un template d'Application en Ligne de Commande (CLI) avec Java 25 et les JEP 458, 511 et 512
22

3-
Le template **java-23-quickstart** permet de démarrer une nouvelle application en commande ligne avec Java et Gradle.
3+
Le template **java-25-quickstart** permet de démarrer une nouvelle application en commande ligne avec Java et Gradle.
44

5-
Ce template nécessite d'utiliser Java 23 ou une version supérieure car il utilise les JEPs suivantes :
5+
Ce template utilise les JEPs suivantes :
66

7-
* La [JEP 458](https://openjdk.org/jeps/458) qui permet de lancer un programme Java dont le code est réparti dans
8-
plusieurs fichiers sources sans avoir besoin de les compiler préalablement
9-
* La [JEP 477](https://openjdk.org/jeps/477) qui permet de :
10-
* Se passer de déclaration de classe
11-
* Simplifier la déclaration de la méthode `main`
12-
* Utiliser les méthodes de la classe `java.io.IO` sans devoir les importer
7+
* La [JEP 458: Launch Multi-File Source-Code Programs](https://openjdk.org/jeps/458) qui permet de lancer un programme
8+
Java dont le code est réparti dans plusieurs fichiers sources sans avoir besoin de les compiler préalablement
9+
* La [JEP 511: Module Import Declarations](https://openjdk.org/jeps/511) qui permet d'importer tous les packages
10+
exportés par un module java
11+
* La [JEP 512: Compact Source Files and Instance Main Methods](https://openjdk.org/jeps/512) qui permet de :
12+
* Se passer de déclaration de classe
13+
* Simplifier la déclaration de la méthode `main`
14+
* Utiliser les méthodes `println` et `readln` de la classe `java.lang.IO`
15+
16+
Le template utilise la librairie [record-args](https://github.com/nipafx/record-args), développée par
17+
[Nicolai Parlog](https://nipafx.dev), et qui s'appuie sur les `record` et les interfaces `sealed` pour définir les
18+
arguments de la ligne de commande et en effectuer le parsing.
19+
20+
* [Créer une application depuis ce template](#créer-une-application-depuis-ce-template)
21+
* [Construire votre application](#construire-votre-application)
22+
* [Changer le nom de l'application](#changer-le-nom-de-lapplication)
23+
* [Lancer l'application localement](#lancer-lapplication-localement)
24+
* [Afficher l'aide de l'application](#afficher-laide-de-lapplication)
25+
* [Construire le livrable de l'application](#construire-le-livrable-de-lapplication)
26+
* [Installer l'application](#installer-lapplication)
27+
* [Shell de lancement](#shell-de-lancement)
28+
* [Lancer l'application installée](#lancer-lapplication-installée)
29+
* [Exécuter les tests](#exécuter-les-tests)
30+
* [Autres templates](#autres-templates)
31+
32+
## Créer une application depuis ce template
33+
34+
Pour créer une application depuis ce template, on procédera comme suit :
35+
36+
<a href="https://asciinema.org/a/732396" target="_blank"><img src="https://asciinema.org/a/732396.svg" /></a>
1337

1438
## Construire votre application
1539

16-
Après avoir [créé le dépôt GitHub](https://github.com/new?template_name=java-23-quickstart&template_owner=java-cli-apps)
40+
Après avoir [créé le dépôt GitHub](https://github.com/new?template_name=java-25-quickstart&template_owner=java-cli-apps)
1741
de votre nouvelle application à partir de ce template, vous pouvez suivre les étapes suivantes pour construire votre application.
1842

1943
### Changer le nom de l'application
@@ -72,7 +96,7 @@ $ DEST_DIR=/home/user make run-installed-app
7296
```
7397

7498
```console
75-
PATH=/home/user/QuickStart/bin:/usr/lib/jvm/jdk-23/bin:/home/fopy/.local/bin:... QuickStart.sh --language French
99+
PATH=/home/user/QuickStart/bin:/usr/lib/jvm/jdk-25/bin:/home/fopy/.local/bin:... QuickStart.sh --language French
76100
Bonjour 🇫🇷
77101
```
78102

@@ -81,16 +105,35 @@ Il ne nous reste plus qu'à :
81105
- Implémenter notre métier dans [Application.java](src/main/java/Application.java)
82106
- Ajouter dans le répertoire [src/main/java](src/main/java) les fichiers qui déclarent les classes utilisées par `Application.java`
83107
- Ajouter les caractéristiques de nos dépendances dans [gradle/libs.versions.toml](gradle/libs.versions.toml) et [build.gradle.kts](build.gradle.kts)
108+
- Implémenter des tests
109+
110+
111+
## Exécuter les tests
112+
113+
Dans ce template utilisant Gradle, les tests utilisent JUnit, et contrairement
114+
au template [basic-java-25-quickstart](https://github.com/java-cli-apps/basic-java-25-quickstart)
115+
ils n'utilisent pas la JEP 458: les sources sont compilées avant les tests.
116+
117+
```bash
118+
$ make test
119+
```
84120

85121
## Autres templates
86122

87-
### Sans utiliser Java 23
123+
### Sans utiliser Java 25
124+
125+
Si vous ne disposez pas de Java 25, vous avez trois possibilités :
88126

89-
Si vous ne disposez pas de Java 23, vous pouvez utiliser le template [basic-java-11-quickstart](https://github.com/java-cli-apps/basic-java-11-quickstart)
90-
qui ne requiert que la version 11 de Java. Il est alors nécessaire que tout le code Java réside dans le même fichier
91-
comme décrit dans la [JEP 330](https://openjdk.org/jeps/330).
127+
- Utiliser les templates [java-23-quickstart](https://github.com/java-cli-apps/java-23-quickstart) ou
128+
[java-22-quickstart](https://github.com/java-cli-apps/java-22-quickstart) qui ne nécessitent
129+
respectivement que la version 23 ou 22 de Java.
130+
- Utiliser le template [basic-java-11-quickstart](https://github.com/java-cli-apps/basic-java-11-quickstart)
131+
qui ne requiert que la version 11 de Java. Il est alors nécessaire que tout le code Java réside dans le même fichier
132+
comme décrit dans la [JEP 330](https://openjdk.org/jeps/330).
92133

93134
### Sans utiliser Gradle
94135

95-
Si vous ne disposez pas de Gradle ou que vous ne souhaitez pas l'utiliser, vous pouvez utiliser le template [basic-java-23-quickstart](https://github.com/java-cli-apps/basic-java-23-quickstart)
96-
qui ne requiert que `make` pour construire l'application.
136+
Si vous ne disposez pas de Gradle ou que vous ne souhaitez pas l'utiliser, vous
137+
pouvez utiliser les templates [basic-java-25-quickstart](https://github.com/java-cli-apps/basic-java-25-quickstart)
138+
ou [basic-java-23-quickstart](https://github.com/java-cli-apps/basic-java-23-quickstart)
139+
qui ne requierent que `make` pour construire l'application.

build.gradle.kts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ application {
1111

1212
java {
1313
toolchain {
14-
languageVersion.set(JavaLanguageVersion.of(23))
14+
languageVersion.set(JavaLanguageVersion.of(25))
1515
}
1616
}
1717

1818
dependencies {
19-
implementation(libs.picocli)
19+
implementation(libs.record.args)
2020
testImplementation(libs.junit.jupiter)
2121
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
2222
}
@@ -45,14 +45,6 @@ tasks.named<Zip>("scriptsDistZip") {
4545
archiveFileName.set("${APP_NAME}.zip")
4646
}
4747

48-
tasks.compileJava {
49-
options.compilerArgs.addAll(listOf("--enable-preview"))
50-
}
51-
52-
tasks.withType<JavaExec> {
53-
jvmArgs = listOf("--enable-preview")
54-
}
55-
5648
tasks.named<Test>("test") {
5749
useJUnitPlatform()
5850
}

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[versions]
2+
record-args = "0.9.3"
23
junit-jupiter = "5.13.4"
3-
picocli = "4.7.7"
44

55
[libraries]
6+
record-args = { module = "dev.nipafx.args:record-args", version.ref = "record-args" }
67
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
7-
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }

src/main/java/Application.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
//usr/bin/env java --enable-preview --class-path ${APP_DIR:-.}/lib/'*' "$0" "$@"; exit $?
1+
//usr/bin/env java --class-path ${APP_DIR:-.}/lib/'*' "$0" "$@"; exit $?
22

3-
import language.api.Greeting;
4-
import language.api.Greeting.Language;
3+
import dev.nipafx.args.Args;
54

6-
import picocli.CommandLine;
7-
import picocli.CommandLine.Command;
8-
import picocli.CommandLine.Option;
5+
import static java.lang.IO.println;
96

107
void main(String... args) {
11-
var method = CommandLine.getCommandMethods(getClass(), null).getFirst();
12-
var commandLine = new CommandLine(method);
13-
int exitCode = commandLine.execute(args);
14-
System.exit(exitCode);
8+
try {
9+
sayHello(Args.parse(args, ParsedArgs.class));
10+
} catch (Exception exception) {
11+
printHelp();
12+
throw new RuntimeException(exception);
13+
}
1514
}
1615

17-
@Command(name = "PolyglotHello", mixinStandardHelpOptions = true)
18-
private int polyglotHello(
19-
@Option(names = {"-l", "--language"}, required = true, description = "Valid values are: ${COMPLETION-CANDIDATES}")
20-
Language language
21-
) {
22-
println(Greeting.byLanguage(language).getGreeting());
23-
return CommandLine.ExitCode.OK;
16+
void sayHello(ParsedArgs parsedArgs) {
17+
if (parsedArgs.hasHelpFlag()) {
18+
printHelp();
19+
} else {
20+
println(parsedArgs.getLanguage().getGreeting());
21+
}
22+
}
23+
24+
void printHelp() {
25+
println("Usage: Application [--language %s | %s] [--help]".formatted(Language.French, Language.English));
2426
}

src/main/java/Language.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import module java.base;
2+
3+
enum Language {
4+
5+
French("Bonjour", new int[]{0x1F1EB, 0x1F1F7}),
6+
English("Hello", new int[]{0x1F1EC, 0x1F1E7});
7+
8+
private final String message;
9+
private final int[] emoji;
10+
11+
Language(String message, int[] emoji) {
12+
this.message = message;
13+
this.emoji = emoji;
14+
}
15+
16+
String getGreeting() {
17+
return "%s %s%s".formatted(message, Character.toString(emoji[0]), Character.toString(emoji[1]));
18+
}
19+
20+
static Optional<Language> fromString(String language) {
21+
return Arrays.stream(values())
22+
.filter(current_language -> current_language.name().equalsIgnoreCase(language))
23+
.findFirst();
24+
}
25+
26+
static void validate(String language) {
27+
fromString(language)
28+
.orElseThrow(() -> new IllegalArgumentException("Unknown language provided: %s".formatted(language)));
29+
}
30+
}

src/main/java/ParsedArgs.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import module java.base;
2+
3+
record ParsedArgs(Optional<String> language, Optional<Boolean> help) {
4+
5+
ParsedArgs {
6+
language.ifPresent(Language::validate);
7+
}
8+
9+
boolean hasHelpFlag() {
10+
return help.orElse(false);
11+
}
12+
13+
Language getLanguage() {
14+
return language
15+
.flatMap(Language::fromString)
16+
.orElse(Language.French);
17+
}
18+
}

src/main/java/language/api/Greeting.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/main/java/language/en/Hello.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/main/java/language/fr/Bonjour.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)