What is new in Spring Boot 2.2?

 “First do it, then do it right, then do it better.“ (Addy Osmani)

Spring Boot 2.2 has recently been released and comes out with a range of new features. Among the dependency upgrades for quite a large number of Spring projects, some more changes in Spring Boot 2.2 are as follows:

  • Support for Java 13
  • JUnit 5
  • Jakarta EE dependencies
  • Lazy initialization
  • RSocket support
  • Hibernate dialect
  • Kubernetes detection
  • And others like: Health indicator groups, AssertJ 3.12, Spring HATEOAS 1.0, DataSize migration, Elasticsearch, Actuator HTTP Trace and Auditing, Gradle requirements, Jetty logging configuration, Hamcrest 2.1, Freemarker templates configuration, HttpHiddenMethodFilter disabled by default, Health Indicator, Test Application Arguments, Banners …

I decided not to describe every feature in detail but to focus on the changes I found to be the most interesting.

Deprecations

To begin with, I’d like to draw your attention to the deprecations introduced in Spring Boot 2.1 that have been completely removed in the new version (2.2). Therefore, if you want to migrate from older versions you have to get rid of all the deprecated methods used in your project.

You can find more information by searching the list of classes, methods, interfaces and other deprecated contents by accessing the Spring docs web page. (for example: https://docs.spring.io/spring-boot/docs/current/api/deprecated-list.html)

Java 13 support

An interesting part of Spring Boot is the fact that it not only supports Java 8 and 11 but it is also compatible with the new Java 13 version that has been released very recently (as of September, 17th 2019).

JUnit Jupiter (JUnit 5)

The feature-rich unit testing library JUnit 5 has been added as default support to the Spring Boot 2.2 Starter Application. This means that JUnit 5 is the default test library dependency.

The following Wrappers should be used in order to run the test:

  • Maven Wrapper: ./mvnw clean test
  • Gradle Wrapper: ./gradlew clean test

If you access the Spring Boot starter page http://start.spring.io and generate a project, you will find out that the created project contains all the required dependencies for JUnit 5.

(https://start.spring.io

The generated demo test class is shown below:

package com.helloworld.example;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class HelloWorldApplicationTests

        @Test
        void contextLoads() {
        }
}

Furthermore, if you are still using JUnit 4 and want to migrate to the new Spring Boot version you don’t have to worry or migrate everything to JUnit 5 because JUnit 5’s engine supports existing JUnit 4 test classes.

Supposing that you use Maven with the Maven Surefire plugin for JUnit 4, there are some things such as the listener property you have take into consideration. For an example of this, you can refer to the release notes for Spring Boot 2.2.

Another key point to take into consideration is the creation of Spring Boot tests. First of all, you can create a Spring Boot test utilizing a web server that runs on a random port (@LocalServerPort) or using a web server running on a random port with a mocked dependency (@MockBean). Secondly, you can create a Spring Boot test with a mocked layer using the following annotation: @AutoConfigureMockMvc.

Other test dependency upgrades for Spring Boot 2.2 are AssertJ 3.13.2, Hamcrest 2.1, and Mockito 3.1.0.

Jakarta EE dependencies

If you haven’t heard of Jakarta EE that’s not a worry. Jakarta EE is the specification for Java Enterprise Edition going forward. Jakarta EE is Java’s key for the focus on cloud computing. If you are interested in this subject you can read the articles from the https://www.eclipse.org newsletter.

Getting back to our topic, in Spring Boot 2.2 some of the dependencies have been moved from Java EE to Jakarta EE dependencies:   

  • javax group ID -> jakarta group ID

Notice that you now should move to the Jakarta EE API dependencies because the Java EE API dependencies will ultimately be eliminated.

Lazy Initialization

A new property has been introduced in Spring Boot 2.2 in order to enable the lazy initialization. This is also possible in older versions but the process to have the lazy initialization enabled is quite difficult because you need to write a BeanFactoryPostProcessor. In Spring Boot 2.2 you can enable it by setting the spring.main.lazy-initialization to true.

Its advantages are the reduced start-up times because fewer classes are loaded and fewer beans are created during the application startup.

If you wonder why I didn’t mention Spring Boot’s DevTools, here is the answer: Spring Boot already contains DevTools that helps increase your productivity. Instead of restarting the JVM and application every time a new change was made, DevTools uses hot restart in the same JVM instance. Even if the original time is reduced by 80% after the restart, when using spring.main.lazy-initialization it decreases even more, by 64% directly in the IDE.

But why is it not enabled by default?

This can produce problems that should have been pointed out at start-up because there are classes that won’t load anymore or beans that are not created until they are necessary. The produced errors should include:

  • NoClassDefFoundError
  • OutOfMemoryError
  • Failures due to misconfiguration

In order to enable the lazy initialization, you must add the following line to the configuration file:

spring.main.lazy-initialization=true

This applies to all beans.

If you need this configuration for all beans except one (or more) you can use: @Lazy(false). Moreover, if you need one specific bean to be configured with lazy initialization,  the @Lazy annotation should be used.

The @Lazy annotation is applied as follows. If a class is annotated with @Lazy, it means that all the methods annotated with @Bean will be lazy. For instance, in the example below only the address will be loaded lazily.

@Lazy
@Configuration
public class HelloWorld {

    @Bean
    public Address getAddress() {
        return new Address();
    }

    public Name getName() {
        return new Name();
    }

    public Company getCompany() {
        return new Company();
    }
}

If @Lazy is removed from the class and is added to a @Bean declaration, it means that the lazy loading only affects that specific bean.

@Configuration
public class HelloWorld {

    @Bean
    @Lazy(true)
    public Address getAddress() {
        return new Address();
    }

    public Name getName() {
        return new Name();
    }
}

Kubernetes detection

Kubernetes is an Open Source container management tool by Google.

Notable is the fact that by using @ConditionalOnCloudPlatform on a class you can check if the application is running on Kubernetes.

@ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES)
public class DemoApplication {
    //…
}

Other new features and performance improvements include the fact that configuration properties now support constructor-based binding, the ability to group health indicators and an extensive self-configuration of Spring Boot’s RSocket implementation.  RSocket is an application protocol that provides Reactive Streams semantics. spring-boot-starter-rsocket is now part of Spring Boot starter.

All things considered, I think you should definitely try out Spring Boot 2.2 in order to code more comfortably.

Views All Time
2385
Views Today
3
Short URL for this post: https://blog.oio.de/2ZlNp
This entry was posted in Spring Universe and tagged , . Bookmark the permalink.

Leave a Reply

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