Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / Spring

Creating MVC Web Application using Spring Boot with JSP and WAR Archive

0.00/5 (No votes)
17 Oct 2018MIT10 min read 12.9K   131  
In this article, I like to discuss the way to set up a Spring Boot application that is packaged as a WAR archive and supports Spring MVC with JSP as view.

Introduction

This will be my first tutorial on Spring Boot, in which I would like to discuss the way of setting up an Spring MVC application. In order to use JSP pages as view templates, one way is to package the application as a WAR archive. The finished product can be run as a standalone application and handling the user requests as an MVC application.

Spring Boot is a very awesome application development framework. The sole focus of this framework is to create all kinds of programs that can run as standalone applications. I am not just referring to any web applications that can be deployed into an application container like Tomcat, or Jetty, or Glassfish; but also applications that can interact with messaging brokers like RabbitMQ or Kafka; as well as programs that can run with a quartz scheduler. I guess most people probably use this framework to create web based applications -- either MVC applications or RESTFul API based applications. These application can be deployed into a Docker container, served as micro-services.

This tutorial will show you how easy it is to create a web based application using Spring Boot. The application when it is done is a stand-alone Java application. It has an embedded Tomcat application server. It can handle web requests, and static web contents. As I have mentioned a couple times in my past articles, the worst part of every new project is setting the project up. There is some difficulty with Spring Boot. But comparing to creating Spring v3/v4 MVC applications, it is a lot easier to work with. You will see.

The File Structure

Before we go into the details of the sample project, I like to show the directory and file structure of the project. Here it is:

XML
<base-dir>/src/main/java/org/hanbo/boot/app/controllers/HelloController.java
<base-dir>/src/main/java/org/hanbo/boot/app/App.java
<base-dir>/src/main/resources/application.properties
<base-dir>/src/main/resources/static/test.html
<base-dir>/src/main/resources/static/assets/css/index.css
<base-dir>/src/main/resources/static/assets/js/test.js
<base-dir>/src/main/webapp/WEB-INF/jsp/testme.jsp

We got a wide variety of files. They are:

  • Two Java files. One is the program execution entry. The other is the MVC controller.
  • One properties file that contains some configuration values.
  • Three static files that can be served directly to user when requested.
  • One JSP file that is used as the view template for the MVC application.

As you can see here, setting up the Spring MVC application is quick and simple. If you knew the old ways of setting up the web application, what you will need is at least two XML files for the configuration. Or if you use Java annotations for the Spring application, then you need to know the way of converting the configurations in the XML configurations to use Java annotation. If you expand the sample application in this tutorial, you will have to use Java annotation for the configuration. It will resemble the way XML configuration works, but for a starter application, this is as simple as it can be.

The POM XML File

Let's begin with the POM XML file. POM XML file is used for Maven build. It specifies how the project can be compiled and packaged. Here is the content of this file:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<artifactId>boot-war</artifactId>
	<packaging>war</packaging>
	<name>Hanbo Boot War Sample App</name>
	<description>An example of Spring Boot, JSP and WAR</description>
	<version>1.0.0</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
	</parent>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

There are a couple of important things about this POM file. The first is the line that specifies the maven build will create a WAR archive:

XML
<packaging>war</packaging>

The second is the POM file has a parent POM dependency. This allows a lot of Spring and non-Spring dependencies to be downloaded and linked into this project:

XML
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.0.5.RELEASE</version>
</parent>

The third is the properties definition that sets the Java compilation to use JDK 1.8:

XML
<properties>
   <java.version>1.8</java.version>
</properties>

The last would be using the Spring Boot maven plugin to for the compilation and packaging:

XML
<build>
   <plugins>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
   </plugins>
</build>

The section for dependencies defines extra dependencies needed for this application. What I need is Spring MVC, and run as a J2EE web application. The dependencies added are used to compile the JSP views and running embedded application server.

The Main Entry

