servers

servers

Run your application on top of your favorite server!

Change one line and switch between Netty, Jetty or Undertow!!

netty

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

exports

  • Server

dependency

<dependency>
  <groupId>org.jooby</groupId>
  <artifactId>jooby-netty</artifactId>
  <version>1.0.3</version>
</dependency>

usage

In order to use a web server all you have to do is add the dependency to your build system.

http/2

HTTP/2 is fully supported:

| H2        | H2C           | PUSH  |
| --------- | ------------- | ----- |
| Yes       | Yes           | Yes   |

No extra configuration is necessary.

server.conf

# netty defaults 
server.module = org.jooby.netty.Netty

server.http2.cleartext = true

netty {

  http {

    MaxInitialLineLength = 4k

    MaxHeaderSize = ${server.http.HeaderSize}

    MaxChunkSize = 16k

    MaxContentLength = ${server.http.MaxRequestSize}

    IdleTimeout = ${server.http.IdleTimeout}

  }

  threads {

    Min = ${server.threads.Min}

    Max = ${server.threads.Max}

    Name = netty task

    Boss = 1

    Worker = ${runtime.processors-x2}

  }

  options {

    SO_REUSEADDR = true

  }

  worker {

    options {

      SO_REUSEADDR = true

    }

  }

}

undertow

Undertow is a flexible performant web server written in java, providing both blocking and non-blocking API’s based on NIO.

exports

  • Server

dependency

<dependency>
  <groupId>org.jooby</groupId>
  <artifactId>jooby-undertow</artifactId>
  <version>1.0.3</version>
</dependency>

usage

In order to use a web server all you have to do is add the dependency to your build system.

http/2

HTTP/2 is fully supported:

| H2        | H2C           | PUSH  |
| --------- | ------------- | ----- |
| Yes       | Yes           | Yes   |

You need Java 8 Update 71 or higher (integration tests uses Java 8 Update 101).

See Java 8 releases for more details.

server.conf

# undertow defaults 
server.module = org.jooby.undertow.Undertow

server.http2.cleartext = true

undertow {

  bufferSize = ${server.http.ResponseBufferSize}

  workerThreads = ${server.threads.Max}

  # Waits a set length of time for the handler to shut down. It provides a way to prevent the server 
  # from accepting new requests, and wait for existing requests to complete 
  awaitShutdown = 1000

  server {

    ALLOW_EQUALS_IN_COOKIE_VALUE = true

    ALWAYS_SET_KEEP_ALIVE = true

    # The maximum size in bytes of a http request header. 
    MAX_HEADER_SIZE = ${server.http.HeaderSize}

    # The default maximum size of the HTTP entity body. 
    MAX_ENTITY_SIZE = ${server.http.MaxRequestSize}

    # The maximum number of parameters that will be parsed. This is used to protect against hash 
    # vulnerabilities. 
    # This applies to both query parameters, and to POST data, but is not cumulative 
    # (i.e. you can potentially have max parameters * 2 total parameters). 
    MAX_PARAMETERS = 1000

    # The maximum number of headers that will be parsed. This is used to protect against hash 
    # vulnerabilities. 
    MAX_HEADERS = 200

    # The maximum number of headers that will be parsed. This is used to protect against hash 
    # vulnerabilities. 
    MAX_COOKIES = 200

    URL_CHARSET = ${application.charset}

    # If this is true then the parser will decode the URL and query parameters using the selected 
    # character encoding (URL_CHARSET by default). If this is false they will not be decoded. 
    # This will allow a later handler to decode them into whatever charset is desired. 
    DECODE_URL = true

    # The idle timeout in milliseconds after which the channel will be closed. 
    # If the underlying channel already has a read or write timeout set the smaller of the two values will be used 
    # for read/write timeouts. 
    IDLE_TIMEOUT = ${server.http.IdleTimeout}

  }

  worker {

    WORKER_NAME = utow

  }

  socket {

    BACKLOG = 1024

  }

  ws {

    # The maximum size of a text message during parsing/generating. 
    MaxTextBufferSize = ${server.ws.MaxTextMessageSize}

    # The maximum size of a binary message during parsing/generating. 
    MaxBinaryBufferSize = ${server.ws.MaxBinaryMessageSize}

    # The time in ms (milliseconds) that a websocket may be idle before closing. 
    IdleTimeout = ${server.ws.IdleTimeout}

  }

}

jetty

Jetty provides a Web server and javax.servlet container, plus support for HTTP/2, WebSocket and many other integrations.

exports

  • Jetty Server

dependency

<dependency>
  <groupId>org.jooby</groupId>
  <artifactId>jooby-jetty</artifactId>
  <version>1.0.3</version>
</dependency>

usage

In order to use a web server all you have to do is add the dependency to your build system. Jooby will find the server and start it.

http/2

HTTP/2 is fully supported:

| H2        | H2C           | PUSH  |
| --------- | ------------- | ----- |
| Yes       | Yes           | Yes   |

You need to add alpn-boot to the JVM bootstrap path. See Jetty HTTP2 documentation.

server.conf

# jetty defaults 
server.module = org.jooby.jetty.Jetty

