Spring Boot 3.4 was released on the 21st of November 2024, and once again it contains a lot of useful enhancements.

Spring Boot 3.4 - What to keep an eye on? - spring screen removebg

Once again, there’s a large focus on observability, which helps us ensure our quality and get to Josh Long’s favourite place (production). Furthermore, the Testcontainer integration has been improved, enhancing our testing capacity and fully running our applications. We also get more granular control, thus increasing the security of our applications.

We also see some upgrades, I recommend especially paying attention to the bean validation and buildpack changes.

Enhancements: Spring Boot 3.4

As always, we get some useful new features to enhance our applications with.

Virtual threads

Spring and its ecosystem are further embracing Virtual Threads.

Both OtlpMeterRegistry, and the Undertow web server now make use of Virtual threads if they’re enabled.

Observability Improvements

Beyond the structured logging enhancements we discussed in our previous blog which added out-of-the-box support for ECS and Logstash, there are further improvements.

Graylog Extended Log Format (GELF) is now also supported by structured logging.

And the ProcessInfoContributor now also provides us with information about heap and non-heap usage.

{
  "version": "1.1",
  "host": "digma.org",
  "short_message": "A short observability message",
  "full_message": "A longer\n\nmultiline message",
  "timestamp": 1385053862.3072,
  "level": 1,
  "_user_id": 9001,
  "_some_info": "digmaInfo",
  "_some_env_var": "digmaProd"
}

OTLP spans can now be sent over gRPC by updating the management.otlp.tracing.transport (with http as default) to grpc, and service connection support for this has been added as well.

OTLP logging now also has support for Docker Compose and Testcontainers.

Application grouping

The new property spring.application.group allows us to group related (business unit, part of) together. This property, if configured will be included in our logging (which can be adapted by changing logging.include-application.group). Furthermore, it’ll also be automatically added to our OpenTelemetry Resource.

AssertJ Support for MockMvc

When AssertJ is on the classpath we now get autoconfiguration for MockMvcTester. This MockMvc alternative allows us to define our requests and assertions using a Fluent API. More details can be found in the Spring Boot – MockMvc – AssertJ documentation.

New properties

Three properties have been added to manage trace exporting in a more fine-grained manner for the respective systems:

  • management.otlp.tracing.export.enabled
  • management.wavefront.tracing.export.enabled
  • management.zipkin.tracing.export.enabled

And we can now also autoconfigure OpenTelemetry’s OtlpHttpLogRecordExporter and SdkLoggerProvider.

Embedded broker support for ActiveMQ classic

Since ActiveMQ classic once again supports an embedded broker, the autoconfiguration has been updated to support it. Do keep in mind that the starter is client only, so you’ll need to add org.apache.activemq:activemq-broker to use the embedded broker.

Apache pulsar

We can now further manage Apache Pulsar.

The autoconfigured PulsarContainerFactory can be customized by implementing the new PulsarContainerFactoryCustomizer interface.

The autoconfigured Pulsar listener container name is now managed by spring.pulsar.consumer.subscription.name.

Three new configuration properties have also been added:

  • spring.pulsar.client.threads.io controls the number of threads used for handling connections to brokers
  • spring.pulsar.client.threads.listener controls the number of threads used for message listeners
  • spring.pulsar.listener.concurrency controls the concurrency of the autoconfigured Pulsar message listener container

Image building improvements

When building Open Container Initiative (OCI) images we can now make use of the trustBuilder option with the respective Maven and Gradle plugins. This option allows us to control how the Cloud Native Buildpacks (CNB) lifecycle is invoked which provides us with enhanced security when using builders from untrusted sources. By default, only builders from the Paketo project, Heroku, and Google are trusted.

Docker compose enhancements

We can now pass in additional command line arguments to Docker Compose when starting and stopping services by making use of the new properties spring.docker.compose.start.arguments and spring.docker.compose.stop.arguments.

Furthermore, the POSTGRES_HOST_AUTH_METHOD=trust environment variable is now supported.

Testcontainer improvements

Testcontainer support keeps improving in Spring, this release adds:

  • Redis Stack (Server) support through the redis/redis-stack(-server) image
  • org.testcontainers.kafka.KafkaContainer support

Connection details

A HazelCast implementation has been added. ConnectionDetails were added in Spring Boot 3.1 and models the connection to a remote service.

Autoconfiguration management

Support for deprecating and replacing autoconfiguration classes has been added by declaring them in the new META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements file. It will define the link between the old and new class. You can find more details in the reference documentation.

Fallback beans

We can now define a @Fallback bean for @ConditionalOnSingleCandidate. It will be matched if there’s a single primary beans, or in case of no primary beans if there’s a single non-fallback bean.

Upgrading

There are certain things we will need to keep in mind when we’re upgrading our application, some noteworthy ones are:

Bean validation

An important change to keep in mind if you’re using @Validated @ConfigurationProperties is that as of this releas, the Bean Validation specification is properly followed. Whereas before this release, validation of nested properties happened as they were bound, now the validation only cascades down as expected when the field is annotated with @Valid.

Bean-based conditions

When a @Bean method is annotated with @ConditionalOnBean or @ConditionalOnMissingBean where the annotation attribute has been set, it will now behave consistently as when the name, type, or value has been set. Before 3.4 it used the return type of the method as the default type to match. To restore the old behaviour you will need to set a value that is the return type of the`@Bean` method and annotation.

