Using Armeria with Spring WebFlux

Spring framework provides powerful features which are necessary for building a web application, such as dependency injection, data binding, AOP, transaction, etc. In addition, if your Spring application integrates with Armeria, you can leverage the following:

  • Rich support for Apache Thrift and gRPC, including the fancy web console that enables you to send Thrift and gRPC requests from a web browser
  • Ability to run HTTP REST service and RPC service in the same port
  • Full HTTP/2 support for both server-side and client-side, including h2c (plaintext HTTP/2)
  • PROXY protocol support which provides interoperability with load balancers such as HAProxy and AWS ELB

Armeria can be plugged in as the underlying HTTP server for a Spring Boot 2 WebFlux application by adding the following dependency:

build.gradle
dependencies {
    implementation platform('com.linecorp.armeria:armeria-bom:1.31.0')
    implementation platform('io.netty:netty-bom:4.1.115.Final')

    ...
    implementation 'com.linecorp.armeria:armeria-spring-boot2-webflux-starter'
}

The above starter configures Armeria as the HTTP server for WebFlux to run on by referring to application.yml when the application starts up. A user can customize the server configuration with the same properties provided by Spring Boot as for other servers supported with WebFlux such as Tomcat or Reactor Netty. The following is a simple example for configuring the server:

server:
  address: 127.0.0.1
  port: 8080

For a user who wants to customize the web server, ArmeriaServerConfigurator is provided. The user can customize the server by defining a bean of the type in the configuration as follows:

@Configuration
public class ArmeriaConfiguration {
    // A user can configure the server by providing an ArmeriaServerConfigurator bean.
    @Bean
    public ArmeriaServerConfigurator armeriaServerConfigurator() {
        // Customize the server using the given ServerBuilder. For example:
        return builder -> {
            // Add DocService that enables you to send Thrift and gRPC requests
            // from web browser.
            builder.serviceUnder("/docs", new DocService());

            // Log every message which the server receives and responds.
            builder.decorator(LoggingService.newDecorator());

            // Write access log after completing a request.
            builder.accessLogWriter(AccessLogWriter.combined(), false);

            // You can also bind asynchronous RPC services such as Thrift and gRPC:
            // builder.service(THttpService.of(...));
            // builder.service(GrpcService.builder()...build());
        };
    }
}

Armeria can also be plugged as the underlying HTTP client for the Spring WebClient. To customize client settings for the Armeria HTTP client, simply define an ArmeriaClientConfigurator bean in your configuration as follows:

@Configuration
public class ArmeriaConfiguration {
    // Returns a custom ClientFactory with TLS certificate validation disabled,
    // which means any certificate received from the server will be accepted
    // without any verification. It is used for an example which makes the client
    // send an HTTPS request to the server running on localhost with a self-signed
    // certificate. Do NOT use ClientFactory.insecure() or
    // ClientFactoryBuilder.tlsNoVerify() in production.
    @Bean
    public ClientFactory clientFactory() {
        return ClientFactory.insecure();
    }

    // A user can configure a Client by providing an ArmeriaClientConfigurator bean.
    @Bean
    public ArmeriaClientConfigurator
            armeriaClientConfigurator(ClientFactory clientFactory) {

        // Customize the client using the given WebClientBuilder. For example:
        return builder -> {
            // Use a circuit breaker for each remote host.
            final CircuitBreakerRule rule =
                    CircuitBreakerRule.onServerErrorStatus();
            builder.decorator(CircuitBreakerClient.builder(rule)
                                                  .newDecorator());

            // Set a custom client factory.
            builder.factory(clientFactory);
        };
    }
}