By default when we run spring boot application, it runs a tomcat server. I have personally found tomcat too heavyweight and I prefer to use Jetty for writing a webservices backend.
to
The next step is to add a customizer for jetty which will allow us to set some parameters related to Jetty.
As we can see the customizer uses a set of variables that we can override in application.properties file to modify the behavior of the server.
2018-12-19 10:54:08.403 INFO 16029 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2018-12-19 10:54:08.424 INFO 16029 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-12-19 10:54:08.424 INFO 16029 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/9.0.12
To replace tomcat with Jetty, we need to make a couple of changes. The first step is to add Jetty dependencies in the pom.xml.
Since springframework boot bom automatically includes a dependency on tomcat in spring-boot-starter-web, we specifically need to exclude it. So we change<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-deploy</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-rewrite</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
to
<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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package in.springframework.blog.tutorials; | |
import org.apache.logging.log4j.LoggingException; | |
import org.eclipse.jetty.server.*; | |
import org.eclipse.jetty.server.handler.HandlerCollection; | |
import org.eclipse.jetty.server.handler.RequestLogHandler; | |
import org.eclipse.jetty.util.thread.QueuedThreadPool; | |
import org.springframework.beans.factory.annotation.Value; | |
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; | |
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; | |
import org.springframework.boot.web.server.WebServerFactoryCustomizer; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import java.io.File; | |
/** | |
* Created by vinay on 2/3/16. | |
*/ | |
@Configuration | |
public class HelloWorldJettyCustomizer { | |
@Bean | |
WebServerFactoryCustomizer<JettyServletWebServerFactory> containerCustomizer( | |
@Value("${server.port:8081}") final int port, | |
@Value("${jetty.acceptqueuesize:5000}") final String acceptQueueSize, | |
@Value("${jetty.threadPool.maxThreads:2000}") final String maxThreads, | |
@Value("${jetty.threadPool.minThreads:8}") final String minThreads, | |
@Value("${jetty.threadPool.idleTimeout:60000}") final String idleTimeout, | |
@Value("${logging.path:/tmp}") final String loggingPath) | |
throws Exception { | |
// This is boiler plate code to setup https on embedded Tomcat | |
// with Spring Boot: | |
return container -> { | |
container.addServerCustomizers((JettyServerCustomizer) server -> { | |
// Enable logs | |
File logFile = new File(loggingPath + "/product-yyyy_mm_dd.access.log"); | |
String logFilename = logFile.getAbsolutePath(); | |
if (!logFile.getParentFile().exists() && !logFile.getParentFile().mkdirs()) { | |
throw new LoggingException(String.format("%s could not be created.", logFile.getParentFile().getAbsolutePath())); | |
} | |
NCSARequestLog requestLog = new NCSARequestLog(logFilename); | |
requestLog.setAppend(true); | |
requestLog.setExtended(false); | |
requestLog.setLogTimeZone("UTC"); | |
RequestLogHandler rlh = new RequestLogHandler(); | |
rlh.setRequestLog(requestLog); | |
Handler[] handlers = server.getHandlers(); | |
if (handlers == null || handlers.length == 0) { | |
server.setHandler(rlh); | |
} | |
else { | |
HandlerCollection handlerCollection = new HandlerCollection(); | |
for (int i = 0; i < handlers.length; ++i) { | |
handlerCollection.addHandler(handlers[i]); | |
} | |
handlerCollection.addHandler(rlh); | |
server.setHandler(handlerCollection); | |
} | |
// Tweak the connection pool used by Jetty to handle incoming HTTP connections | |
final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class); | |
threadPool.setMaxThreads(Integer.valueOf(maxThreads)); | |
threadPool.setMinThreads(Integer.valueOf(minThreads)); | |
threadPool.setIdleTimeout(Integer.valueOf(idleTimeout)); | |
threadPool.setName("Jetty-Threadpool"); | |
for (Connector connector : server.getConnectors()) { | |
if (connector instanceof ServerConnector) { | |
ServerConnector serverConnector = (ServerConnector)connector; | |
serverConnector.setPort(port); | |
serverConnector.setAcceptQueueSize(Integer.valueOf(acceptQueueSize)); | |
serverConnector.setIdleTimeout(Integer.valueOf(idleTimeout)); | |
HttpConnectionFactory connectionFactory = connector.getConnectionFactory(HttpConnectionFactory.class); | |
connectionFactory.getHttpConfiguration().setSendServerVersion(false); | |
} | |
} | |
}); | |
}; | |
} | |
} |
As we can see the customizer uses a set of variables that we can override in application.properties file to modify the behavior of the server.
2018-12-19 11:06:44.577 INFO 16219 --- [ main] o.e.jetty.server.AbstractConnector : Started ServerConnector@42ebece0{HTTP/1.1,[http/1.1]}{0.0.0.0:8081} 2018-12-19 11:06:44.580 INFO 16219 --- [ main] o.s.b.web.embedded.jetty.JettyWebServer : Jetty started on port(s) 8081 (http/1.1) with context path ''Now the logs clearly show that in place of tomcat, it is running jetty.