Spring Boot Hello World Example – JSP

A Spring Boot web application example, using embedded Tomcat + JSP template, and package as an executable WAR file.

Technologies used :

  1. Spring Boot 1.4.2.RELEASE
  2. Spring 4.3.4.RELEASE
  3. Tomcat Embed 8.5.6
  4. Maven 3
  5. Java 8

1. Project Directory

Create the following folders manually :

spring-boot-web-jsp-project-directory

2. Project Dependencies

Maven example. Read comments for self-explanatory.

pom.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>spring-boot-web-jsp</artifactId>
	<packaging>war</packaging>
	<name>Spring Boot Web JSP Example</name>
	<description>Spring Boot Web JSP Example</description>
	<url>https://www.mkyong.com</url>
	<version>1.0</version>

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

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

	<dependencies>

		<!-- This is a web application -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- Tomcat embedded container-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>

		<!-- JSTL for JSP -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!-- Need this to compile JSP -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>

		<!-- Need this to compile JSP, 
			tomcat-embed-jasper version is not working, no idea why -->
		<dependency>
			<groupId>org.eclipse.jdt.core.compiler</groupId>
			<artifactId>ecj</artifactId>
			<version>4.6.1</version>
			<scope>provided</scope>
		</dependency>

		<!-- Optional, test for static content, bootstrap CSS-->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>3.3.7</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<!-- Package as an executable jar/war -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Display project depdencies :


$ mvn dependency:tree

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Spring Boot Web JSP Example 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ spring-boot-web-jsp ---
[INFO] org.springframework.boot:spring-boot-web-jsp:war:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:1.4.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.4.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.1.7:compile
[INFO] |  |  |  |  +- ch.qos.logback:logback-core:jar:1.1.7:compile
[INFO] |  |  |  |  \- org.slf4j:slf4j-api:jar:1.7.21:compile
[INFO] |  |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.21:compile
[INFO] |  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.21:compile
[INFO] |  |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.21:compile
[INFO] |  |  +- org.springframework:spring-core:jar:4.3.4.RELEASE:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.17:runtime
[INFO] |  +- org.hibernate:hibernate-validator:jar:5.2.4.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.3.3:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.4:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.4:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.4:compile
[INFO] |  +- org.springframework:spring-web:jar:4.3.4.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-aop:jar:4.3.4.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-beans:jar:4.3.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-context:jar:4.3.4.RELEASE:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:4.3.4.RELEASE:compile
[INFO] |     \- org.springframework:spring-expression:jar:4.3.4.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.4.2.RELEASE:provided
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.6:provided
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.6:provided
[INFO] |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.6:provided
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- org.apache.tomcat.embed:tomcat-embed-jasper:jar:8.5.6:provided
[INFO] +- org.eclipse.jdt.core.compiler:ecj:jar:4.6.1:provided
[INFO] \- org.webjars:bootstrap:jar:3.3.7:compile
[INFO]    \- org.webjars:jquery:jar:1.11.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.327 s
[INFO] Finished at: 2016-11-28T16:57:00+08:00
[INFO] Final Memory: 20M/309M
[INFO] ------------------------------------------------------------------------

3. Spring Spring

3.1 This SpringBootServletInitializer run a SpringApplication from a traditional WAR deployment

SpringBootWebApplication.java

package com.mkyong;

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

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(SpringBootWebApplication.class);
	}

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

}

3.2 A simple Spring controller class.

WelcomeController.java

package com.mkyong;

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WelcomeController {

	// inject via application.properties
	@Value("${welcome.message:test}")
	private String message = "Hello World";

	@RequestMapping("/")
	public String welcome(Map<String, Object> model) {
		model.put("message", this.message);
		return "welcome";
	}

}

4. JSP + Resources + Static files

4.1 For JSP files, put in src/main/webapp/WEB-INF/jsp/

src/main/webapp/WEB-INF/jsp/welcome.jsp

<!DOCTYPE html>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>

	<!-- Access the bootstrap Css like this, 
		Spring boot will handle the resource mapping automcatically -->
	<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />

	<!-- 
	<spring:url value="/css/main.css" var="springCss" />
	<link href="${springCss}" rel="stylesheet" />
	 -->
	<c:url value="/css/main.css" var="jstlCss" />
	<link href="${jstlCss}" rel="stylesheet" />

</head>
<body>

	<nav class="navbar navbar-inverse">
		<div class="container">
			<div class="navbar-header">
				<a class="navbar-brand" href="#">Spring Boot</a>
			</div>
			<div id="navbar" class="collapse navbar-collapse">
				<ul class="nav navbar-nav">
					<li class="active"><a href="#">Home</a></li>
					<li><a href="#about">About</a></li>
				</ul>
			</div>
		</div>
	</nav>

	<div class="container">

		<div class="starter-template">
			<h1>Spring Boot Web JSP Example</h1>
			<h2>Message: ${message}</h2>
		</div>

	</div>
	
	<script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>