server.http2.cleartext = true

jetty {

  threads {

    MinThreads = ${server.threads.Min}

    MaxThreads = ${server.threads.Max}

    IdleTimeout = ${server.threads.IdleTimeout}

    Name = jetty task

  }

  FileSizeThreshold = 16k

  http {

    HeaderCacheSize = ${server.http.HeaderSize}

    RequestHeaderSize = ${server.http.HeaderSize}

    ResponseHeaderSize = ${server.http.HeaderSize}

    OutputBufferSize = ${server.http.ResponseBufferSize}

    SendServerVersion = false

    SendXPoweredBy = false

    SendDateHeader = false

    connector {

      # The accept queue size (also known as accept backlog) 
      AcceptQueueSize = 0

      # Use -1 to disable 
      SoLingerTime = -1

      StopTimeout = 30000

      # Sets the maximum Idle time for a connection, which roughly translates to the Socket#setSoTimeout(int) 
      # call, although with NIO implementations other mechanisms may be used to implement the timeout. 
      # The max idle time is applied: 
      # When waiting for a new message to be received on a connection 
      # When waiting for a new message to be sent on a connection 
      # This value is interpreted as the maximum time between some progress being made on the connection. 
      # So if a single byte is read or written, then the timeout is reset. 
      IdleTimeout = ${server.http.IdleTimeout}

    }

  }

  ws {

    # The maximum size of a text message during parsing/generating. 
    # Text messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE} 
    MaxTextMessageSize = ${server.ws.MaxTextMessageSize}

    # The maximum size of a text message buffer. 
    # Used ONLY for stream based message writing. 
    MaxTextMessageBufferSize = 32k

    # The maximum size of a binary message during parsing/generating. 
    # Binary messages over this maximum will result in a close code 1009 {@link StatusCode#MESSAGE_TOO_LARGE} 
    MaxBinaryMessageSize = ${server.ws.MaxBinaryMessageSize}

    # The maximum size of a binary message buffer 
    # Used ONLY for for stream based message writing 
    MaxBinaryMessageBufferSize = 32k

    # The timeout in ms (milliseconds) for async write operations. 
    # Negative values indicate a disabled timeout. 
    AsyncWriteTimeout = 60000

    # The time in ms (milliseconds) that a websocket may be idle before closing. 
    IdleTimeout = ${server.ws.IdleTimeout}

    # The size of the input (read from network layer) buffer size. 
    InputBufferSize = 4k

  }

  url.charset = ${application.charset}

}

servlets

This module exists for strict environments where the ONLY option is to deploy into a Servlet Container. If you are free to deploy a new server technology, we strongly recommend to avoid this and go directly with Netty, Jetty or Undertow.

usage

In order to deploy into a Servlet Container, we need to generate a *.war file. The next steps guide you on how to do it:

  • Write a war.activator file inside the src/etc directory.

  • Open a console and type: mvn clean package

  • Find the *.war file in the target directory.

limitations

  • web-sockets are not supported
  • some properties has no effect when deploying into a Servlet Container:
    • application.path / contextPath
    • appplication.port
    • max upload file sizes
    • any other server specific property: server., jetty., netty., undertow.

special note on contextPath

To avoid a headache… make sure to use the contextPath variable while loading static/dynamic resources (.css, .js, etc..).

For example:

<html>
<head>
  <link rel="stylesheet" text="text/css" href="{{contextPath}}/css/styles.css">
  <script src="{{contextPath}}/js/app.js"></script>
</head>
</html>

Here the expression: {{contextPath}} corresponds to the template engine (handlebars here) or ${contextPath} for Freemarker.

how it works?

The presence of the src/etc/war.activator file triggers a Maven profile. Content of the file doesn’t matter, just the presence.

The Maven profile build the *.war file using the maven-assembly-plugin. The assembly descriptor can be found here

web.xml

A default web.xml file is generated by the assembly plugin. File looks like:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">
  <context-param>
    <param-name>application.class</param-name>
    <param-value>${application.class}</param-value>
  </context-param>

  <listener>
    <listener-class>org.jooby.servlet.ServerInitializer</listener-class>
  </listener>

  <servlet>
    <servlet-name>jooby</servlet-name>
    <servlet-class>org.jooby.servlet.ServletHandler</servlet-class>
    <load-on-startup>0</load-on-startup>
    <!-- MultiPart setup -->
    <multipart-config>
      <file-size-threshold>0</file-size-threshold>
      <!-- Default 200k -->
      <max-request-size>${war.maxRequestSize}</max-request-size>
    </multipart-config>
  </servlet>

  <servlet-mapping>
    <servlet-name>jooby</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>
upload size

Default upload size is set to 204800b (200kb). If you need to increase the upload size, add the war.maxRequestSize property to pom.xml:

<properties>
  <war.maxRequestSize>1048576</war.maxRequestSize> <!-- 1mb -->
</properties>
custom web.xml

When the generated file isn’t enough, follow these steps:

  1. create a dir: src/etc/war/WEB-INF
  2. save a web.xml file inside that dir
  3. run: mvn clean package

Share