Upgrading a major version is always a pain. Although from java 9 up it’s supposed to be easier. In this post I will give some examples of the obstacles I encountered. The use case is a Spring Boot application, so we need to upgrade to Spring Boot 2 if we wish to be on java 11.

Default password encoder in Spring Security 5

In turn Spring Boot 2 needs Spring 5. Here the PasswordEncoder could not handle randomly generated salt so it was removed. This freed us from one application only using one encoding algorithm with the concept of password encoding delegation. The algorithm used is recognised by a prefix like so:

{bcrypt}$2b$12$RkdabMUdgqU4MLAasNOKb.LIElTRdhaQdX59RWHy6X.4Ghf773Gre

And this is how I configured the bcrypt password encoder:

@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    PasswordEncoder defaultEncoder = new StandardPasswordEncoder();
    Map encoders = new HashMap();
    encoders.put("bcrypt", new BCryptPasswordEncoder());
 
    DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder("bcrypt", encoders);
    passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);
 
    return passworEncoder;
}

Mockito 2

First of all we need to add the mockito 2 dependency explicitly:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.22.0</version>
    <scope>test</scope>
</dependency>

Then our IDE soon tells us that some things are moved. The MockitoJUnitRunner is moved to from the org.mockito.runners package to the org.mockito.junit package. Also matchers on arguments like any or eq are moved from the org.mockito.Matchers to the org.mockito.ArgumentMatchers package.

The application I was migrating was using the Whitebox out of the internal package of mockito. This is always a candidate for changes in a major upgrade and with java modules this could be impossible in the future. The solution was to use reflection to set private fields:

Field parameterField = ClassWithPrivateField.class.getDeclaredField("parameter");
parameterField.setAccessible(true);
softAssertions.assertThat(parameterField.get(classInstance)).isSameAs(parameterField);

For more changes in mockito 2 please look at this overview.

Spring Boot Actuator

With Spring Boot 2 the actuator got some big improvements. Read all about it in the Actuator API Documentation.

For me migrating there were things moving around. The SpringBootServletInitializer moved to the org.springframework.boot.web.servlet.support package and the EndpointAutoConfiguration moved to the org.springframework.boot.actuate.autoconfigure.endpoint package. But these were easy to update. The hard part is to move the spring properties to there new places. But here is the dependency that will change your migrating life:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
    <scope>runtime</scope>
</dependency>

The old properties will work and it points out where the have to go in the new configuration. Fantastic! Please make sure you remove it when you’re done.

These are just a few obstacles I came across. For a more complete overview of migration issues take a look at their own migration guide.