Click here to Skip to main content
15,038,451 members
Articles / Web Development / Spring
Article
Posted 13 Feb 2019

Stats

4.8K views
77 downloads
1 bookmarked

Hosting Spring Boot Web Application using Embedded Jetty Application Server

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
13 Feb 2019MIT6 min read
In this tutorial, I am going to show the readers how to create an MVC application using Spring Boot, packaging as a self host WAR file, and execute using embedded Jetty application server.

Introduction

In April 2018, I wrote a quick tutorial article on creating a web application using Spring Boot, packaged in WAR archive. It runs with a embedded Tomcat Application Server. This article will use the same code base but hosted with an embedded Jetty Application Server. You might ask, what is the significance by duplicating the same article? The significance is when you finish this tutorial, you can easily swap out the embedded Tomcat server and use embedded Jetty server. It is always better to have choices than being stuck with just one option.

Quick Review of the Source Code

I didn't make any changes with the actual source code from the twin article. If you are lazy and not wanting to flip between this tutorial and the other tutorial, just go through this section quickly, then we will jump into the good stuff on swapping out the embedded Tomcat server with the embedded Jetty server.

Here is the code for 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 main entry sets up the application to be run as a web application. The class extends from SpringBootServletInitializer which allows the application to be packaged in a WAR archive. The embedded server would use the WAR archive file structure to run the application. It is an ideal approach for hosting a Spring MVC application, with JSP template and all.

Every MVC application has a controller. Here it is:

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;
   }
}

All this controller does is set up the web page that echoes back some input. Here is a URL:

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

As long as the application runs, and when you paste the URL in the browser and hit Enter, you will see a page displaying:

What did you say?

I said: "This is pretty crazy."

I need to let the web application know where to find the JSP template, the view name which is called "testme". I need to let the web application know what the file extension of the view template file. I have specified these in application.properties:

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

This looks familiar, right? Just a hint: org.springframework.web.servlet.view.InternalResourceViewResolver.

Finally, the view template JSP file is called "testme.jsp":

jsp
<%@ 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>

