Have you
ever wanted to configure internal Java servers using HTTP/2 (or H2 in short), because
of the following advantages?
Read more on how to produce a native executable of this setup in Part-3 of this article.
Note: At present, only Jetty client supports H2C.
Now run the program using NetBeans or maven-command line and hit the url http://localhost:8080/hello-servlet in browser.
You can get source for this project from here. You can directly open the project in NetBeans and run or run it from command line using maven.
- Internal clients making concurrent calls, can now use a single connection by utilizing the multiplexing nature of HTTP/2.
- Server will/can use less threads as there are less connections overall.
- Servers can also push resources/data and can communicate using websockets
Or what if
you want to save every bit of CPU and time by skipping encryption and
decryption?
You are at
the right place. Since everyone nowadays is moving towards (or talking about)
micro services, we will also configure Jetty HTTP/2 server in embedded mode.
What more? We
are also going to configure our server to use Asynchronous Servlets and Asynchronous
IO (aka non-blocking IO or NIO) in Part-2 of this article.
Software used
- Java 11
- Jetty 9.4.28
- NetBeans IDE 11.3
Let’s configure
HTTP/1.1 and HTTP/2 over plain text (aka H2C) on same port. This has the
advantage that the interested clients can speak directly HTTP/2 over plain text,
without upgrading from HTTP/1.1 to HTTP/2.
Server configuration
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class Main {
private static final int PORT = 8080;
private static final String HOST = "localhost";
public static void main(String[] args) throws Exception {
Server server = new Server();
// HTTP connector
HttpConfiguration http2Config = new HttpConfiguration();
ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(), new HTTP2CServerConnectionFactory(http2Config));
http.setHost(HOST);
http.setPort(PORT);
http.setIdleTimeout(30_000);
// Set the connector
server.addConnector(http);
// set servlet handler
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
ServletHolder asyncHolder = context.addServlet(HelloServlet.class, "/hello-servlet");
server.setHandler(context);
server.start();
server.join();
}
}
Servlet content
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
response.getWriter().println("<h1>Hello from HelloServlet</h1>");
}
}
POM file
<?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>
<groupId>com.pb</groupId>
<artifactId>jetty-http2-server</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jetty.version>9.4.28.v20200408</jetty.version>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-http-client-transport</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.pb.jetty.http2.server.Main</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Now run the program using NetBeans or maven-command line and hit the url http://localhost:8080/hello-servlet in browser.
You can get source for this project from here. You can directly open the project in NetBeans and run or run it from command line using maven.
This comment has been removed by a blog administrator.
ReplyDeleteThis article provides a useful practical example of configuring an embedded Jetty server for HTTP/2 using Java 11. The explanation of HTTP/2 multiplexing, H2C, and running HTTP/1.1 and HTTP/2 on the same port makes the server configuration much easier to understand, especially for developers working with internal services and microservice architectures.
ReplyDeleteThe HTTP2CServerConnectionFactory configuration is particularly interesting because it demonstrates how Jetty can support HTTP/2 over clear text without going through the TLS setup required by browser-based HTTP/2. The accompanying servlet example also shows how the server and application layer connect in a straightforward Java environment, which fits naturally with broader Java Full Stack Course topics.