Skip to content

Spring Framework 6.2 Release Notes

Sam Brannen edited this page Nov 11, 2024 · 24 revisions

Upgrading From Spring Framework 6.1

Baseline upgrades

Spring Framework 6.2 raises its minimum requirements with the following libraries:

  • For GraalVM native image support only, Hibernate 6.5
  • FreeMarker 2.3.33
  • HtmlUnit 4.2
  • Codecs and converters now officially support Protobuf 4.x, raising our baseline to Protobuf 3.29.

We also recommend an upgrade to Jackson 2.18 while preserving runtime compatibility with Jackson 2.15+ for the time being.

Removed APIs

Several deprecated classes, constructors, and methods have been removed across the code base. See 30608, 31492, and 33123.

Core Container

6.2 comes with a slightly revised autowiring algorithm where among a set of candidate beans that match by type, parameter name matches and @Qualifier("...") matches (against the target bean name) overrule @jakarta.annotation.Priority ranking whereas they were previously checked the other way around. That said, since we do not recommend mixing and matching those qualification mechanisms and generally do not recommend @Priority for identifying single candidates (rather just for ranking multiple candidates in an injected collection), we do not expect common regressions here. Note that @Primary beans always come first (and as a side note, 6.2 introduces the notion of @Fallback beans as well).

6.2 also comes with deeper generic type matching. If an injection point that previously matched does not match anymore, double-check your generic signatures at that injection point (e.g. your constructor argument) and for the bean type on the bean definition (e.g. the return type of your @Bean method). Spring is effectively less lenient in accepting fallback matches now, insisting on the resolvable part of the type signature to match even if the remaining part is leniently accepted with unresolvable type variables or wildcards.

Component scanning happens early in the BeanFactory initialization and, as such, is not suitable to be guarded by a condition that is evaluated late. We now fail hard if you use @ComponentScan with a REGISTER_BEAN condition (such as Spring Boot's @ConditionalOnBean).

We've made it clearer that bean definition overriding is discouraged in production code, and the container now logs each override at INFO level. While not recommended, you can silence those logs by setting the allowBeanDefinitionOverriding flag to true on the bean factory or application context before it is refreshed.

Web Applications

org.webjars:webjars-locator-core support implemented in WebJarsResourceResolver is deprecated due to efficiency issues as of Spring Framework 6.2 and is superseded by org.webjars:webjars-locator-lite support implemented in LiteWebJarsResourceResolver.

Messaging Applications

The JMS DefaultMessageListenerContainer comes with revised idleReceivesPerTaskLimit semantics when using its default executor: Core threads always stay alive now, with only surplus consumers (between concurrentConsumers and maxConcurrentConsumers) timing out after the specified number of idle receives. Only in combination with a maxMessagesPerTask does idleReceivesPerTaskLimit have an effect on core consumers as well, as inferred for an external thread pool for dynamic rescheduling of all consumer tasks.

Testing

Support for HtmlUnit has moved to a new major release that requires some changes when upgrading, see Migrating from HtmlUnit 2.x.x to HtmlUnit 3.x.x for additional details. If you are using HtmlUnit with Selenium, please note that the coordinates of the driver have changed, and the version now matches the Selenium version: org.seleniumhq.selenium:htmlunit3-driver:X.Y.Z, where X.Y.Z is your Selenium version.

New and Noteworthy

Support for escaping property placeholders

Property placeholders are a way to replace a property from the environment in an arbitrary String. Assuming that customer.name is set to "John Smith" in the Environment, "Customer ${customer.name}" would resolve to "Customer John Smith". There are corner cases where you’d like to retain the original value rather than having it resolved. Spring Framework 6.2 allows you to escape a placeholder using a configurable escape character (backslash by default). Taking our previous example, "Customer \${customer.name}" resolves now to "Customer ${customer.name}".

Support for fallback beans

A fallback bean is used if no bean of that type has been provided. This is essentially a companion of @Primary without the trade-off of having to specify it. Consider that a component requires MyService to be defined. You can provide a default implementation for the service, but you’d like that if a user specifies one, it can be injected by type transparently. So far, the user had to configure their specific bean with @Primary to make sure it is used, since two beans of that type are defined now.

As of Spring Framework 6.2.0 you can craft your configuration with @Fallback:

@Configuration
class MyConfiguration {

	@Bean
	MyComponent myComponent(MyService service) {
    	//...
	}

	@Bean
	@Fallback
	MyService defaultMyService() {
    	//...
	}

}

If no other MyService bean is defined, defaultMyService is used. Otherwise, the container will pick transparently the one that’s been defined externally.

See the dedicated section in the reference documentation.

Bean Background Initialization

Individual beans can be initialized in the background using the newly introduced bootstrap attribute.

@Configuration
class MyConfiguration {

    @Bean(bootstrap = BACKGROUND)
    MyExpensiveComponent myComponent() {
   	 ...
    }

}

Check the reference guide for more details about this new feature.

Bean overriding in tests, @TestBean, @MockitoBean and @MockitoSpyBean

See our new reference documentation section on these features and the dedicated blog post published during the milestones phase.

AssertJ support for MockMvc

We love AssertJ! While Spring Boot has already jumped on that train a while ago and provides several testing facilities using it, the framework team has been more conservative. At the same time, we recognize that our Hamcrest support may not fit everyone’s needs: the use of static imports make the API less discoverable and writing custom assertions is harder. Spring Framework now provides an exhaustive support for testing your web application with MockMvc and AssertJ.

Building an MvcTester instance is more straightforward, with dedicated factory methods on the class itself. If you have a WebApplicationContext handy, this is as easy as MvcTester.from(webApplicationContext). If you want to test only a controller in a unit test, you can do so as follows:

MvcTester mvc = MvcTester.of(List.of(new HelloController()), builder ->
builder.defaultRequest(get("/hello").accept(MediaType.APPLICATION_JSON)).build());

Once you have an instance you can perform your usual requests and wrap that in AssertJ’s standard assertThat:

assertThat(mvc.perform(get("/vehicle/{id}", "12").accept(MediaType.TEXT_PLAIN)))
        .hasStatusOk()
        .body().isEqualTo("Honda Civic");

This covers the same features as the existing Hamcrest matchers, and extends it with advanced JSON support, for instance:

assertThat(mvc.perform(get("/message")))
        .body().json()
        .isLenientlyEqualTo(new ClassPathResource("samples/message.json"));

See the reference documentation for more on that.

Dynamic properties can now be registered from within a test's ApplicationContext

You can now register dynamic properties in tests by contributing DynamicPropertyRegistrar beans to the context.

See related documentation.

UrlHandlerFilter for trailing slash match

Spring Framework recently deprecated the trailing slash match option in PathMatchConfigurer, the Spring community requested a way to gracefully handle this transition period in large applications. The new UrlHandlerFilter Servlet and reactive filters will help redirecting or rewriting incoming URLs with a trailing slash "/blog/blog-title/" to "/blog/blog-title".

Check out the reference documentation for this.

New URL parser implementations

Spring Framework 6.2 introduces new URL parser implementations. One is based on an algorithm provided in the Living URL standard, the other strictly conforms to RFC 3986 syntax. They can both be used in UriComponentsBuilder for parsing URLs and this allows applications to significantly hardens the URL parsing infrastructure, in response of recent security reports.

// This is using the "strict" RFC parser
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri, ParserType.RFC).build();
// Using the "living URL" standard is more flexible and behaves similarly to browsers
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri, ParserType.WHAT_WG).build();

Content negotiation support for @ExceptionHandler methods

@ExceptionHandler methods are now more flexible as they support content negotiation during the error handling phase. This means that you can tailor error handling depending on the content type requested by the HTTP client.

Here's a code snippet showing this feature in action:

@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
    return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}

@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
    model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
    return "errorView";
}

Here, automated clients will get a JSON response, while browsers will display an HTML error page with custom messages.

Easier reflection hints registration for Native apps

We have significantly improved the developer experience of registering reflection hints. @RegisterReflection has been introduced to easily register hints against arbitrary data types, and @ReflectionScan lets you opt-in for scanning of any reflection hints on arbitrary classes, not only Spring beans. See the reference documentation section for this.

Miscellaneous

Apart from the changes listed above, there have also been a lot of minor tweaks, improvements, and bug fixes including: