Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2b7f6f3
Address new warnings from NullAway 0.13.6
msridhar Jun 5, 2026
8715efc
Polish "Address new warnings from NullAway 0.13.6"
wilkinsona Jun 24, 2026
5a8ecdf
Merge pull request #50701 from msridhar
wilkinsona Jun 24, 2026
fa371e8
Merge branch '4.0.x'
wilkinsona Jun 24, 2026
0acd43d
Update web starter documentation
doehyunbaek Jun 20, 2026
e612907
Merge pull request #50842 from doehyunbaek
wilkinsona Jun 24, 2026
6a7c783
Merge branch '4.0.x'
wilkinsona Jun 24, 2026
9a2fb47
Fix forwarded headers property in cloud deployment docs
doehyunbaek Jun 12, 2026
8f217b4
Polish "Fix forwarded headers property in cloud deployment docs"
wilkinsona Jun 24, 2026
cd562c1
Merge pull request #50841 from doehyunbaek
wilkinsona Jun 24, 2026
3a5f796
Merge branch '4.0.x'
wilkinsona Jun 24, 2026
f7c2c0b
Align documentation with changes made during 4.1's development
doehyunbaek Jun 20, 2026
f61b91c
Merge pull request #50800 from doehyunbaek
wilkinsona Jun 24, 2026
248f6ee
Align docs with recent changes
doehyunbaek Jun 12, 2026
0bf6964
Merge pull request #50759 from doehyunbaek
wilkinsona Jun 24, 2026
8eb3b03
Treat empty JWK Set URI as absent
codingkiddo Jun 11, 2026
a495492
Polish "Treat empty JWK Set URI as absent"
wilkinsona Jun 24, 2026
4fe692e
Merge pull request #50755 from codingkiddo
wilkinsona Jun 24, 2026
185b446
Merge branch '4.0.x'
wilkinsona Jun 24, 2026
463d68c
Fix duplicate word typos in documentation
vipi-n Jun 10, 2026
65097a4
Merge pull request #50738 from vipi-n
wilkinsona Jun 24, 2026
73010ce
Merge branch '4.0.x'
wilkinsona Jun 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ include::example$running/devtools-pom.xml[tags=devtools]

When `devtools` is running, it detects changes when you recompile your application and automatically refreshes it.
This works for not only resources but code as well.
It also provides a LiveReload server so that it can automatically trigger a browser refresh whenever things change.