This web application also contains some static content, which can be found in src/main/resources/static/** directory. By convention, Spring Boot looks for the static content here.

Anyways, I will describe how to test this application later. It is time to show the good stuff. The only change I have to make for the application to run successfully with embedded Jetty server is in the maven POM file.

The Maven POM File for Jetty

The Maven POM file is used for dependency management, for building and WAR packaging. By default, it packages embedded Tomcat server in the WAR archive, that is, all the jar dependencies in the WAR archive. Now if I need to replace the embedded Tomcat server with the embedded Jetty server, I need to first exclude all the Tomcat embedded server jars and add the embedded Jetty server jars. Because Jetty is not the default application container used by Spring Boot, and with Spring MVC, JSP/JSTL enabled for this Spring application. At the time, it is all quite overwhelming. This is why I document this to save everyone the trouble, and I liked the challenge. Now I will tell you how this is done.

The first thing I do is to exclude the Tomcat server jars. Here is how I do it:

XML
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <exclusions>
      <exclusion>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-tomcat</artifactId>
      </exclusion>
   </exclusions>
</dependency>

Artifact "spring-boot-starter-web" is to include all the jar files needed for web applications, which also included Tomcat. It is why I need to have a little section to exclude the artifact "spring-boot-starter-tomcat". I didn't come up with this by myself. You can find this in one of the tutorials provided by Baeldung. Next is to add the self-hosting Jetty dependencies. Here it is:

XML
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Again, I didn't come up with this by myself. If you guess, yeah, from the same tutorial provided by Baeldung. However, that is all I can get from Baeldung. The two moves I've just done only supports the basic web application functionality. If you run the application just like this with no additional jars, the application just won't work. It does not help with my little application here because I need JSP/JSTL support, and I need to package the application as a WAR file. So with a little research, I came up with a solution that just works. And it is so simple it just blows my mind. This solution is to add three more artifacts, like this:

XML
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
</dependency>
<dependency>
   <groupId>org.eclipse.jetty</groupId>
   <artifactId>apache-jsp</artifactId>
</dependency>
<dependency>
   <groupId>org.eclipse.jetty</groupId>
   <artifactId>apache-jstl</artifactId>
</dependency>

The most important ones are the last two artifacts, once you have it in the POM file, it will bring in all the necessary jar files for embedded Jetty server. Before you move on, take a careful look at the entire maven POM file. In it, you may find the way of packing the file as a war, and use Spring Boot build plugin to build the application. Now it is time to run the application.

Testing the Application

Before you build and run the application, please go into the static web content folders and rename all the *.sj file to *.js files.

To build the application, first go to the base directory of the project (where the POM file located), then use the following Maven build command:

mvn clean install

After clicking Enter on the command line prompt, it will download all the dependencies, which will take some time, so be patient. Once the build succeeded, you can run the application with just one command. Assuming you are still at the base directory of the project, type in command:

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

When the command runs, it will spit out a lot of non-sense, look for segments like this:

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

2019-02-11 23:06:59.055  INFO 12404 --- [           main] org.hanbo.boot.app.App
                   : Starting App v1.0.0 on U3DTEST-PC with PID 12404 (C:\Users\
u3dadmin\workspace-mars8\SpringBootJettyWar\target\boot-war-1.0.0.war started by
 u3dadmin in C:\Users\u3dadmin\workspace-mars8\SpringBootJettyWar)
2019-02-11 23:06:59.132  INFO 12404 --- [           main] org.hanbo.boot.app.App
                   : No active profile set, falling back to default profiles: de
fault
2019-02-11 23:06:59.584  INFO 12404 --- [           main] ConfigServletWebServer
ApplicationContext : Refreshing org.springframework.boot.web.servlet.context.Ann
otationConfigServletWebServerApplicationContext@6aceb1a5: startup date [Mon Feb
11 23:06:59 EST 2019]; root of context hierarchy
2019-02-11 23:07:04.389  INFO 12404 --- [           main] o.s.b.w.e.j.JettyServl
etWebServerFactory : Server initialized with port: 8080

....

2019-02-11 23:07:09.103  INFO 12404 --- [           main] o.e.jetty.server.handl
er.ContextHandler  : Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@6293abcc{app
lication,/,[org.springframework.boot.web.embedded.jetty.JettyServletWebServerFac
tory$LoaderHidingResource@7995092a],AVAILABLE}
2019-02-11 23:07:09.106  INFO 12404 --- [           main] org.eclipse.jetty.serv
er.Server          : Started @16076ms

....

2019-02-11 23:07:10.454  INFO 12404 --- [           main] o.e.j.s.h.ContextHandl
er.application     : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-02-11 23:07:10.454  INFO 12404 --- [           main] o.s.web.servlet.Dispat
cherServlet        : FrameworkServlet 'dispatcherServlet': initialization starte
d
2019-02-11 23:07:10.479  INFO 12404 --- [           main] o.s.web.servlet.Dispat
cherServlet        : FrameworkServlet 'dispatcherServlet': initialization comple
ted in 20 ms
2019-02-11 23:07:10.844  INFO 12404 --- [           main] o.e.jetty.server.Abstr
actConnector       : Started ServerConnector@1bd4fdd{HTTP/1.1,[http/1.1]}{0.0.0.
0:8080}
2019-02-11 23:07:10.849  INFO 12404 --- [           main] o.s.b.web.embedded.jet
ty.JettyWebServer  : Jetty started on port(s) 8080 (http/1.1) with context path
'/'
2019-02-11 23:07:10.854  INFO 12404 --- [           main] org.hanbo.boot.app.App
                   : Started App in 15.3 seconds (JVM running for 17.828)

The first segment is the start of the application run. Somewhere at the very end, you can see the embedded Jetty server initialization. In the middle of the output, there is more of Jetty server starting up. At the very end, we see that the application is running on port 8080 and is ready to accept user request. If you don't see any exception output, and see the last line there, you have started the application successfully.

To test the application, just copy and paste the following link to browser:

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

Then you will see a simple page displaying:

What did you say?

I said: "This is pretty crazy."

Or try something new:

http://localhost:8080/meow?sayit=Hello+World

Then you will see a simple page displaying:

What did you say?

I said: "Hello World."

Summary

This is a very straight forward tutorial on Spring Boot. I took one article which I submitted last year and removed the use of embedded Tomcat server and replaced it with embedded Jetty server. It is fairly straight forward, all one needs to do is exclude the artifact "spring-boot-starter-tomcat". Then add the equivalent artifact for embedded Jetty server. To support JSP/JSTL for Spring MVC, one must add at least two more Jetty related artifacts for JSP/JSTL. Once you know how to do this, you can use the same approach to replace all embedded Tomcat servers from the sample projects of my Spring Boot tutorials from 2018. Enjoy!

History

  • 02/11/2019 - Initial draft

License

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

Share

About the Author

Han Bo Sun
Team Leader The Judge Group
United States United States
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --