Embedding a servlet container

You can make Armeria serve your JEE web application on the same JVM and TCP/IP port by embedding Apache Tomcat or Jetty. Neither Tomcat nor Jetty will open a server socket or accept an incoming connection. All HTTP requests and responses go through Armeria. As a result, you get the following bonuses:

  • Your webapp gets HTTP/2 support for free even if your servlet container does not support it.
  • You can run your RPC services on the same JVM and port as your webapp with no performance loss.

Embedding Apache Tomcat

You need the armeria-tomcat9 dependency:

build.gradle
dependencies {
    implementation platform('com.linecorp.armeria:armeria-bom:1.30.1')

    ...
    implementation 'com.linecorp.armeria:armeria-tomcat9'
}

Then, add a TomcatService to a ServerBuilder:

import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.tomcat.TomcatService;

ServerBuilder sb = Server.builder();

sb.serviceUnder("/tomcat/api/rest/v2/",
                TomcatService.forCurrentClassPath("/webapp"));

sb.serviceUnder("/tomcat/api/rest/v1/",
                TomcatService.forFileSystem("/var/lib/webapps/old_api.war"));

For more information, please refer to the API documentation of TomcatService and TomcatServiceBuilder.

Embedding Jetty

You need armeria-jetty9, additional jetty dependencies and bootstrap code due to its modular design:

build.gradle
dependencies {
    implementation platform('com.linecorp.armeria:armeria-bom:1.30.1')
    implementation platform('org.eclipse.jetty:jetty-bom:undefined')

    ...
    implementation 'com.linecorp.armeria:armeria-jetty9'
    implementation 'org.eclipse.jetty:jetty-webapp'
    implementation 'org.eclipse.jetty:jetty-annotations'
    implementation 'org.eclipse.jetty:apache-jsp'
    implementation 'org.eclipse.jetty:apache-jstl'
}
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.jetty.JettyService;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.apache.jsp.JettyJasperInitializer
import org.eclipse.jetty.plus.annotation.ContainerInitializer
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;

ServerBuilder sb = Server.builder();

sb.serviceUnder("/jetty/api/rest/v2/",
                JettyService.builder()
                            .handler(newWebAppContext("/webapp"))
                            .build());

static WebAppContext newWebAppContext(String resourcePath) throws MalformedURLException {
    final WebAppContext handler = new WebAppContext();
    handler.setContextPath("/");
    handler.setBaseResource(Resource.newClassPathResource(resourcePath));
    handler.setClassLoader(/* Specify your class loader here. */);
    handler.addBean(new ServletContainerInitializersStarter(handler), true);
    handler.setAttribute(
            "org.eclipse.jetty.containerInitializers",
            Collections.singletonList(
                    new ContainerInitializer(new JettyJasperInitializer(), null)));
    return handler;
}

For more information, please refer to the API documentation of JettyService and JettyServiceBuilder.