</html>

4.2 For static files like CSS or Javascript, put in /src/main/resources/static/

/src/main/resources/static/css/main.css

h1{
	color:#0000FF;
}

h2{
	color:#FF0000;
}

4.3 For properties files, put in /src/main/resources/

/src/main/resources/application.properties

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

welcome.message: Hello Mkyong
Note
Spring Boot, convention over configuration, no need to declare the resource mapping like this. The resource mapping just handles automatically – Read this article – Spring Boot Serving static content

5. Demo

5.1 Start the Spring Boot web app.


project$ mvn spring-boot:run

//...
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.2.RELEASE)

2016-11-28 17:25:24.809  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : Starting SpringBootWebApplication on MKYONG-WIN10 with PID 4696 (C:\spring-boot\spring-boot-examples\spring-boot-web-jsp\target\classes started by mkyong in C:\spring-boot\spring-boot-examples\spring-boot-web-jsp)
2016-11-28 17:25:24.812  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : No active profile set, falling back to default profiles: default
2016-11-28 17:25:24.861  INFO 4696 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@69410cd3: startup date [Mon Nov 28 17:25:24 SGT 2016]; root of context hierarchy
2016-11-28 17:25:25.950  INFO 4696 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-11-28 17:25:25.965  INFO 4696 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-11-28 17:25:25.966  INFO 4696 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-11-28 17:25:26.171  INFO 4696 --- [ost-startStop-1] org.apache.jasper.servlet.TldScanner     : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2016-11-28 17:25:26.180  INFO 4696 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-11-28 17:25:26.180  INFO 4696 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1322 ms
2016-11-28 17:25:26.304  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-11-28 17:25:26.312  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-28 17:25:26.313  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-28 17:25:26.313  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-28 17:25:26.314  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]

//...

2016-11-28 17:25:26.841  INFO 4696 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-11-28 17:25:26.846  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : Started SpringBootWebApplication in 2.403 seconds (JVM running for 5.08)

5.2 Access http://localhost:8080

spring-boot-web-jsp-demo

5.3 Maven package the project as an executable WAR file. A 18M++ WAR file will be generated in the target folder.


project$ mvn clean package

...
[INFO] Building war: ...\spring-boot-web-jsp\target\spring-boot-web-jsp-1.0.war
[INFO]
[INFO] --- spring-boot-maven-plugin:1.4.2.RELEASE:repackage (default) @ spring-boot-web-jsp ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Run It, access http://localhost:8080 again.


project$ java -jar target/spring-boot-web-jsp-1.0.war
JSP limitations
You can’t create an executable jar to run this embedded Tomcat + JSP web example, because of a hard coded file pattern in Tomcat. Read this Spring Boot – JSP limitation.

Download Source Code

References

  1. Spring Boot – Static content
  2. SpringBootServletInitializer JavaDoc
  3. Deploying Spring Boot Applications
  4. Spring Boot – JSP limitations
  5. Spring MVC – Inlucde CSS file

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
Kalpesh
Guest
Kalpesh

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Feb 09 11:33:19 IST 2018
There was an unexpected error (type=Not Found, status=404).
/WEB-INF/jsp/helloPage.jsp

Vaishali Modi
Guest
Vaishali Modi

Getting error as below:
——————————————————————————————–
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Not Found, status=404).
No message available
——————————————————————————————–

Srinivas
Guest
Srinivas

You have to execute the maven command like “mvn clean package”, after this run the java program

Graeme
Guest
Graeme

I had the same issue, my application.properties was in the wrong location.

Hiten
Guest
Hiten

Remove/Comment the entry ->
org.springframework.boot
spring-boot-starter-tomcat
provided
from pom.xml .. This dependency is already getting added through spring-boot-starter-web

Raja
Guest
Raja

Hello guys please be add @ResponseBody annotation on top of method .then you should get the exact output

Bob
Guest
Bob

I am getting this message after running application and in browser http://localhost:8080
“This application has no explicit mapping for /error, so you are seeing this as a fallback.”

Barak
Guest
Barak

Missing
@ComponentScan(“com.mkyong”)

Aniket Luharia
Guest
Aniket Luharia

hi
my jsp is getting downloaded
as a file when i am hitting http://localhost:8080 url.

Ian Kaplan
Guest
Ian Kaplan

