Make it easier to create executable and deployable war

Closes gh-46944
This commit is contained in:
Andy Wilkinson
2025-10-22 10:13:46 +01:00
parent a3ca741c56
commit 635e766aaf
24 changed files with 112 additions and 57 deletions
@@ -24,6 +24,6 @@ apply plugin: 'io.spring.dependency-management'
// tag::dependencies[]
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
providedRuntime('org.springframework.boot:spring-boot-tomcat-runtime')
}
// end::dependencies[]
@@ -8,6 +8,6 @@ apply(plugin = "io.spring.dependency-management")
// tag::dependencies[]
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
providedRuntime("org.springframework.boot:spring-boot-tomcat-runtime")
}
// end::dependencies[]
@@ -27,7 +27,7 @@ The `assemble` task is automatically configured to depend upon the `bootWar` tas
=== Packaging Executable and Deployable Wars
A war file can be packaged such that it can be executed using `java -jar` and deployed to an external container.
To do so, the embedded servlet container dependencies should be added to the `providedRuntime` configuration, for example:
To do so, the embedded servlet runtime should be added to the `providedRuntime` configuration, for example:
[tabs]
======
@@ -45,7 +45,7 @@ include::example$packaging/war-container-dependency.gradle.kts[tags=dependencies
----
======
This ensures that they are package in the war file's `WEB-INF/lib-provided` directory from where they will not conflict with the external container's own classes.
This ensures that the runtime is packaged in the war file's `WEB-INF/lib-provided` directory from where it will not conflict with the external container's own classes.
NOTE: `providedRuntime` is preferred to Gradle's `compileOnly` configuration as, among other limitations, `compileOnly` dependencies are not on the test classpath so any web-based integration tests will fail.
@@ -33,9 +33,9 @@ apply plugin: 'war'
----
The final step in the process is to ensure that the embedded servlet container does not interfere with the servlet container to which the war file is deployed.
To do so, you need to mark the embedded servlet container dependency as being provided.
To do so, you need to mark the embedded servlet runtime dependency as being provided.
If you use Maven, the following example marks the servlet container (Tomcat, in this case) as being provided:
If you use Maven, the following example marks the servlet runtime (Tomcat, in this case) as being provided:
[source,xml]
----
@@ -43,20 +43,20 @@ If you use Maven, the following example marks the servlet container (Tomcat, in
<!-- ... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<artifactId>spring-boot-tomcat-runtime</artifactId>
<scope>provided</scope>
</dependency>
<!-- ... -->
</dependencies>
----
If you use Gradle, the following example marks the servlet container (Tomcat, in this case) as being provided:
If you use Gradle, the following example marks the servlet runtime (Tomcat, in this case) as being provided:
[source,gradle]
----
dependencies {
// ...
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
providedRuntime 'org.springframework.boot:spring-boot-tomcat-runtime'
// ...
}
----
@@ -0,0 +1,48 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
id "java-library"
id "org.springframework.boot.deployed"
}
description = "Spring Boot Jetty Runtime"
dependencies {
api("org.apache.tomcat.embed:tomcat-embed-el")
api("org.eclipse.jetty.compression:jetty-compression-gzip") {
exclude group: "org.slf4j", module: "slf4j-api"
}
api("org.eclipse.jetty.compression:jetty-compression-server") {
exclude group: "org.slf4j", module: "slf4j-api"
}
api("org.eclipse.jetty.ee11:jetty-ee11-servlets") {
exclude group: "org.slf4j", module: "slf4j-api"
}
api("org.eclipse.jetty.ee11:jetty-ee11-webapp") {
exclude group: "org.slf4j", module: "slf4j-api"
}
api("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jakarta-server") {
exclude group: "jakarta.el", module: "jakarta.el-api"
exclude group: "org.eclipse.jetty", module: "jetty-jndi"
exclude group: "org.slf4j", module: "slf4j-api"
}
api("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jetty-server") {
exclude group: "jakarta.el", module: "jakarta.el-api"
exclude group: "org.eclipse.jetty", module: "jetty-jndi"
exclude group: "org.slf4j", module: "slf4j-api"
}
}
+4 -7
View File
@@ -25,20 +25,17 @@ plugins {
description = "Spring Boot Jetty"
dependencies {
api(project(":module:spring-boot-jetty-runtime"))
api(project(":module:spring-boot-web-server"))
api("org.eclipse.jetty.ee11:jetty-ee11-servlets")
api("org.eclipse.jetty.ee11:jetty-ee11-webapp")
implementation("org.eclipse.jetty.compression:jetty-compression-server")
implementation("org.eclipse.jetty.compression:jetty-compression-gzip")
api("jakarta.servlet:jakarta.servlet-api")
api("jakarta.websocket:jakarta.websocket-api")
api("jakarta.websocket:jakarta.websocket-client-api")
optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-actuator-autoconfigure"))
optional(project(":module:spring-boot-micrometer-metrics"))
optional("org.apache.tomcat.embed:tomcat-embed-jasper")
optional("org.eclipse.jetty:jetty-alpn-conscrypt-server")
optional("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jakarta-server")
optional("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jetty-server")
optional("org.eclipse.jetty.http2:jetty-http2-server")
optional("org.springframework:spring-webflux")
@@ -0,0 +1,32 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
id "java-library"
id "org.springframework.boot.deployed"
}
description = "Spring Boot Tomcat Runtime"
dependencies {
api("org.apache.tomcat.embed:tomcat-embed-core") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
api("org.apache.tomcat.embed:tomcat-embed-el")
api("org.apache.tomcat.embed:tomcat-embed-websocket") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
}
+1 -6
View File
@@ -32,18 +32,13 @@ configurations {
dependencies {
api(project(":module:spring-boot-web-server"))
api("org.apache.tomcat.embed:tomcat-embed-core") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
api(project(":module:spring-boot-tomcat-runtime"))
optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-actuator-autoconfigure"))
optional(project(":module:spring-boot-micrometer-metrics"))
optional("io.micrometer:micrometer-core")
optional("org.apache.tomcat.embed:tomcat-embed-jasper")
optional("org.apache.tomcat.embed:tomcat-embed-websocket") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
optional("org.springframework:spring-webflux")
runtimeOnly("jakarta.annotation:jakarta.annotation-api")
@@ -2044,6 +2044,7 @@ bom {
"spring-boot-jdbc",
"spring-boot-jdbc-test",
"spring-boot-jetty",
"spring-boot-jetty-runtime",
"spring-boot-jms",
"spring-boot-jooq",
"spring-boot-jooq-test",
@@ -2252,6 +2253,7 @@ bom {
"spring-boot-testcontainers",
"spring-boot-thymeleaf",
"spring-boot-tomcat",
"spring-boot-tomcat-runtime",
"spring-boot-transaction",
"spring-boot-validation",
"spring-boot-web-server",
+2
View File
@@ -136,6 +136,7 @@ include "module:spring-boot-jackson2"
include "module:spring-boot-jdbc"
include "module:spring-boot-jdbc-test"
include "module:spring-boot-jetty"
include "module:spring-boot-jetty-runtime"
include "module:spring-boot-jms"
include "module:spring-boot-jooq"
include "module:spring-boot-jooq-test"
@@ -184,6 +185,7 @@ include "module:spring-boot-sql"
include "module:spring-boot-test-classic-modules"
include "module:spring-boot-thymeleaf"
include "module:spring-boot-tomcat"
include "module:spring-boot-tomcat-runtime"
include "module:spring-boot-transaction"
include "module:spring-boot-validation"
include "module:spring-boot-web-server"
@@ -29,7 +29,7 @@ configurations {
dependencies {
implementation(project(":starter:spring-boot-starter-webmvc"))
providedRuntime(project(":starter:spring-boot-starter-tomcat"))
providedRuntime(project(":module:spring-boot-tomcat-runtime"))
providedRuntime("org.glassfish.web:jakarta.servlet.jsp.jstl")
providedRuntime("org.apache.tomcat.embed:tomcat-embed-jasper")
@@ -27,10 +27,9 @@ configurations {
}
dependencies {
implementation(project(":starter:spring-boot-starter"))
implementation(project(":module:spring-boot-webmvc"))
implementation(project(":starter:spring-boot-starter-webmvc"))
providedRuntime(project(":starter:spring-boot-starter-tomcat"))
providedRuntime(project(":module:spring-boot-tomcat-runtime"))
providedRuntime("org.apache.tomcat.embed:tomcat-embed-jasper")
testImplementation(project(":module:spring-boot-resttestclient"))
@@ -29,7 +29,7 @@ configurations {
dependencies {
implementation(project(":starter:spring-boot-starter-webmvc"))
providedRuntime(project(":starter:spring-boot-starter-tomcat"))
providedRuntime(project(":module:spring-boot-tomcat-runtime"))
providedRuntime("org.glassfish.web:jakarta.servlet.jsp.jstl")
providedRuntime("org.apache.tomcat.embed:tomcat-embed-jasper")
@@ -29,7 +29,7 @@ configurations {
dependencies {
implementation(project(":starter:spring-boot-starter-webmvc"))
providedRuntime( project(":starter:spring-boot-starter-tomcat"))
providedRuntime(project(":module:spring-boot-tomcat-runtime"))
runtimeOnly("org.webjars:bootstrap:3.0.3")
runtimeOnly("org.webjars:jquery:2.0.3-1")
@@ -22,19 +22,5 @@ description = "Starter for using Jetty as the embedded servlet container"
dependencies {
api(project(":starter:spring-boot-starter"))
api(project(":module:spring-boot-jetty"))
api("jakarta.servlet:jakarta.servlet-api")
api("jakarta.websocket:jakarta.websocket-api")
api("jakarta.websocket:jakarta.websocket-client-api")
api("org.apache.tomcat.embed:tomcat-embed-el")
api("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jakarta-server") {
exclude group: "jakarta.el", module: "jakarta.el-api"
exclude group: "org.eclipse.jetty", module: "jetty-jndi"
}
api("org.eclipse.jetty.ee11.websocket:jetty-ee11-websocket-jetty-server") {
exclude group: "jakarta.el", module: "jakarta.el-api"
exclude group: "org.eclipse.jetty", module: "jetty-jndi"
}
}
@@ -22,12 +22,6 @@ description = "Starter for using Tomcat"
dependencies {
api(project(":starter:spring-boot-starter"))
api(project(":module:spring-boot-tomcat"))
api("jakarta.annotation:jakarta.annotation-api")
api("org.apache.tomcat.embed:tomcat-embed-el")
api("org.apache.tomcat.embed:tomcat-embed-websocket") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
}
@@ -44,7 +44,7 @@ systemTest {
dependencies {
app project(path: ":build-plugin:spring-boot-gradle-plugin", configuration: "mavenRepository")
app project(path: ":starter:spring-boot-starter-web", configuration: "mavenRepository")
app project(path: ":starter:spring-boot-starter-webmvc", configuration: "mavenRepository")
implementation(project(":starter:spring-boot-starter-webmvc")) {
exclude group: "org.hibernate.validator"
@@ -37,7 +37,7 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
bootJar {
@@ -41,7 +41,7 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
bootJar {
@@ -37,8 +37,8 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
providedRuntime("org.springframework.boot:spring-boot-tomcat-runtime:{bootVersion}")
}
bootWar {
@@ -42,7 +42,7 @@ tasks.named("bootBuildImage") {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
bootJar {
@@ -37,7 +37,7 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
bootJar {
@@ -37,7 +37,7 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
war {
@@ -36,7 +36,7 @@ repositories {
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:{bootVersion}")
implementation("org.springframework.boot:spring-boot-starter-webmvc:{bootVersion}")
}
bootJar {