Pages

Wednesday, April 15, 2020

Spring Boot - Configure Jetty Server

1. Introduction


In this article, You'll learn how to configure the jetty server in spring boot instead of the default tomcat server.

After creating a new spring boot application just start the application. That generates the following log and look at the last two lines that mentioning Tomcat Started on port 8080.

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.6.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>
 <groupId>com.javaprogram</groupId>
 <artifactId>spring-boot-app</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>spring-boot-app</name>
 <description>Demo project for Spring Boot</description>

 <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.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
   <exclusions>
    <exclusion>
     <groupId>org.junit.vintage</groupId>
     <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
   </exclusions>
  </dependency>
 </dependencies>

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

</project>

Log:

If you are using a "spring-boot-starter-web" starter then it enables tomcat as an embedded server by default.

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

2020-04-15 17:40:27.898  INFO 28475 --- [           main] c.j.s.SpringBootAppApplication           : Starting SpringBootAppApplication on -Pro-2.local with PID 28475 (/Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app/target/classes started by venkateshn in /Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app)
2020-04-15 17:40:27.901  INFO 28475 --- [           main] c.j.s.SpringBootAppApplication           : No active profile set, falling back to default profiles: default
2020-04-15 17:40:29.070  INFO 28475 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-04-15 17:40:29.086  INFO 28475 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-04-15 17:40:29.086  INFO 28475 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.33]
2020-04-15 17:40:29.166  INFO 28475 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-04-15 17:40:29.166  INFO 28475 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1198 ms
2020-04-15 17:40:29.361  INFO 28475 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-15 17:40:29.570  INFO 28475 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-04-15 17:40:29.575  INFO 28475 --- [           main] c.j.s.SpringBootAppApplication           : Started SpringBootAppApplication in 2.17 seconds (JVM running for 2.782)


2. Enable Jetty Server in Spring Boot


This is quite easy to enable the Jetty server by disabling the existing default tomcat server.

You need to exclude the tomcat from the web starter.


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


For now, the jetty server is not added yet. But let us start the application and see how the application is deployed.

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

2020-04-15 17:51:14.200  INFO 28944 --- [           main] c.j.s.SpringBootAppApplication           : Starting SpringBootAppApplication on -Pro-2.local with PID 28944 (/Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app/target/classes started by venkateshn in /Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app)
2020-04-15 17:51:14.203  INFO 28944 --- [           main] c.j.s.SpringBootAppApplication           : No active profile set, falling back to default profiles: default
2020-04-15 17:51:14.911  INFO 28944 --- [           main] c.j.s.SpringBootAppApplication           : Started SpringBootAppApplication in 1.217 seconds (JVM running for 1.588)


From the log, It is saying the application is started but not deployed on any server. That is indicating that no server is attached to the application.

Adding jetty server into spring boot with the jetty starter as "spring-boot-starter-jetty" in pom.xml

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

If the server is started already on the same port 8080, it produces the following error.

Web server failed to start. Port 8080 was already in use.

Successful application startup log.

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

2020-04-15 17:54:59.287  INFO 29104 --- [           main] c.j.s.SpringBootAppApplication           : Starting SpringBootAppApplication on -Pro-2.local with PID 29104 (/Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app/target/classes started by venkateshn in /Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-app)
2020-04-15 17:54:59.291  INFO 29104 --- [           main] c.j.s.SpringBootAppApplication           : No active profile set, falling back to default profiles: default
2020-04-15 17:55:00.603  INFO 29104 --- [           main] org.eclipse.jetty.util.log               : Logging initialized @2514ms to org.eclipse.jetty.util.log.Slf4jLog
2020-04-15 17:55:00.785  INFO 29104 --- [           main] o.s.b.w.e.j.JettyServletWebServerFactory : Server initialized with port: 8080
2020-04-15 17:55:00.793  INFO 29104 --- [           main] org.eclipse.jetty.server.Server          : jetty-9.4.27.v20200227; built: 2020-02-27T18:37:21.340Z; git: a304fd9f351f337e7c0e2a7c28878dd536149c6c; jvm 1.8.0_161-b12
2020-04-15 17:55:00.848  INFO 29104 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring embedded WebApplicationContext
2020-04-15 17:55:00.848  INFO 29104 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1440 ms
2020-04-15 17:55:01.031  INFO 29104 --- [           main] org.eclipse.jetty.server.session         : DefaultSessionIdManager workerName=node0
2020-04-15 17:55:01.031  INFO 29104 --- [           main] org.eclipse.jetty.server.session         : No SessionScavenger set, using defaults
2020-04-15 17:55:01.032  INFO 29104 --- [           main] org.eclipse.jetty.server.session         : node0 Scavenging every 660000ms
2020-04-15 17:55:01.043  INFO 29104 --- [           main] o.e.jetty.server.handler.ContextHandler  : Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@42a9a63e{application,/,[file:///private/var/folders/g0/0x5m1w1950z18h3m6z6h1_000000gn/T/jetty-docbase.8312808006303778546.8080/],AVAILABLE}
2020-04-15 17:55:01.044  INFO 29104 --- [           main] org.eclipse.jetty.server.Server          : Started @2957ms
2020-04-15 17:55:01.307  INFO 29104 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-15 17:55:01.684  INFO 29104 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-04-15 17:55:01.684  INFO 29104 --- [           main] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-04-15 17:55:01.696  INFO 29104 --- [           main] o.s.web.servlet.DispatcherServlet        : Completed initialization in 11 ms
2020-04-15 17:55:01.789  INFO 29104 --- [           main] o.e.jetty.server.AbstractConnector       : Started ServerConnector@18f20260{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2020-04-15 17:55:01.791  INFO 29104 --- [           main] o.s.b.web.embedded.jetty.JettyWebServer  : Jetty started on port(s) 8080 (http/1.1) with context path '/'
2020-04-15 17:55:01.797  INFO 29104 --- [           main] c.j.s.SpringBootAppApplication           : Started SpringBootAppApplication in 3.194 seconds (JVM running for 3.71)


Now it is saying application on "Jetty started on port(s) 8080" and created instance for Jetty embed server using JettyEmbeddedWebAppContext.

3. Spring Boot Jetty Configurations


Spring Boot provides the configurations through application.properties file related to Jetty. You can customize which port jetty should be running and how many threads used.

And also many props are available to use. Even you can limit the post request size to a specific value.

The below all are pertaining to the jetty.

#Jetty Configurations

server.port=8082
server.servlet.context-path=/home
server.jetty.acceptors=1 
#Number of acceptor threads to use. When the value is -1.

server.jetty.accesslog.append=false
 # Append to log.
 
server.jetty.accesslog.date-format=dd/MMM/yyyy:HH:mm:ss Z 
# Timestamp format of the request log.

server.jetty.accesslog.enabled=false 
# Enable access log.

server.jetty.accesslog.extended-format=false
 # Enable extended NCSA format.
 
server.jetty.accesslog.file-date-format=dd/MMM/yyyy
# Date format to place in a log filename.

server.jetty.accesslog.filename= app.log
# Log filename. If not specified, logs redirect to "System.err".

server.jetty.accesslog.locale=IN
# Locale of the request log.

server.jetty.accesslog.log-cookies=false 
# Enable logging of the request cookies.

server.jetty.accesslog.log-latency=false 
# Enable logging of request processing time.

server.jetty.accesslog.log-server=false 
# Enable logging of the request hostname.

server.jetty.accesslog.retention-period=31
server.jetty.accesslog.time-zone=GMT 
# Timezone of the request log.

#server.jetty.max-http-post-size=200000B # Maximum size of the HTTP post or put content.
# Number of selector threads to use. When the value is -1.
server.jetty.selectors=2 

4. Configure Properties Through Bean JettyEmbeddedServletContainerFactory


All the above properties can be also configured from java code as well in Spring Boot 2.0 release.

import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;

@Bean
public ConfigurableServletWebServerFactory webServerFactory() 
{
    JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
    factory.setPort(9009);
    factory.setContextPath("/app");
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}


Before Spring Boot 2.0

@Bean
public JettyEmbeddedServletContainerFactory  jettyEmbeddedServletContainerFactory() {
    JettyEmbeddedServletContainerFactory jettyContainer = 
        new JettyEmbeddedServletContainerFactory();
      
    jettyContainer.setPort(9002);
    jettyContainer.setContextPath("/app");
    return jettyContainer;
}

5. Jetty Start Up Errors


If you get any of these exceptions to the values mapped to the given property, Please provide the appropriate values.


***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'server.jetty.acceptors' to java.lang.Integer:

    Property: server.jetty.acceptors
    Value: 1 # Number of acceptor threads to use. When the value is -1.
    Origin: class path resource [application.properties]:5:24
    Reason: failed to convert java.lang.String to java.lang.Integer

Action:

Update your application's configuration

I have also faced the same problem and resolved by providing valid values.

6. Conclusion


In this article, We've seen how to configure Jetty Server by adding jetty starter "spring-boot-starter-jetty". How to enable a certain property from application.properties file and java code.


As usual, the Code shown is present is over GitHub.

GitHub Code

No comments:

Post a Comment

Please do not add any spam links in the comments section.