Next, I will show you the program entry. Unlike the Spring based web applications that run in an application container, Spring Boot based web application is self hosting. There is a static main entry in every such program. Here is the full source code of the class that contains the main entry:

Java
package org.hanbo.boot.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class App extends SpringBootServletInitializer
{
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder appBuilder)
   {
		return appBuilder.sources(App.class);
	}

	public static void main(String[] args) throws Exception
   {
		SpringApplication.run(App.class, args);
	}
}

The class is called App which extends from class SpringBootServletInitializer. This allows the Spring Framework to recognize the class App can be initialized and executed as a traditional WAR package. It also tells Spring Framework that there will be WEB-INF folders, and resources in it for use.

In the class App, there is a protected method called configure(). It is used to specified any application specific configurations. It has only one line, which takes the class type of App and creates an SpringApplicationBuilder object and returns. What this does is that the SpringApplicationBuilder object created would automatically scan the App class, the package it is in, and sub-packages for any annotated classes, and the annotations that contains Spring configurations. Then it would construct a Spring application based on these configurations. This is a classic example of integration by convention. And everything is coupled by dependency injection.

The static main method has only one line, it passes the type of the class App and any additional commandline arguments into SpringApplication.run(). Behind the scenes, this class does a lot. It would implicitly do a component scan on the current package and all the subpackages. If needed, developer can also specify other packages for component scan. And the developer can add extra annotations for any other configurations needed. For this simple program, there is just the MVC controller class that can handle user's request for a page.

The MVC Controller Class

The next class I like to show is the MVC controller class. It is a very simple class that has just one method that handles a HTTP GET request from user, with some query parameters. It responds by using the JSP page as view.

The source code is as the following:

Java
package org.hanbo.boot.app.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController
{
	@RequestMapping(value="/meow", method = RequestMethod.GET)
	public ModelAndView hello(
	   @RequestParam("sayit")
	   String sayit
	)
   {
		ModelAndView retVal = new ModelAndView();
		retVal.setViewName("testme");
		retVal.addObject("mymessage", sayit);
		return retVal;
	}
}

There is no new surprise for this class. That is, the definition of this controller class is the same as any Spring MVC controller for applications that runs in an application container. Let me just summarize about the implementation:

  • The class is annotated with @Controller.
  • The class has just one method that handles the HTTP GET request. It is annotated with @RequestMapping. The annotation defines the subpath of the request and the HTTP method it can handle, GET requests.
  • The method creates a ModelAndView object and returns. The view page is called "testme". The data model is just a string that will be displayed on the page.
  • The method takes in a parameter, which gets from the query parameter, called "sayit".

To put this simply, when a user tries to navigate to:

http://localhost:8080/meow?sayit=This+is+pretty+crazy

Then the user clicks Enter, the browser wil display the following:

What did you say?

I said: "This is pretty crazy."

In order to have this controller working as expected, some additional configuration is needed. And it is done in the application.properties file.

Application.properties File

The reason I needed an application.properties file is that I need to specify the prefix of the view template file and the suffix. If you know from the old days, there is a step of creating and configuring an object of type org.springframework.web.servlet.view.InternalResourceViewResolver. In this case, all we need is two lines in this application.properties:

XML
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

What this configuration does is setting the application to find the view template in the folder of "WEB-INF/jsp/". And the file extension is ".jsp". Now we have seen the main entry, the controller class, and the setting for the internal resource view resolver. The last piece of the puzzle is the view template.

JSP View Template

The view template for this tutorial is very simple, just one JSP file that demonstrates displaying data from the view model:

HTML
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="en">
<head>
	<c:url value="/assets/css/index.css" var="jstlCss" />
	<link href="${jstlCss}" rel="stylesheet" />
</head>
<body>
   <p>What did you say?</p>
   <p>I said: <span class="text-underline">"${mymessage}."</span></p>
   <script type="text/javascript" src="/assets/js/test.js">
   </script>
