Recently, I joined a project that was already going for some time. They had chosen to use Spring Boot to deliver the project as an executable WAR. I hadn’t used Spring Boot before, but I instantly liked the idea of having the Application Server as a dependency, instead of deploying to it. It’s a bit like the way things work in the Node.js ecosystem.
Very short introduction of Spring Boot
So, what exactly is Spring Boot? I think the Spring Boot project home page says it pretty well:
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that can you can “just run”. We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.
Spring Boot tries to achieve this by providing ‘starter POM’s’, a mechanism to create executable JAR’s, pre-configured embedded application servers and more.
Before we dive into it, I want to place a side note about Spring Boot being an opinionated framework. I think being opinionated can be a real strength, but it is also a warning to users of the framework: you shouldn’t use it if your opinion is too far off of the opinion of the Spring Boot team. The power of Spring Boot lays for a large part in their sensible defaults; but what’s the use of those if you disagree with most of them. In that case, you’ll end up losing time while overriding all those defaults.
Executable JAR’s and WAR’s
One of the main features of Spring Boot is the ability to create executable JAR’s and WAR’s. I remember creating a hand rolled executable JAR years ago, for some command line tool I built for a client. It was not difficult, but it required some boiler plate and was a bit cumbersome. Spring Boot can save you this boilerplate, but it can also create executable WAR‘s, that include an embedded application server. And that’s really powerful!
In the project I’m working on, we’re creating a synchronization server that does its job mainly in the background, but has a minimal web interface to do some manual tasks. It was decided to keep it simple and use plain old JSP’s for the web pages, of course combined with Spring MVC. We had a bit of a challenge, because the JSP’s were not rendering in our executable WAR. But with the help of Google and Stackoverflow.com, I found a fairly simple solution. It turns out Spring Boot uses a minimalistic version of Embedded Tomcat, that doesn’t include Tomcat’s JSP rendering engine, Jasper. The fix is to add Jasper as an extra dependency in the project’s POM, like this:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>
The same goes for the JSP Standard Tag Library (JSTL). To have it available, it must be included as a dependency explicitly:
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency>
With both fragments added to our project’s POM, the JSP’s were rendering fine in the embedded Tomcat.
How it is done
It is important to know how Spring Boot creates the executable WAR’s and JAR’s. It does this by plugging into the build process. If you use Maven, like we do in our project, Spring Boot uses a Maven plugin that plugs in at the end of the build process, in the package phase. After Maven finishes creating the JAR of WAR, the Spring Boot plugin takes that JAR/WAR and changes it to make it executable. That way, it is ensured that the normal build process is not changed. To enable this plugin, it has to be added to the plugins-section of the POM, as stated in the Spring Boot docs:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
It is important to have the executions-section, otherwise the plugin won’t be activated in the right life-cycle phase. With this in place, a simple mvn clean install will get you an executable WAR or JAR! Another important thing is to have Maven build a proper WAR first. As stated, Spring Boot does its magic after Maven has created the WAR. So if you don’t tell Maven to build a WAR, but e.g. a JAR, you will get an executable JAR, but the web app won’t work, since essential WAR-specific parts are missing. So make sure the Maven WAR-plugin is also listed in the plugins-section:
<plugin> <artifactId>maven-war-plugin</artifactId> <version>2.5</version> </plugin>
And double-check that you have selected the right packaging:
So far for my very short introduction to Spring Boot and some lessons learned, based on my first acquaintance with Spring Boot. I hope you enjoyed it. Please leave a comment if anything is unclear or if you want to discuss.