Spring Boot With JSPs in Executable Jars
A real life example of upgrading from Tomcat to blue/green deployment using Spring Boot and Pivotal Web Services.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
Goal
When we started planning for DevNexus 2016, I wanted to modernize the DevNexus application. Specifically, I planned to improve the underlying infrastructure of the app.
One main sticking point, though, was the used view technology. The DevNexus application has been using JavaServer Pages (JSP) for several years, and we accumulated a non-trivial amount of them. Ultimately, the plan is to migrate the user interface (UI) to a Single Page Application (SPA) but for the 2016 conference (February) that intent was unattainable due to time constraints.
1.3.3
, the reference guide states:JSPs should be avoided if possible, there are several known limitations when using them with embedded servlet containers.
An executable jar will not work because of a hard coded file pattern in Tomcat.
What a bummer…
Solution
Just to recap my requirement, I want to serve JSPs out of my classpath so that I can create executable Jar files. Basically, Eliminate the web apps folder.
Note | An interesting aspect of this is, that one can compose web applications out of multiple JARs, each possibly containing JSPs that are automatically served. |
src/main/resources/public
or src/main/resources/static
does not work. While reading the JSR-245 JavaServer™ Pages 2.1 Specification as well as the following in interesting blog post titled Serving Static Content with Servlet 3.0, it became apparent that I should also be able to store static resources in the META-INF/resources
directory. Heureka it worked!So the simple thing to remember is to store your JSPs in a folder like /src/main/resources/META-INF/resources/WEB-INF/jsp
and you’re good to go (Plus some minor configuration around). To make things easy, let's go over a little example project.
Sample Project
Spring Initializr
web
project.Selecting web
enables Full-stack web development with Tomcat and Spring MVC. Now you can press the Generate Project
button, which will start the download of a Zip file containing your customized project.
Note | Instead of following the individual steps, you can also download the fully configured sample project from GitHub. Just clone the Demo Project using: |
$ git clone https://github.com/ghillert/spring-boot-jsp-demo.git
$ cd spring-boot-jsp-demo
Unzip the project to a directory of your choosing.
Add Maven Dependencies
In order to enable JSP support, we need to add a few dependencies to our new project in pom.xml
.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Define the location of your JSP templates
Next we need to define the template prefix and suffix for our JSP files in application.properties
. Thus add:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
Important | Keep in mind that we will ultimately place the JSP templates under src/main/resources/META-INF/resources/WEB-INF/jsp/ |
Create a Spring Web Controller
Create a simple web controller:
package com.hillert.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloWorldController {
@RequestMapping("/")
public String helloWorld(Model model) {
model.addAttribute("russian", "Добрый день");
return "hello-world";
}
}
Create the JSP Template
Next, create the corresponding JSP file hello-world.jsp
in the directory src/main/resources/META-INF/resources/WEB-INF/jsp/
:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setHeader("Expires","0");
%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="ctx" value="${pageContext['request'].contextPath}"/>
<html>
<body>
<h1>Hello World - ${russian}</h1>
</body>
</html>
Run the Sample Application
Now it is time to run the application - execute:
$ mvn clean package
$ java -jar target/jsp-demo-0.0.1-SNAPSHOT.jar
Conclusion
In this blog post, have shown how easy it is to use JSP templates with Spring Boot in executable Jars by simply putting your templates into src/main/resources/META-INF/resources/WEB-INF/jsp/
.
While JSPs are often touted as being legacy, I see several reasons why they stay relevant today (2016):
- You need to migrate an application to Spring Boot but have an existing sizable investment in JSP templates, that can’t be migrated immediately (My use-case)
- While Single Page Applications (SPA) are all the rage, you may have use-cases where the traditional Spring Web MVC approach is still relevant
- Even for SPA scenarios, you may still use dynamically-created wrapper pages (e.g. to inject data into the zero-payload HTML file)
- Also JSP are battle-tested in large scale environments, e.g. at Ebay
- Even with alternative frameworks, you may run into issues
Published at DZone with permission of Gunnar Hillert. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments