Skip to content

Commit ebdb046

Browse files
committed
Leave jar and war tasks enabled but configured with a classifier
Closes gh-23797
1 parent 3f2a069 commit ebdb046

15 files changed

+99
-89
lines changed

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging.adoc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,37 @@ NOTE: `providedRuntime` is preferred to Gradle's `compileOnly` configuration as,
4444

4545

4646

47-
[[packaging-executable-and-normal]]
48-
=== Packaging Executable and Normal Archives
49-
By default, when the `bootJar` or `bootWar` tasks are configured, the `jar` or `war` tasks are disabled.
50-
A project can be configured to build both an executable archive and a normal archive at the same time by enabling the `jar` or `war` task:
47+
[[packaging-executable-and-plain]]
48+
=== Packaging Executable and Plain Archives
49+
By default, when the `bootJar` or `bootWar` tasks are configured, the `jar` or `war` tasks are configured to use `plain` as the convention for their archive classifier.
50+
This ensures that `bootJar` and `jar` or `bootWar` and `war` have different output locations, allowing both the executable archive and the plain archive to be built at the same time.
51+
52+
If you prefer that its the executable archive, rather than the plain archive, that uses a classifier, configure the classifiers as shown in the following example for the `jar` and `bootJar` tasks:
5153

5254
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
5355
.Groovy
5456
----
55-
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=enable-jar]
57+
include::../gradle/packaging/boot-jar-and-jar-classifiers.gradle[tags=classifiers]
5658
----
5759

5860
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
5961
.Kotlin
6062
----
61-
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=enable-jar]
63+
include::../gradle/packaging/boot-jar-and-jar-classifiers.gradle.kts[tags=classifiers]
6264
----
6365

64-
65-
To avoid the executable archive and the normal archive from being written to the same location, one or the other should be configured to use a different location.
66-
One way to do so is by configuring a classifier:
66+
Alternatively, if you prefer that the plain archive isn't built at all, disable its task as shown in the following example for the `jar` task:
6767

6868
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
6969
.Groovy
7070
----
71-
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=classifier]
71+
include::../gradle/packaging/only-boot-jar.gradle[tags=disable-jar]
7272
----
7373

7474
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
7575
.Kotlin
7676
----
77-
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=classifier]
77+
include::../gradle/packaging/only-boot-jar.gradle.kts[tags=disable-jar]
7878
----
7979

8080

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/reacting.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ When Gradle's {java-plugin}[`java` plugin] is applied to a project, the Spring B
1212
1. Creates a {boot-jar-javadoc}[`BootJar`] task named `bootJar` that will create an executable, fat jar for the project.
1313
The jar will contain everything on the runtime classpath of the main source set; classes are packaged in `BOOT-INF/classes` and jars are packaged in `BOOT-INF/lib`
1414
2. Configures the `assemble` task to depend on the `bootJar` task.
15-
3. Disables the `jar` task.
15+
3. Configures the `jar` task to use `plain` as the convention for its archive classifier.
1616
4. Creates a {boot-build-image-javadoc}[`BootBuildImage`] task named `bootBuildImage` that will create a OCI image using a https://buildpacks.io[buildpack].
1717
5. Creates a {boot-run-javadoc}[`BootRun`] task named `bootRun` that can be used to run your application.
1818
6. Creates a configuration named `bootArchives` that contains the artifact produced by the `bootJar` task.
@@ -39,7 +39,7 @@ When Gradle's {war-plugin}[`war` plugin] is applied to a project, the Spring Boo
3939
1. Creates a {boot-war-javadoc}[`BootWar`] task named `bootWar` that will create an executable, fat war for the project.
4040
In addition to the standard packaging, everything in the `providedRuntime` configuration will be packaged in `WEB-INF/lib-provided`.
4141
2. Configures the `assemble` task to depend on the `bootWar` task.
42-
3. Disables the `war` task.
42+
3. Configures the `war` task to use `plain` as the convention for its archive classifier.
4343
4. Configures the `bootArchives` configuration to contain the artifact produced by the `bootWar` task.
4444

4545

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ plugins {
33
id 'org.springframework.boot' version '{gradle-project-version}'
44
}
55

