Micronaut Servlet

Provides integration between Micronaut and the Servlet API

Version:

1 Introduction

This project implements a Micronaut HTTP server backed onto the Servlet API and includes various subprojects that allow running popular Servlet containers as servers.

This project is for users who fall into one of the following categories:

  • Users who want to use Micronaut but the target deployment environment is based on Servlets

  • Users who prefer the thread per connection model of the Servlet API over the Event Loop model provided by the default Netty-based HTTP server

  • Users who have existing Servlets and/or Filters that they wish to combine with Micronaut.

2 Working with the Servlet API

In general you can follow the documentation for the HTTP server when building applications. All non-Netty specific features of the default HTTP server should work the same for Servlet containers (Report an issue if you find a difference).

There are a couple of additional extensions within Micronaut Servlet that make it easier to work with the Servlet API which are detailed in the following sections.

Injecting the Servlet Request and Response

You can receive the HttpServletRequest and HttpServletResponse objects directly as parameters:

Using the Request and Response
@Get("/hello")
void process(
        HttpServletRequest request, (1)
        HttpServletResponse response) (2)
        throws IOException {
    response.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
    response.setStatus(HttpStatus.ACCEPTED.getCode());
    try (final PrintWriter writer = response.getWriter()) {
        writer.append("Hello ").append(request.getParameter("name"));
        writer.flush();
    }
}
1 The request object
2 The response object

Simplified I/O code with Readable and Writable

Writing to the response and reading from the request can be simplified with Micronaut’s Readable and Writable interfaces:

Using Readable and Writable
import io.micronaut.core.io.Readable;
import io.micronaut.core.io.Writable;

@Post(value = "/writable", processes = "text/plain")
Writable readAndWrite(@Body Readable readable) throws IOException {
    return out -> {
        try (BufferedReader reader = new BufferedReader(readable.asReader())) {
            out.append("Hello ").append(reader.readLine());
        }
    };
}

Multipart support with @Part

Multipart support is improved with the ability to inject parts using the annotation io.micronaut.http.annotation.Part. For example:

Using @Part
@Post(value = "/multipart", consumes = MediaType.MULTIPART_FORM_DATA, produces = "text/plain")
String multipart(
        String attribute, (1)
        @Part("one") Person person, (2)
        @Part("two") String text, (3)
        @Part("three") byte[] bytes, (4)
        @Part("four") javax.servlet.http.Part raw, (5)
        @Part("five") CompletedPart part) { (6)
    return "Ok";
}
1 You can receive attributes with just parameter names that match the attribute name
2 Parts that have a content type of application/json can be bound to POJOs
3 You can read parts as text
4 You can read parts as byte[]
5 You can receive the raw javax.servlet.http.Part
6 You can receive Micronaut’s CompletedPart interface which works with Netty too

3 WAR Deployment

To deploy as a WAR file you need to make some adjustments to your dependencies.

Firsts make the server you are using a developmentOnly dependency (or provided in Maven):

developmentOnly("io.micronaut.servlet:micronaut-http-server-jetty:1.0.2")
<dependency>
    <groupId>io.micronaut.servlet</groupId>
    <artifactId>micronaut-http-server-jetty</artifactId>
    <version>1.0.2</version>
    <scope>provided</scope>
</dependency>

Then make sure you include micronaut-servlet-engine dependency in your build configuration:

implementation("io.micronaut.servlet:micronaut-servlet-engine:1.0.2")
<dependency>
    <groupId>io.micronaut.servlet</groupId>
    <artifactId>micronaut-servlet-engine</artifactId>
    <version>1.0.2</version>
</dependency>

Then alter your build configuration to build a WAR file. In Gradle this can be done by applying the WAR plugin:

Applying the Gradle WAR plugin
plugins {
    id "war"
    id "application"
}

You can then build the WAR file and deploy it to the Servlet container as per the instructions provided by the container.

Micronaut will load using MicronautServletInitializer which registers the DefaultMicronautServlet instance.

4 Jetty Server

To use Jetty as a server add the following dependency:

implementation("io.micronaut.servlet:micronaut-http-server-jetty:1.0.2")
<dependency>
    <groupId>io.micronaut.servlet</groupId>
    <artifactId>micronaut-http-server-jetty</artifactId>
    <version>1.0.2</version>
</dependency>

Jetty is supported with GraalVM native image
If you plan to produce a WAR file then the dependency should be developmentOnly.

To customize the Jetty server you can use the following configuration properties:

🔗
Table 1. Configuration Properties for JettyConfiguration
Property Type Description

micronaut.server.jetty.idle-timeout

long

micronaut.server.jetty.persistent-connections-enabled

boolean

micronaut.server.jetty.send-server-version

boolean

micronaut.server.jetty.send-xpowered-by

boolean

micronaut.server.jetty.send-date-header

boolean

micronaut.server.jetty.delay-dispatch-until-content

boolean

micronaut.server.jetty.customizers

java.util.List

micronaut.server.jetty.output-buffer-size

int

micronaut.server.jetty.output-aggregation-size

int

micronaut.server.jetty.request-header-size

int

micronaut.server.jetty.response-header-size

int

micronaut.server.jetty.header-cache-size

int

micronaut.server.jetty.secure-port

int

micronaut.server.jetty.secure-scheme

java.lang.String

micronaut.server.jetty.form-encoded-methods

java.lang.String[]

micronaut.server.jetty.max-error-dispatches

int

micronaut.server.jetty.min-request-data-rate

long

micronaut.server.jetty.min-response-data-rate

long

micronaut.server.jetty.request-cookie-compliance

org.eclipse.jetty.http.CookieCompliance

micronaut.server.jetty.response-cookie-compliance

