Recently I decided to upgrade the Spring Boot version of one of my projects to the most recent one. The project’s version was 1.5.14 and the current Spring Boot version is 2.1.2. Here I present the procedure for the Spring boot 2 migration.
Migrating to Spring Boot 2 can be a little tricky as some code changes might be required. I have decided to collect the issues that I faced in this article, as they could be handy to someone else who wants to do the same task.
The first step is of course to update the spring boot’s version to 2.X.X.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> </parent>
After this step, our code may not compile since some dependencies have relocated to new packages. In my case those were the following:
- DataSourceBuilder was moved from org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder to org.springframework.boot.jdbc.DataSourceBuilder
- LocalServerPort was moved from org.springframework.boot.context.embedded.LocalServerPort to org.springframework.boot.web.server.LocalServerPort
To resolve this we simply need to update our imports.
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.jdbc.DataSourceBuilder;
POM updates
Now that our code compiles it’s time to start performing the requested changes in order to build and run our project. Let’s start from the pom.xml. First, we need to update the versions of some of our dependencies. Here is the list of the minimum required versions of those :
- Tomcat 8.5
- Flyway 5
- Hibernate 5.2
- Thymeleaf 3
Those are the version changes that are referred to the Spring documents. However, there are some others that need to be updated as well. In my case, I had to update the Jackson dependencies to the latest version 2.9.8.
Also, at this point, it is also a good idea to refactor our dependencies. Some of them might not be needed anymore, as they are included in Spring Boot. One of them is the HikariCP, which is now the default datasource connection pool.
<!-- Remove this --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>${hikaricp.version}</version> </dependency>
Configuration updates
Now that we have finished with the pom.xml changes, let’s move to our configuration files. One of Spring Boot’s 2 major change is the replacement of the Tomcat JDBC connection pool with HikariCP as default. Depending on your previous datasource configuration, some changes might be required here. In my case these were the following:
- Replace spring.datasource.url with spring.datasource.jdbcUrl
- Replace spring.datasource.initialize with spring.datasource.initializationMode
datasource: name: ds_name jdbcUrl: jdbc_url initializationMode: always ...
The Liquibase configuration parameters also were updated.
- Replace liquibase.change-log with spring.liquibase.change-log
spring: liquibase: changeLog: changelog.xml
In case that you are using Spring Cloud dependency, you need to upgrade it to something greater than Edgware. From the Spring Cloud Documentation :
- 2.0.X Finchley
- 2.1.X Greenwich
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> </dependency>
Issues
There are some other issues that I faced, which do not fall into any particular category but still I think it will be useful to mention.
I was mistakenly registering a bean twice, on my @Configuration class, and on my main @SpringBootApplication class. It seems that Spring boot 1.5.X was tolerant with this, however, after the migration the following error occurred during the build :
The bean 'exampleBean', defined in com.antogeo.XXX.Application, could not be registered. A bean with that name has already been defined in class path resource [com/antogeo/XXX/Configuration.class] and overriding is disabled.
To resolve this we simply need to define each bean only once.
Another issue that I faced was the following :
ERROR:Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
This is a misleading error which guides you to add the ServletWebServerFactory bean to your configuration. After I did that I got a new error :
ERROR: Factory method 'servletWebServerFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol
which again wasn’t very helpful. It seems that in my case the solution to all this was to upgrade the Tomcat version to something greater that 8.5 (I used the 9.0.14 version).
In conclusion, the Spring boot 2 migration could be an easy and straightforward process or a ticky one depending on your codebase and the features that you are using.