Leave jar and war tasks enabled but configured with a classifier

Closes gh-23797
pull/25690/head
Andy Wilkinson 4 years ago
parent 3f2a069e71
commit ebdb046ca9

@ -44,37 +44,37 @@ NOTE: `providedRuntime` is preferred to Gradle's `compileOnly` configuration as,
[[packaging-executable-and-normal]]
=== Packaging Executable and Normal Archives
By default, when the `bootJar` or `bootWar` tasks are configured, the `jar` or `war` tasks are disabled.
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:
[[packaging-executable-and-plain]]
=== Packaging Executable and Plain Archives
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.
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.
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:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=enable-jar]
include::../gradle/packaging/boot-jar-and-jar-classifiers.gradle[tags=classifiers]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=enable-jar]
include::../gradle/packaging/boot-jar-and-jar-classifiers.gradle.kts[tags=classifiers]
----
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.
One way to do so is by configuring a classifier:
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:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=classifier]
include::../gradle/packaging/only-boot-jar.gradle[tags=disable-jar]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=classifier]
include::../gradle/packaging/only-boot-jar.gradle.kts[tags=disable-jar]
----

@ -12,7 +12,7 @@ When Gradle's {java-plugin}[`java` plugin] is applied to a project, the Spring B
1. Creates a {boot-jar-javadoc}[`BootJar`] task named `bootJar` that will create an executable, fat jar for the project.
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`
2. Configures the `assemble` task to depend on the `bootJar` task.
3. Disables the `jar` task.
3. Configures the `jar` task to use `plain` as the convention for its archive classifier.
4. Creates a {boot-build-image-javadoc}[`BootBuildImage`] task named `bootBuildImage` that will create a OCI image using a https://buildpacks.io[buildpack].
5. Creates a {boot-run-javadoc}[`BootRun`] task named `bootRun` that can be used to run your application.
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
1. Creates a {boot-war-javadoc}[`BootWar`] task named `bootWar` that will create an executable, fat war for the project.
In addition to the standard packaging, everything in the `providedRuntime` configuration will be packaged in `WEB-INF/lib-provided`.
2. Configures the `assemble` task to depend on the `bootWar` task.
3. Disables the `war` task.
3. Configures the `war` task to use `plain` as the convention for its archive classifier.
4. Configures the `bootArchives` configuration to contain the artifact produced by the `bootWar` task.

@ -3,17 +3,15 @@ plugins {
id 'org.springframework.boot' version '{gradle-project-version}'
}
// tag::enable-jar[]
jar {
enabled = true
}
// end::enable-jar[]
// tag::classifier[]
// tag::classifiers[]
bootJar {
classifier = 'boot'
}
// end::classifier[]
jar {
classifier = ''
}
// end::classifiers[]
bootJar {
mainClass = 'com.example.Application'

@ -5,17 +5,15 @@ plugins {
id("org.springframework.boot") version "{gradle-project-version}"
}
// tag::enable-jar[]
tasks.getByName<Jar>("jar") {
enabled = true
}
// end::enable-jar[]
// tag::classifier[]
// tag::classifiers[]
tasks.getByName<BootJar>("bootJar") {
classifier = "boot"
}
// end::classifier[]
tasks.getByName<Jar>("jar") {
classifier = ""
}
// end::classifiers[]
tasks.getByName<BootJar>("bootJar") {
mainClass.set("com.example.Application")

@ -0,0 +1,14 @@
plugins {
id 'java'
id 'org.springframework.boot' version '{gradle-project-version}'
}
// tag::disable-jar[]
jar {
enabled = false
}
// end::disable-jar[]
bootJar {
mainClass = 'com.example.Application'
}

@ -0,0 +1,16 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{gradle-project-version}"
}
// tag::disable-jar[]
tasks.getByName<Jar>("jar") {
enabled = false
}
// end::disable-jar[]
tasks.getByName<BootJar>("bootJar") {
mainClass.set("com.example.Application")
}

@ -42,6 +42,7 @@ import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.jvm.toolchain.JavaToolchainService;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
@ -75,7 +76,7 @@ final class JavaPluginAction implements PluginApplicationAction {
@Override
public void execute(Project project) {
disableJarTask(project);
classifyJarTask(project);
configureBuildTask(project);
configureDevelopmentOnlyConfiguration(project);
TaskProvider<BootJar> bootJar = configureBootJarTask(project);
@ -87,8 +88,9 @@ final class JavaPluginAction implements PluginApplicationAction {
configureAdditionalMetadataLocations(project);
}
private void disableJarTask(Project project) {
project.getTasks().named(JavaPlugin.JAR_TASK_NAME).configure((task) -> task.setEnabled(false));
private void classifyJarTask(Project project) {
project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class)
.configure((task) -> task.getArchiveClassifier().convention("plain"));
}
private void configureBuildTask(Project project) {

@ -29,6 +29,7 @@ import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.bundling.War;
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage;
import org.springframework.boot.gradle.tasks.bundling.BootWar;
@ -54,14 +55,15 @@ class WarPluginAction implements PluginApplicationAction {
@Override
public void execute(Project project) {
disableWarTask(project);
classifyWarTask(project);
TaskProvider<BootWar> bootWar = configureBootWarTask(project);
configureBootBuildImageTask(project, bootWar);
configureArtifactPublication(bootWar);
}
private void disableWarTask(Project project) {
project.getTasks().named(WarPlugin.WAR_TASK_NAME).configure((war) -> war.setEnabled(false));
private void classifyWarTask(Project project) {
project.getTasks().named(WarPlugin.WAR_TASK_NAME, War.class)
.configure((war) -> war.getArchiveClassifier().convention("plain"));
}
private TaskProvider<BootWar> configureBootWarTask(Project project) {

@ -171,14 +171,34 @@ class PackagingDocumentationTests {
}
@TestTemplate
void bootJarAndJar() {
this.gradleBuild.script("src/docs/gradle/packaging/boot-jar-and-jar").build("assemble");
File jar = new File(this.gradleBuild.getProjectDir(),
void onlyBootJar() throws IOException {
this.gradleBuild.script("src/docs/gradle/packaging/only-boot-jar").build("assemble");
File plainJar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-plain.jar");
assertThat(plainJar).doesNotExist();
File bootJar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
assertThat(jar).isFile();
assertThat(bootJar).isFile();
try (JarFile jar = new JarFile(bootJar)) {
assertThat(jar.getEntry("BOOT-INF/")).isNotNull();
}
}
@TestTemplate
void classifiedBootJar() throws IOException {
this.gradleBuild.script("src/docs/gradle/packaging/boot-jar-and-jar-classifiers").build("assemble");
File plainJar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
assertThat(plainJar).isFile();
try (JarFile jar = new JarFile(plainJar)) {
assertThat(jar.getEntry("BOOT-INF/")).isNull();
}
File bootJar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-boot.jar");
assertThat(bootJar).isFile();
try (JarFile jar = new JarFile(bootJar)) {
assertThat(jar.getEntry("BOOT-INF/")).isNotNull();
}
}
@TestTemplate

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -92,10 +92,14 @@ class JavaPluginActionIntegrationTests {
}
@TestTemplate
void assembleRunsBootJarAndJarIsSkipped() {
void assembleRunsBootJarAndJar() {
BuildResult result = this.gradleBuild.build("assemble");
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"),
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-plain.jar"));
}
@TestTemplate
@ -105,17 +109,6 @@ class JavaPluginActionIntegrationTests {
assertThat(result.getOutput()).contains("Main class name has not been configured and it could not be resolved");
}
@TestTemplate
void jarAndBootJarCanBothBeBuilt() {
BuildResult result = this.gradleBuild.build("assemble");
assertThat(result.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.task(":jar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".jar"),
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-boot.jar"));
}
@TestTemplate
void additionalMetadataLocationsConfiguredWhenProcessorIsPresent() throws IOException {
createMinimalMainSource();

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -50,21 +50,14 @@ class WarPluginActionIntegrationTests {
}
@TestTemplate
void assembleRunsBootWarAndWarIsSkipped() {
BuildResult result = this.gradleBuild.build("assemble");
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SKIPPED);
}
@TestTemplate
void warAndBootWarCanBothBeBuilt() {
void assembleRunsBootWarAndWar() {
BuildResult result = this.gradleBuild.build("assemble");
assertThat(result.task(":bootWar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.task(":war").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
assertThat(buildLibs.listFiles()).containsExactlyInAnyOrder(
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"),
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-boot.war"));
new File(buildLibs, this.gradleBuild.getProjectDir().getName() + "-plain.war"));
}
@TestTemplate

@ -1,13 +0,0 @@
plugins {
id 'java'
id 'org.springframework.boot' version '{version}'
}
bootJar {
mainClass = 'com.example.Application'
classifier = 'boot'
}
jar {
enabled = true
}

@ -1,13 +0,0 @@
plugins {
id 'war'
id 'org.springframework.boot' version '{version}'
}
bootWar {
mainClass = 'com.example.Application'
classifier = 'boot'
}
war {
enabled = true
}
Loading…
Cancel
Save