org.eclipse.jetty.http.CookieCompliance

micronaut.server.jetty.multi-part-form-data-compliance

org.eclipse.jetty.server.MultiPartFormDataCompliance

micronaut.server.jetty.notify-remote-async-errors

boolean

micronaut.server.jetty.relative-redirect-allowed

boolean

micronaut.server.jetty.init-parameters

java.util.Map

Sets the servlet init parameters.

Or you can register a BeanCreatedEventListener:

Jetty Server Customization
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import org.eclipse.jetty.server.Server;
import javax.inject.Singleton;

@Singleton
public class JettyServerCustomizer implements BeanCreatedEventListener<Server> {
    @Override
    public Server onCreated(BeanCreatedEvent<Server> event) {
        Server jettyServer = event.getBean();
        // perform customizations...
        return jettyServer;
    }
}

5 Tomcat Server

To use Tomcat as a server add the following dependency:

implementation("io.micronaut.servlet:micronaut-http-server-tomcat:1.0.2")
<dependency>
    <groupId>io.micronaut.servlet</groupId>
    <artifactId>micronaut-http-server-tomcat</artifactId>
    <version>1.0.2</version>
</dependency>

Tomcat is supported with GraalVM native image
If you plan to produce a WAR file then the dependency should be developmentOnly.

To customize the Tomcat server you can use the following configuration properties:

🔗
Table 1. Configuration Properties for TomcatConfiguration
Property Type Description

micronaut.server.tomcat.service

org.apache.catalina.Service

micronaut.server.tomcat.allow-trace

boolean

micronaut.server.tomcat.async-timeout

long

micronaut.server.tomcat.discard-facades

boolean

micronaut.server.tomcat.enable-lookups

boolean

micronaut.server.tomcat.max-cookie-count

int

micronaut.server.tomcat.max-parameter-count

int

micronaut.server.tomcat.max-post-size

int

micronaut.server.tomcat.max-save-post-size

int

micronaut.server.tomcat.parse-body-methods

java.lang.String

micronaut.server.tomcat.port

int

micronaut.server.tomcat.port-offset

int

micronaut.server.tomcat.proxy-name

java.lang.String

micronaut.server.tomcat.proxy-port

int

micronaut.server.tomcat.redirect-port

int

micronaut.server.tomcat.scheme

java.lang.String

micronaut.server.tomcat.secure

boolean

micronaut.server.tomcat.uriencoding

java.lang.String

micronaut.server.tomcat.use-body-encoding-for-uri

boolean

micronaut.server.tomcat.xpowered-by

boolean

micronaut.server.tomcat.use-ipvhosts

boolean

micronaut.server.tomcat.encoded-solidus-handling

java.lang.String

micronaut.server.tomcat.domain

java.lang.String

micronaut.server.tomcat.throw-on-failure

boolean

micronaut.server.tomcat.protocol

java.lang.String

The protocol to use. Defaults to org.apache.coyote.http11.Http11NioProtocol.

micronaut.server.tomcat.attributes

java.util.Map

The connector attributes

Or you can register a BeanCreatedEventListener:

Tomcat Server Customization
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import org.apache.catalina.startup.Tomcat;
import javax.inject.Singleton;

@Singleton
public class TomcatServerCustomizer implements BeanCreatedEventListener<Tomcat> {
    @Override
    public Tomcat onCreated(BeanCreatedEvent<Tomcat> event) {
        Tomcat tomcat = event.getBean();
        // perform customizations...
        return tomcat;
    }
}

6 Undertow Server

To use Undertow as a server add the following dependency:

implementation("io.micronaut.servlet:micronaut-http-server-undertow:1.0.2")
<dependency>
    <groupId>io.micronaut.servlet</groupId>
    <artifactId>micronaut-http-server-undertow</artifactId>
    <version>1.0.2</version>
</dependency>

Undertow is not supported with GraalVM native image. Use Jetty or Tomcat if native image support is required. See UNDERTOW-1408.
If you plan to produce a WAR file then the dependency should be developmentOnly.

To customize the Undertow server you can use the following configuration properties:

🔗
Table 1. Configuration Properties for UndertowConfiguration
Property Type Description

micronaut.server.undertow.buffer-size

int

micronaut.server.undertow.io-threads

int

micronaut.server.undertow.worker-threads

int

micronaut.server.undertow.direct-buffers

boolean

micronaut.server.undertow.handler

io.undertow.server.HttpHandler

micronaut.server.undertow.worker

org.xnio.XnioWorker

micronaut.server.undertow.byte-buffer-pool

io.undertow.connector.ByteBufferPool

micronaut.server.undertow.worker-options

java.util.Map

Sets the worker options.

micronaut.server.undertow.socket-options

java.util.Map

Sets the socket options.

micronaut.server.undertow.server-options

java.util.Map

Sets the server options

Or you can register a BeanCreatedEventListener:

Undertow Server Customization
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import io.undertow.Undertow;
import javax.inject.Singleton;

@Singleton
public class UndertowServerCustomizer implements BeanCreatedEventListener<Undertow.Builder> {
    @Override
    public Undertow.Builder onCreated(BeanCreatedEvent<Undertow.Builder> event) {
        Undertow.Builder undertowBuilder = event.getBean();
        // perform customizations...
        return undertowBuilder;
    }
}

7 FAQ

Where can I find the source code?

You can find the source code of this project in this repository:

How do I configure Multipart handling?

Multipart handling is disabled by default. You can enable it with the following configuration properties.

How do I configure Static Resource handling for the embedded server?

Static resources are not enabled by default. See Serving Static Resources for how to configure paths to static resources.

How do I enable HTTPS for the embedded server?