6-
// tag::enable-jar[]
7-
jar {
8-
enabled = true
9-
}
10-
// end::enable-jar[]
11-
12-
// tag::classifier[]
6+
// tag::classifiers[]
137
bootJar {
148
classifier = 'boot'
159
}
16-
// end::classifier[]
10+
11+
jar {
12+
classifier = ''
13+
}
14+
// end::classifiers[]
1715

1816
bootJar {
1917
mainClass = 'com.example.Application'
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ plugins {
55
id("org.springframework.boot") version "{gradle-project-version}"
66
}
77

8-
// tag::enable-jar[]
9-
tasks.getByName<Jar>("jar") {
10-
enabled = true
11-
}
12-
// end::enable-jar[]
13-
14-
// tag::classifier[]
8+
// tag::classifiers[]
159
tasks.getByName<BootJar>("bootJar") {
1610
classifier = "boot"
1711
}
18-
// end::classifier[]
12+
13+
tasks.getByName<Jar>("jar") {
14+
classifier = ""
15+
}
16+
// end::classifiers[]
1917

2018
tasks.getByName<BootJar>("bootJar") {
2119
mainClass.set("com.example.Application")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
plugins {
2+
id 'java'
3+
id 'org.springframework.boot' version '{gradle-project-version}'
4+
}
5+
6+
// tag::disable-jar[]
7+
jar {
8+
enabled = false
9+
}
10+
// end::disable-jar[]
11+
12+
bootJar {
13+
mainClass = 'com.example.Application'
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import org.springframework.boot.gradle.tasks.bundling.BootJar
2+
3+
plugins {
4+
java
5+
id("org.springframework.boot") version "{gradle-project-version}"
6+
}
7+
8+
// tag::disable-jar[]
9+
tasks.getByName<Jar>("jar") {
10+
enabled = false
11+
}
12+
// end::disable-jar[]
13+
14+
tasks.getByName<BootJar>("bootJar") {
15+
mainClass.set("com.example.Application")
16+
}

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.gradle.api.provider.Provider;
4343
import org.gradle.api.tasks.SourceSet;
4444
import org.gradle.api.tasks.TaskProvider;
45+
import org.gradle.api.tasks.bundling.Jar;
4546
import org.gradle.api.tasks.compile.JavaCompile;
4647
import org.gradle.jvm.toolchain.JavaToolchainService;
4748
import org.gradle.jvm.toolchain.JavaToolchainSpec;
@@ -75,7 +76,7 @@ public Class<? extends Plugin<? extends Project>> getPluginClass() {
7576

7677
@Override
7778
public void execute(Project project) {
78-
disableJarTask(project);
79+
classifyJarTask(project);
7980
configureBuildTask(project);
8081
configureDevelopmentOnlyConfiguration(project);
8182
TaskProvider<BootJar> bootJar = configureBootJarTask(project);
@@ -87,8 +88,9 @@ public void execute(Project project) {
8788
configureAdditionalMetadataLocations(project);
8889
}
8990

90-
private void disableJarTask(Project project) {
91-
project.getTasks().named(JavaPlugin.JAR_TASK_NAME).configure((task) -> task.setEnabled(false));
91+
private void classifyJarTask(Project project) {
92+
project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class)
93+
.configure((task) -> task.getArchiveClassifier().convention("plain"));
9294
}
9395

9496
private void configureBuildTask(Project project) {

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.gradle.api.tasks.SourceSet;
3030
import org.gradle.api.tasks.SourceSetContainer;
3131
import org.gradle.api.tasks.TaskProvider;
32+
import org.gradle.api.tasks.bundling.War;
3233

3334
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage;
3435
import org.springframework.boot.gradle.tasks.bundling.BootWar;
@@ -54,14 +55,15 @@ public Class<? extends Plugin<? extends Project>> getPluginClass() {
5455

5556
@Override
5657
public void execute(Project project) {
57-
disableWarTask(project);
58+
classifyWarTask(project);
5859
TaskProvider<BootWar> bootWar = configureBootWarTask(project);
5960
configureBootBuildImageTask(project, bootWar);
6061
configureArtifactPublication(bootWar);
6162
}
6263

63-
private void disableWarTask(Project project) {
64-
project.getTasks().named(WarPlugin.WAR_TASK_NAME).configure((war) -> war.setEnabled(false));
64+
private void classifyWarTask(Project project) {
65+
project.getTasks().named(WarPlugin.WAR_TASK_NAME, War.class)
66+
.configure((war) -> war.getArchiveClassifier().convention("plain"));
6567
}
6668

6769
private TaskProvider<BootWar> configureBootWarTask(Project project) {

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,34 @@ void bootWarPropertiesLauncher() throws IOException {
171171
}
172172

173173
@TestTemplate
174-
void bootJarAndJar() {
175-
this.gradleBuild.script("src/docs/gradle/packaging/boot-jar-and-jar").build("assemble");
176-
File jar = new File(this.gradleBuild.getProjectDir(),
174+
void onlyBootJar() throws IOException {
175+
this.gradleBuild.script("src/docs/gradle/packaging/only-boot-jar").build("assemble");
176+
File plainJar = new File(this.gradleBuild.getProjectDir(),
177+
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-plain.jar");
178+
assertThat(plainJar).doesNotExist();
179+
File bootJar = new File(this.gradleBuild.getProjectDir(),
177180
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
178-
assertThat(jar).isFile();
181+
assertThat(bootJar).isFile();
182+
try (JarFile jar = new JarFile(bootJar)) {
183+
assertThat(jar.getEntry("BOOT-INF/")).isNotNull();
184+
}
185+
}
186+
187+
@TestTemplate
188+
void classifiedBootJar() throws IOException {
189+
this.gradleBuild.script("src/docs/gradle/packaging/boot-jar-and-jar-classifiers").build("assemble");
190+
File plainJar = new File(this.gradleBuild.getProjectDir(),
191+
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
192+
assertThat(plainJar).isFile();
193+
try (JarFile jar = new JarFile(plainJar)) {
194+
assertThat(jar.getEntry("BOOT-INF/")).isNull();
195+
}
179196
File bootJar = new File(this.gradleBuild.getProjectDir(),
180197
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-boot.jar");
181198
assertThat(bootJar).isFile();
199+
try (JarFile jar = new JarFile(bootJar)) {
200+
assertThat(jar.getEntry("BOOT-INF/")).isNotNull();
201+
}
182202
}
183203

184204
@TestTemplate

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -92,10 +92,14 @@ void javaCompileTasksCanOverrideDefaultParametersCompilerFlag() {
9292
}
9393

9494
@TestTemplate
95-
void assembleRunsBootJarAndJarIsSkipped() {
95+
void assembleRunsBootJarAndJar() {
9696
BuildResult result = this.gradleBuild.build("assemble");
9797
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
98-
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
98+
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
99+
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
100+
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
101+
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"),
102+
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-plain.jar"));
99103
}
100104

101105
@TestTemplate
@@ -105,17 +109,6 @@ void errorMessageIsHelpfulWhenMainClassCannotBeResolved() {
105109
assertThat(result.getOutput()).contains("Main class name has not been configured and it could not be resolved");
106110
}
107111

108-
@TestTemplate
109-
void jarAndBootJarCanBothBeBuilt() {
110-
BuildResult result = this.gradleBuild.build("assemble");
111-
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
112-
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
113-
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
114-
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
115-
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"),
116-
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-boot.jar"));
117-
}
118-
119112
@TestTemplate
120113
void additionalMetadataLocationsConfiguredWhenProcessorIsPresent() throws IOException {
121114
createMinimalMainSource();

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,21 +50,14 @@ void applyingWarPluginCreatesBootWarTask() {
5050
}
5151

5252
@TestTemplate
53-
void assembleRunsBootWarAndWarIsSkipped() {
54-
BuildResult result = this.gradleBuild.build("assemble");
55-
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
56-
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
57-
}
58-
59-
@TestTemplate
60-
void warAndBootWarCanBothBeBuilt() {
53+
void assembleRunsBootWarAndWar() {
6154
BuildResult result = this.gradleBuild.build("assemble");
6255
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
6356
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
6457
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
6558
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
6659
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"),
67-
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-boot.war"));
60+
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-plain.war"));
6861
}
6962

7063
@TestTemplate

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests-jarAndBootJarCanBothBeBuilt.gradle

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

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/WarPluginActionIntegrationTests-warAndBootWarCanBothBeBuilt.gradle

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

0 commit comments

Comments
 (0)