Devtools can also be configured to only refresh the browser whenever a static resource has changed (and ignore any change in the code).
Just include the following property in your project:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public <T> AbstractObjectArrayAssert<?, String> getBeanNames(Class<T> type) {
* given type
*/
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(Class<T> type) {
public <T> AbstractObjectAssert<?, @Nullable T> getBean(Class<T> type) {
return getBean(type, Scope.INCLUDE_ANCESTORS);
}

Expand All @@ -273,7 +273,7 @@ public <T> AbstractObjectAssert<?, T> getBean(Class<T> type) {
* given type
*/
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(Class<T> type, Scope scope) {
public <T> AbstractObjectAssert<?, @Nullable T> getBean(Class<T> type, Scope scope) {
Assert.notNull(scope, "'scope' must not be null");
if (this.startupFailure != null) {
throwAssertionError(
Expand Down Expand Up @@ -334,7 +334,7 @@ private boolean isPrimary(String name, Scope scope) {
* @throws AssertionError if the application context did not start
*/
@CheckReturnValue
public AbstractObjectAssert<?, Object> getBean(String name) {
public AbstractObjectAssert<?, @Nullable Object> getBean(String name) {
if (this.startupFailure != null) {
throwAssertionError(
contextFailedToStartWhenExpecting(this.startupFailure, "to contain a bean of name:%n <%s>", name));
Expand Down Expand Up @@ -362,7 +362,7 @@ public AbstractObjectAssert<?, Object> getBean(String name) {
*/
@SuppressWarnings("unchecked")
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type) {
public <T> AbstractObjectAssert<?, @Nullable T> getBean(String name, Class<T> type) {
if (this.startupFailure != null) {
throwAssertionError(contextFailedToStartWhenExpecting(this.startupFailure,
"to contain a bean of name:%n <%s> (%s)", name, type));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private ResponseFieldsSnippet processInfo() {
fieldWithPath("memory.nonHeap.max")
.description("Maximum number of bytes that can be used by the JVM (or -1)."),
fieldWithPath("memory.garbageCollectors").description("Details for garbage collectors."),
fieldWithPath("memory.garbageCollectors[].name").description("Name of of the garbage collector."),
fieldWithPath("memory.garbageCollectors[].name").description("Name of the garbage collector."),
fieldWithPath("memory.garbageCollectors[].collectionCount")
.description("Total number of collections that have occurred."),
fieldWithPath("virtualThreads")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ In this section, we look at what it takes to get the xref:tutorial:first-applica
Support for xref:how-to:webserver.adoc#howto.webserver.use-behind-a-proxy-server[forwarded headers] should only be enabled when the application receives traffic from a trusted HTTP proxy, and is only directly accessible from a trusted network.
When running on a cloud platform, forward headers are enabled automatically.
This builds on the assumption that the platform will ensure that individual application instances will only be directly accessible from a trusted network.
If that is not the case for your specific platform, set `spring.forward-headers-strategy` to `none`.
If that is not the case for your specific platform, set configprop:server.forward-headers-strategy[] to `none`.


[[howto.deployment.cloud.cloud-foundry]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ This section answers questions about how it works.
== Reload Static Content

There are several options for hot reloading.
The recommended approach is to use xref:reference:using/devtools.adoc[`spring-boot-devtools`], as it provides additional development-time features, such as support for fast application restarts and LiveReload as well as sensible development-time configuration (such as template caching).
The recommended approach is to use xref:reference:using/devtools.adoc[`spring-boot-devtools`], as it provides additional development-time features, such as support for fast application restarts as well as sensible development-time configuration (such as template caching).
Devtools works by monitoring the classpath for changes.
This means that static resource changes must be "built" for the change to take effect.
By default, this happens automatically in Eclipse when you save your changes.
In IntelliJ IDEA, the Make Project command triggers the necessary build.
Due to the xref:reference:using/devtools.adoc#using.devtools.restart.excluding-resources[default restart exclusions], changes to static resources do not trigger a restart of your application.
They do, however, trigger a live reload.

Alternatively, running in an IDE (especially with debugging on) is a good way to do development (all modern IDEs allow reloading of static resources and usually also allow hot-swapping of Java class changes).

Finally, the xref:build-tool-plugin:index.adoc[Maven and Gradle plugins] can be configured (see the `addResources` property) to support running from the command line with reloading of static files directly from source.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ include-code::CityRepository[]

Spring Data JPA repositories support three different modes of bootstrapping: default, deferred, and lazy.
To enable deferred or lazy bootstrapping, set the configprop:spring.data.jpa.repositories.bootstrap-mode[] property to `deferred` or `lazy` respectively.
When using deferred or lazy bootstrapping, the auto-configured javadoc:org.springframework.boot.jpa.EntityManagerFactoryBuilder[] will use the context's javadoc:org.springframework.core.task.AsyncTaskExecutor[], if any, as the bootstrap executor.
When using deferred bootstrapping, the auto-configured javadoc:org.springframework.boot.jpa.EntityManagerFactoryBuilder[] requires a bootstrap executor and will use the context's javadoc:org.springframework.core.task.AsyncTaskExecutor[], if one can be determined.
If more than one exists, the one named `applicationTaskExecutor` will be used.

[NOTE]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ The following service connections are currently supported:
| Containers named "rabbitmq" with container port 5672 mapped

| javadoc:org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails[]
| Containers named "rabbitmq" with container port 5552 mapped
| Containers named "rabbitmq" with container port 5552 mapped, or port 5551 mapped when SSL is configured

| javadoc:org.springframework.boot.data.redis.autoconfigure.DataRedisConnectionDetails[]
| Containers named "redis", "redis/redis-stack" or "redis/redis-stack-server"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ This will happen automatically if you use Spring Boot's Gradle plugin or if you

NOTE: The use of javadoc:java.util.Optional[] with javadoc:org.springframework.boot.context.properties.ConfigurationProperties[format=annotation] is not recommended as it is primarily intended for use as a return type.
As such, it is not well-suited to configuration property injection.
For consistency with properties of other types, if you do declare an javadoc:java.util.Optional[] property and it has no value, `null` rather than an empty javadoc:java.util.Optional[] will be bound.
If you do declare an javadoc:java.util.Optional[] constructor-bound property and it has no value, an empty javadoc:java.util.Optional[] will be bound.

TIP: To use a reserved keyword in the name of a property, such as `my.service.import`, use the javadoc:org.springframework.boot.context.properties.bind.Name[format=annotation] annotation on the constructor parameter.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ As a result, specific configuration keys (such as `logback.configurationFile` fo
[[features.logging.file-rotation]]
== File Rotation

If you are using Logback of Log4J2, it is possible to fine-tune log rotation settings using your `application.properties` or `application.yaml` file.
If you are using Logback or Log4j2, it is possible to fine-tune log rotation settings using your `application.properties` or `application.yaml` file.
For all other logging system, you will need to configure rotation settings directly yourself.

The following rotation policy properties are supported for Logback:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Spring Boot supports for both Maven and Gradle protobuf plugins, but you are fre
==== Using the Maven Plugin

Spring Boot include dependency management for the `io.github.ascopes:protobuf-maven-plugin` Maven plugin.
If you are using the the `spring-boot-starter-parent` POM, you'll also get sensible out-of-the-box configuration.
If you are using the `spring-boot-starter-parent` POM, you'll also get sensible out-of-the-box configuration.

The following shows a typical Maven POM file that uses the plugin:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ For production environments, consider using a javadoc:org.springframework.securi
[[security.oauth2.client.common-providers]]
=== OAuth2 Client Registration for Common Providers

For common OAuth2 and OpenID providers (Google, Github, Facebook, and Okta), we provide a set of provider defaults.
The IDs of these common providers are `google`, `github`, `facebook`, and `okta`, respectively.
For common OAuth2 and OpenID providers (Google, Github, Facebook, X, and Okta), we provide a set of provider defaults.
The IDs of these common providers are `google`, `github`, `facebook`, `x`, and `okta`, respectively.

If you do not need to customize these providers, set the registration's `provider` property to the ID of one of the common providers.
Alternatively, you can xref:security/oauth2.adoc#security.oauth2.client[use a registration ID that matches the ID of the provider].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,11 @@ TIP: A list of the auto-configuration settings that are enabled by javadoc:org.s

The specific beans that you want to test should be specified by using the `value` or `components` attribute of javadoc:org.springframework.boot.restclient.test.autoconfigure.RestClientTest[format=annotation].

When using a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] in the beans under test and `RestTemplateBuilder.rootUri(String rootUri)` has been called when building the javadoc:org.springframework.web.client.RestTemplate[], then the root URI should be omitted from the javadoc:org.springframework.test.web.client.MockRestServiceServer[] expectations as shown in the following example:
When using a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] in the beans under test and `RestTemplateBuilder.baseUri(String baseUri)` has been called when building the javadoc:org.springframework.web.client.RestTemplate[], then the base URI should be omitted from the javadoc:org.springframework.test.web.client.MockRestServiceServer[] expectations as shown in the following example:

include-code::MyRestTemplateServiceTests[]

When using a javadoc:org.springframework.web.client.RestClient$Builder[] in the beans under test, or when using a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] without calling `rootUri(String rootURI)`, the full URI must be used in the javadoc:org.springframework.test.web.client.MockRestServiceServer[] expectations as shown in the following example:
When using a javadoc:org.springframework.web.client.RestClient$Builder[] in the beans under test, or when using a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] without calling `baseUri(String baseUri)`, the full URI must be used in the javadoc:org.springframework.test.web.client.MockRestServiceServer[] expectations as shown in the following example:

include-code::MyRestClientServiceTests[]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ For example, a javadoc:{url-testcontainers-postgresql-javadoc}/org.testcontainer
If you want to create only a subset of the applicable types, you can use the `type` attribute of javadoc:org.springframework.boot.testcontainers.service.connection.ServiceConnection[format=annotation].

To create a javadoc:org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails[] bean from a javadoc:{url-testcontainers-rabbitmq-javadoc}/org.testcontainers.rabbitmq.RabbitMQContainer[], you must opt in using the `type` attribute of javadoc:org.springframework.boot.testcontainers.service.connection.ServiceConnection[format=annotation].
The container must also expose port 5552, the RabbitMQ streams port.
The container must also expose port 5552, or port 5551 when SSL is configured, for RabbitMQ Streams.
====

By default `Container.getDockerImageName().getRepository()` is used to obtain the name used to find connection details.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Spring Boot is well suited for web application development.
You can create a self-contained HTTP server by using embedded Tomcat, Jetty, or Netty.
Most web applications use the `spring-boot-starter-web` module to get up and running quickly.
Most web applications use the `spring-boot-starter-webmvc` module to get up and running quickly.
You can also choose to build reactive web applications by using the `spring-boot-starter-webflux` module.

If you have not yet developed a Spring Boot web application, you can follow the "`Hello World!`" example in the xref:tutorial:first-application/index.adoc[Getting started] section.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ kotlinVersion=2.3.21
mavenVersion=3.9.13
mockitoVersion=5.23.0
nativeBuildToolsVersion=1.1.1
nullabilityPluginVersion=0.0.11
nullabilityPluginVersion=0.0.14
snakeYamlVersion=2.6
springGrpcVersion=1.1.0
springFrameworkVersion=7.0.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static class Registration {

/**
* Reference to the OAuth 2.0 provider to use. May reference one of the common
* providers (google, github, facebook, okta) or the ID of a custom provider
* providers (google, github, facebook, x, okta) or the ID of a custom provider
* configured using 'spring.security.oauth2.client.provider.&lt;id&gt;.*'
* properties. When not set, the ID of this registration is used to identify the
* provider.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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.
*/

package org.springframework.boot.security.oauth2.server.resource.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Conditional;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;

/**
* Condition that matches when a JWK Set URI based {@link NimbusJwtDecoder} or
* {@link NimbusReactiveJwtDecoder} should be used.
*
* @author Andy Wilkinson
* @since 4.0.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(JwkSetUriCondition.class)
public @interface ConditionalOnJwkSetUriJwtDecoder {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.
*/

package org.springframework.boot.security.oauth2.server.resource.autoconfigure;

import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;

/**
* Condition for creating a JWT decoder using a JWK Set URI.
*
* @author Vinod Kumar M
*/
class JwkSetUriCondition extends SpringBootCondition {

@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("JWK Set URI Condition");
Environment environment = context.getEnvironment();
String jwkSetUri = environment.getProperty("spring.security.oauth2.resourceserver.jwt.jwk-set-uri");
if (!StringUtils.hasText(jwkSetUri)) {
return ConditionOutcome.noMatch(message.didNotFind("jwk-set-uri property").atAll());
}
return ConditionOutcome.match(message.foundExactly("jwk-set-uri property"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down Expand Up @@ -115,7 +114,7 @@ private SignatureAlgorithm exactlyOneAlgorithm() {
}

@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
@ConditionalOnJwkSetUriJwtDecoder
JwtDecoder jwtDecoderByJwkKeySetUri() {
String jwkSetUri = this.properties.getJwkSetUri();
Assert.state(jwkSetUri != null, "No JWK Set URI property specified");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.boot.security.oauth2.server.resource.autoconfigure.ConditionalOnIssuerLocationJwtDecoder;
import org.springframework.boot.security.oauth2.server.resource.autoconfigure.ConditionalOnJwkSetUriJwtDecoder;
import org.springframework.boot.security.oauth2.server.resource.autoconfigure.ConditionalOnPublicKeyJwtDecoder;
import org.springframework.boot.security.oauth2.server.resource.autoconfigure.OAuth2ResourceServerProperties;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -122,7 +122,7 @@ private SignatureAlgorithm exactlyOneAlgorithm() {
}

@Bean
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
@ConditionalOnJwkSetUriJwtDecoder
ReactiveJwtDecoder reactiveJwtDecoderByJwkKeySetUri() {
String jwkSetUri = this.properties.getJwkSetUri();
Assert.notNull(jwkSetUri, "No JWK Set URI specified");
Expand Down
Loading
Loading