</body>
</html>

In this JSP file, there are three things:

  • There is the cascade style sheet file. It is a static file and is added via JSTL tag. This demonstrates that the JSTL library is incorporated into the project correctly.
  • View model has just one element, and addedto view via ${mymessage}.
  • There is a JavaScript file added to the end of the HTML content and it will execute once it is loaded. This is to demonstrate the use of static file works in this project.

Having static content served by the sample application is very important. It provides the means to go beyond Spring MVC -- static pages and JavaScripts can be used for single page web applications. And it is very easy to have static content with Spring Boot, which will be explained next.

Serving Static Content

Spring Boot provided a lot of convenience so that a developer can develop and develop fast. The convenience is through convention. Serving static content in a web application is a good example of this. When you specify the application you develop using Spring Boot as a web based application, all you need to do is create a folder called "static" under src/main/resources. Inside this "static" folder, just add any sub-folder as you want, and put any static content files in them, then you can have them served.

Taking the sample application as an example, I have three files that are designated as static content:

  • A file for cascade style sheet -- src/resources/static/assets/css/index.css
  • A JavaScript file, it does not do anything useful, but prints out a line on the JavaScript output console -- src/resources/static/assets/js/test.js
  • An HTML file, just to demo the fact that you don't need JSP in a Spring Boot based web application -- src/resources/static/test.html

So, how does a user access these static content through a browser? It is easy. Assuming the application is running, and assuming the URL of web site the application runs under is http://localhost:8080/ (this is without a specific application context), then the user can see the actual contents of these static content files with the following URLs:

  • http://localhost:8080/assets/js/test.js - You see the actual content of the JS file.
  • http://localhost:8080/assets/css/index.css - You see the actual content of the cascade style sheet file.
  • http://localhost:8080/assets/test.html - You see a web page.

There are ways to configure the Spring Boot application to look for static content files at other locations, same goes with the WEB-INF and JSP locations, as well as how the application initializes, and many other aspects of how the Spring Boot applications behave. These are not the topics of discussion in this tutorial, but they are trivial if one gets to know enough of Spring Boot. I might cover some of them in later writings.

How to Build and Run the Application

Before you build the project, please go to src/main/resources/static/assets/js folder and rename the file "test.sj" to "test.js".

To build this application, you run the following command in a command line console:

mvn clean install

When you run this for the first time, it will download all the dependencies for building this application, which may take some time to do. Afterwards, the subsequent builds will take less time to do.

To run the web application, you can also do it with a command line console:

XML
java -jar target\boot-war-1.0.0.war

If all goes well and you can build the application, the execution will output something like this at the very end:

<small>
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2018-10-14 22:51:11.356  INFO 6124 --- [           main] org.hanbo.boot.app.App                   : Starting App v1.0.0 on U3DTEST-PC with PID 6124 (C:\Users\u3dadmin\workspace-mars8\SpringBootJspWar\target\boot-war-1.0.0.war started by u3dadmin in C:\Users\u3dadmin\workspace-mars8\SpringBootJspWar)

....
....
....

2018-10-14 22:51:28.730  INFO 6124 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-10-14 22:51:28.745  INFO 6124 --- [           main] org.hanbo.boot.app.App                   : Started App in 20.84 seconds (JVM running for 23.398)
</small>

Points of Interest

As I have mentioned before, using Spring Boot for creating a web application is quite easy, convenient. The whole point of such convenience is to take away all the messy configuration so that one can focus on the most important part of the development process, designing something that fits the vision of the final product. Other than this, one cool thing about Spring Boot is that it can be deployed quickly into a Docker VM. So it is well suited for developing micro-sevices.

The next step for me would be to write a more complex tutorial on Spring Boot, which included data access, authentication and authorization. Stay tuned.

History

  • 10/14/2018: Initial draft

License

This article, along with any associated source code and files, is licensed under The MIT License