RestClient and RestTemplate

Autoconfiguration support Reactor Netty’s HttpClient and JDK`s HttpClient have been added for RestClient and RestTemplate .

The following order of precedence is applied for the supported clients:

  1. Apache HTTP Components (HttpComponentsClientHttpRequestFactory)
  2. Jetty Client (JettyClientHttpRequestFactory)
  3. Reactor Netty HttpClient (ReactorClientHttpRequestFactory)
  4. JDK HttpClient (JdkClientHttpRequestFactory)
  5. Simple JDK HttpURLConnection (SimpleClientHttpRequestFactory)

In case you want to select a particular one, then you can set spring.http.client.factory to one of the following: http-components, jetty, reactor, jdk or simple.

And these all follow redirects by default, which can be changed by setting spring.http.client.redirects to dont-follow.

DynamicPropertyRegistry deprecation

Dynamic property injection by using DynamicPropertyRegistry has been deprecated, and will now fail by default. Instead, we should implement a @Bean method that returns a DynamicPropertyRegistrar to inject the container from which the properties should be sourced. This resolve some container lifecycle issues, and ascertains that the source containers have started before the property is used.

@Bean
DynamicPropertyRegistrar apiPropertiesRegistrar(SomeSource someSource) {
    return registry -> registry.add("someSource.someProperty", someSource::getSomeProperty);
}

If we wish to keep the legacy behaviour we can set spring.testcontainers.dynamic-property-registry-injection to either warn or allow where the former will log a warning, and the latter restores the Spring Boot 3.3 behaviour.

More granular Actuator access control

The original on-off support has been augmented with a read-only mode to enhance security.

To facilitate this some properties have been deprecated

  • management.endpoints.enabled-by-default in favour of management.endpoints.access.default
  • management.endpoint.<id>.enabled in favour of management.endpoint.<id>.access

On the @Endpoint annotation, the enableByDefault attribute has also been deprecated in favour of the new defaultAccess attribute.

Important to keep in mind is that enabled-by-default is now applied consistently regardless of the use of @ConditionalOnEnabledEndpoint. Thus I an endpoint becomes unavailable after your upgrade you will need to do one of the following:

  • set management.endpoint.<id>.access to read-only or unrestricted
  • set management.endpoint.<id>.enabled to true

And a new property has been added: management.endpoints.access.max-permitted. It allows an operator to manage the permitted access level to Actuator endpoints by defining the maximum level of access.

For example:

management.endpoint.loggers.access=unrestricted

management.endpoints.access.max-permitted=readonly

This will result in only read-only access to the logger endpoint being allowed.

OkHttp Dependency is no longer managed

If our application directly depends on OkHttp we will need to specify a version as Spring Boot no longer depends on it.

@AutoConfigureTestDatabase

If we’re using containerized databases we no longer need to add replace=Replace.NONE as there’s now autodetection for container usage. We can apply replace=Replace.AUTO_CONFIGURED to revert to the old behaviour.

Graceful shutdown by default

Embedded webservers will now shut down gracefully by default, if you preferred the old behaviour you can set server.shutdown to immediate.

Gradle 8

The minimum supported version has shifted to 8.4, and Gradle 7 remains at 7.6.4 and later.

Cloud-native buildpacks

The default cloud native buildpack builder used when we are using the build image goal in Gradle or Maven has changed from paketobuildpacks/builder-jammy-base to paketobuildpacks/builder-jammy-java-tiny. This will result in smaller images, one important thing to keep in mind is that out of the box tiny does not include a shell, so if you require a start script then you’ll need to customize the builder as documented here for Maven or Gradle

Deprecations

  • The Spring Boot managed org.webjars:webjars-locator-core dependency support has been deprecated in favour of org.webjars:webjars-locator-lite. This dependency is used for faster startup times and assert resolution when using WebJars ( documentation for this feature).
  • OtlpAutoConfiguration has been deprecated in favour of OtlpTracingAutoConfiguration

Varia

There have been a lot of minor changes, for which I recommend checking out the release notes. Some interesting ones are:

  • A new spring.data.web.pageable.serialization-mode property to configure the spring data web serialization mode
  • Registered @ConfigurationProperties beans now respect @DependsOn, @Description, @Fallback, @Lazy, @Primary, @Scope and @Role annotations.
  • Support for Testcontainer’s RedisContainer has been added
  • Autoconfiguration for MockMvcTester is now provided when AssertJ is on the classpath.

Personal thoughts

It’s nice to see the direction the framework’s evolving with the strong focus on observability and developer productivity engineering.

Juergen Hoeller also released some information on what we can look forward to In Spring framework 7.0 on his recent blog post From Spring Framework 6.2 to 7.0.

As always, I recommend perusing the Spring Boot 3.4 release notes. There are certainly more interesting things to peruse in there, and as always the Spring team has done a magnificent job of documenting the (dependency) changes.

Getting in Touch

I’m always happy to receive feedback, and questions, or engage in an interesting conversation. Feel free to check out my recent blog, where I shared tips for structured logging in Spring Boot 3.4.

In case you want to reach out I can be found at:

Get Digma

Spread the news:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *