Spring Bootification Process

Overview

The following guide will focus on the Bootification of an existing spring based Java application. Every application has the potential to take a different Bootification journey depending on a number of different factors:

Dependency Management

If a project is not using a build tool, then the recommendation is to use Gradle as the build tool, however if the project already uses either Maven or Gradle then it may be better to continue with the existing tool.

For Maven based projects, Spring Boot uses a Parent pom.xml and Spring Boot Starter modules to provide necessary Spring dependencies and known versions of 3rd party dependencies that work well together. Maven will bring in transitive dependencies for you so it is always good to baseline the application's dependency tree before and after bootification. See Spring Boot Parent Pom v1.5.x for more detail: GitHub - spring-boot/pom.xml

If the application is using ant, then make sure all the build dependencies are in one folder and you're following the Spring Boot standards for project structure setup.

If the application is already using maven then you can output the dependency graph through the following:

From a bash shell (git bash), navigate to the root application directory that contains the pom.xml

For Gradle based projects, Spring Boot brings in a plugin which manages the dependencies of third party libraries. Dependency management plugin will bring in transitive dependencies. See Spring Boot Parent Pom v1.5.x for more detail: GitHub - spring-boot/pom.xml

If the application is already using gradle then you can output the dependency graph through the following:

From a bash shell (git bash), navigate to the root application directory that contains the build.gradle

If you are teasing out a slice of functionality from a monolith application then you should begin your journey by creating a new Spring Boot project with Spring Initializr. Spring Initializr is like a shopping cart for all the dependencies that you might need for you application.

- If the application already contains a parent `pom.xml` and it will be the go-forward parent `pom.xml` then you can add a `<dependencyManagement>` section to your `pom.xml` and include the `spring-boot-dependencies` to use Spring Boot's dependency management.
- See: [Using Spring Boot without the Parent Pom](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-maven-without-a-parent)
```
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>1.5.X.RELEASE</version><type>pom</type></dependency></dependencies></dependencyManagement>
```

For Gradle based projects, Spring Boot brings in a plugin which manages the dependencies of third party libraries. Dependency management plugin will bring in transitive dependencies

If the application is a has just one module then the Spring Boot plugin can be added to the root build.gradle file

-Iftheapplicationhas[multipleprojects](https://www.petrikainulainen.net/programming/gradle/getting-started-with-gradle-creating-a-multi-project-build/) at the same level, then a root build.gradle describes elements that are common to all the projects. Since Spring Boot is likely to be managing the dependencies of all the child projects, it can be added in as a plugin to the child projects.```buildscript{ext{springBootVersion='1.5.10.RELEASE'}repositories{maven{credentials{usernamemavenUsernamepasswordmavenPassword}url'https://repo.web.xyz.com/artifactory/Maven-Releases/'}}dependencies{classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")}}subprojects{...applyplugin:'org.springframework.boot'...}```-GradleSpringBootpluginalsotendsto[repackageajar](https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-gradle-plugin.html#build-tool-plugins-gradle-repackage-configuration) file. This is useful only for end applications and not for intermediate jar files. To prevent repacking for intermediate jars disable to boot repackage step the following way:```bootRepackage{enabled=false}```

At this point you should be ready to add your first Spring Boot starter dependency and test case to your application.

One approach to creating a Spring Boot application is to add a java main method inside of a class annotated with @SpringBootApplication. The @SpringBootApplication convenience annotation encapsulates the @ComponentScan, @Configuration, @EnableAutoConfiguration annotations. Additional information about @SpringBootApplication can be found here: 18. Using the @SpringBootApplication annotation.

If the application does not have 1 common parent package in src/main/java then create that now. For example, com.companyname.appname

Create a Spring Boot application class in the package created in the prior step.

The application will probably have many individual Spring dependencies i.e. spring-core, spring-jdbc, spring-context etc. The next step is to start removing explicit dependency versions and rely on Spring Boot’s starter modules and dependency management to import dependencies and include versions. One of the advantages of relying on Spring Boot as parent POM is that acts as a Bill of Materials for all the dependencies for that version of Spring Boot that work will together. Here is the catalog of Spring Boot starter modules: Spring Boot Reference Guide - Using Spring Boot Starter

NOTE: You can use the test case above to iterate quickly on updating your dependency graph i.e. Run Test to failure, add dependency, repeat

For Maven projects, If you rely on a parent pom already you can leverage Spring Boot as the Bill of Materials by adding a <dependencyManagement> section to your pom.xml

Comment out spring dependencies and begin replacing with spring-boot-starter-* modules

Comment out explicit versions <version>x.x.x</version> NOTE: A compromise will most likely need to be made for some 3rd party dependencies that are not managed by Spring Boot's dependency management.

Repeat for each No Class Def Found Exception NOTE: If the application is a couple years old there is a good chance that it has accumulated some dependency debt. This is a good opportunity to only pull in dependencies that the application needs.

Auto-Configuration

Auto Configuration is one of the core tenants of Spring Boots opinionated framework. Spring Boot auto-configuration inspects the jar dependencies and attempts to configure the Spring application context on your behalf.

Exclude Auto-Configuration

During the Bootification process you might find that by adding a jar dependency you cause an issue within your Spring Application context. The exception stack trace might indicate that there are multiple beans of the same type and Spring is unable to decipher which one to use.

If this occurs, then you should review the types of beans to see if they are related to JMS, DataSource, Web Services, etc.

Enable debug=true and restart the application. Spring Boot will log an Auto-Configuration report which might provide some more insight into the root cause of the issue.

If you discover that you have an unwanted Auto-Configuration class running, then attempt to exclude like so:

@SpringBootApplication(exclude=JmsAutoConfiguration.class)

or via the following property:
spring.autoconfigure.exlude=JmsAutoConfiguration

WAR Configuration

Spring Boot allows you to configure an executable war, executable jar or standalone war artifact.

Replace the web.xml with a Java configuration class which includes @Bean definitions for Servlets and Filters via ServletRegistrationBean and FilterRegistrationBean, respectively.

TODO - How test the web.xml to java config conversion

Environment Configuration

Spring Boot has multitude of options to configure the applications environment variables. To reduce configuration drift, you should aim to reduce the number of environment specific files/profiles to the least common denominator.

Logging Configuration

If your explicit definition of log level's is small then you may choose to get rid of your logback.xml or log4j.properites file all together and add the log levels to the application.[properties|yml file

Spring Boot Maven Plugin

The spring-boot-maven-plugin will, by default, add jars for running an embedded container in the lib-provided folder within your jar or war artifact. If you are unable to deploy an executable artifact using an embedded servlet container then you must take an extra step to either remove the plugin completely or add the maven-war-plugin to your pom.xml explicitly.

Actuator Endpoints

Spring Boot combined with the Spring Boot Actuator Starter module enriches the telemetry capabilities of your application by providing a set of production ready endpoints to give you more insight into the health, performance, and environment configuration of your application. It also provides you with troubleshooting endpoints that allows you to trace http endpoints and generate heap dumps, emit custom metrics, and much more.