I have tried to carefully type in the application as above. I have read the comments and added things like @RestController. I built this as a SpringBoot, using the SpringToolSuite. Everything compiles, but when I attempt to run the application, all I get is the error page. I have had this problem with other SpringBoot applicaitons. I find this very frustrating. SpringBoot is supposed to be the most popular framework, but I don’t understand how anyone gets started. I am certainly have a lot of trouble.

William
Guest
William

Got following error after downloaded code, imported into IntelliJ, built successfully and Ran (as shown below).
But in command line, use “mvn package” to compile successfully and “mvn spring-boot:run” to run it successfully! (thanks!)

Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.support.SpringBootServletInitializer
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:294) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:230) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
… 12 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_151]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_151]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_151]
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.4.RELEASE.jar:4.3.4.RELEASE]
… 16 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_151]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_151]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_151]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_151]
… 20 common frames omitted

NJJ
Guest
NJJ

This demo app is not at all working.

Bohdan
Guest
Bohdan

For this thing –
“Need this to compile JSP, tomcat-embed-jasper version is not working, no idea why”
tried to remove scope tags or comment them. And it must work.

Andrey
Guest
Andrey

If welcome.message: Hello Mkyong, in application.properties
then why “${welcome.message:test}”?
what is test there?

bharani
Guest
bharani

${property:default value}. ‘test’ is the default value

Daniel Bower
Guest
Daniel Bower

Changing the scope of that tomcat dependency from provided to runtime ought to do the trick.

John Zhu
Guest
John Zhu

Mr. Mong, just want to let you know how appreciative I am to your blogs and teachings. Over the years, your examples have become my must-read when I learning something new.

Thanks

Just a note:

in your SpringBootWebApplication.java, should the line with
import org.springframework.boot.web.support.SpringBootServletInitializer;

should there be a “servlet” between “web” and “support”?

Bob
Guest
Bob

As per @Hiten suggestion removed tomcat pom.xml entry but still same error message.
BUT if I change in controller class @Controller to @RestController everything works fine and error message is gone!
with @RestController I don’t need to comment tomcat entry in pom.xml , everything works fine.

Ravi Shankar
Guest
Ravi Shankar
Hi, I have a question. Requesting your help. We have a spring boot application and i have written integration tests without Mocks with TestRestTemplate and @SpringbootTest. So on local machine, when i execute the tests, they execute fine as i have given MyApplication.class inside @Springboottest It will startup the spring application context and execute the tests. Till here everything is fine. But we deploy this application on different test environments like qa,e2e,staging and then on production. So we have to execute the Jenkins Job for my integration tests against the above environments as an acceptance tests. My Question over here… Read more »
aaa
Guest
aaa

if I create runnable jar for this project, pagenotfound(jsp pages) error is coming.

John
Guest
John

get error. fixed by this:
1. add

javax.servlet
javax.servlet-api

2. remove all the provided

Raman
Guest
Raman

Hi,
I’m still facing the below error as:
———————————————————————————————————————–
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Mon Jan 22 08:29:07 EST 2018
There was an unexpected error (type=Not Found, status=404).
No message available
———————————————————————————————————————–
I have comment the following entry in pom.xml: org.springframework.boot & spring-boot-starter-tomcat
as well run the following command: mvn clean package”, after this run the java program but still facing the above error in my browser.

I even tried to update the “/” to “/welcome” in meantime but still above error exists.

Kakalot
Guest
Kakalot

excuse me, can you tell me why the path is /WEB-INF/jsp? I think it should be /webapp/WEB-INF/jsp. Thank you?

Hiten
Guest
Hiten

Thanks Mkyong. Kindly update the pom.xml . dependency -> spring-boot-starter-tomcat need to be removed here, since this dependency is already getting included via spring-boot-starter-web

Bohdan
Guest
Bohdan

For this thing , tried to remove tags or comment them. And it must work.

Devid
Guest
Devid

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

please provide solution

Jacks
Guest
Jacks

You missed to mark your Application class with “@SpringBootApplication”.
Please refer : https://stackoverflow.com/questions/21783391/spring-boot-unable-to-start-embeddedwebapplicationcontext-due-to-missing-embedd

rtert
Guest
rtert

hhh hgfh fhghg hghg

sas
Guest
sas

sss

Surendra Jnawali
Guest
Surendra Jnawali

@mkyong It’s really very helpful to startup and error free project. As always you did great job

Tiago Cássio
Guest
Tiago Cássio

Could you please give a example to how to create template reuse with JSP using Spring Boot?

Thanks for all.

ALEXEY
Guest
ALEXEY

Thanks for good article.
Please, clarify, why do you include the JSTL for JSP dependency into your pom.
As I can see this dependency is shipped with parent pom(spring-boot), so it will be in classpath without your
explicit declaration. Am I right ?