0.89.0 release notes

29th July 2019

New features

  • You can now specify decorators for all services in a Server in a functional way. #1882 #1900

    ServerBuilder sb = new ServerBuilder();
    sb.service(...);
    // After:
    sb.decorator((delegate, ctx, req) -> {
        ...
        return delegate.serve(ctx, req);
    });
    // Before:
    sb.decorator(delegate -> new SimpleServiceDecorator<HttpRequest, HttpResponse>(delegate) {
        @Override
        public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
            ...
            return delegate().serve(ctx, req);
        }
    });
  • You can now use HealthCheckService which has richer functionality than its predecessor HttpHealthCheckService. #1878

    ServerBuilder sb = new ServerBuilder();
    sb.service("/internal/l7check",
               HealthCheckService.builder()
                                 .checkers(...)
                                 .healthyResponse(...)
                                 .unhealthyResponse(...)
                                 .longPolling(Durations.ofMinutes(1))
                                 .updatable(true)
                                 .build());
    • Long-polling query support
      • You can wait until the server becomes healthy or unhealthy and get notified immediately.
    • Easy customization of healthy/unhealthy responses
    • Easy customization of update request handler
  • You now know exact host you are sending your request to when using Armeria client. #1917

    • It was previously not possible when you specified an EndpointGroup as the destination.
    • Therefore, ClientRequestContext.endpoint() may return null since this release when Armeria failed to determine the destination host.
    • ClientRequestContext.endpointSelector() has been added so that you still know which EndpointGroup you are connecting to.
  • BraveClient and BraveService now accept HttpTracing as well as Tracing. #1223 #1906

    Tracing tracing = ...;
    
    // Server-side
    ServerBuilder sb = new ServerBuilder();
    //// Before
    sb.service("/", myService.decorate(BraveService.newDecorator(tracing)));
    //// After
    HttpTracing httpTracing = HttpTracing.create(tracing);
    sb.service("/", myService.decorate(BraveService.newDecorator(httpTracing)));
    
    // Client-side
    HttpClientBuilder cb = new HttpClientBuilder(...);
    //// Before
    cb.decorator(BraveClient.newDecorator(tracing, "myBackend"));
    //// After
    cb.decorator(BraveClient.newDecorator(httpTracing.clientOf("myBackend")));
  • You can now create a decorating Service or Client in a less verbose way by extending new SimpleDecorating* classes. #1881 #1925

    • SimpleDecoratingHttpService extends SimpleDecoratingService<HttpRequest, HttpResponse>
    • SimpleDecoratingRpcService extends SimpleDecoratingService<RpcRequest, RpcResponse>
    • SimpleDecoratingHttpClient extends SimpleDecoratingClient<HttpRequest, HttpResponse>
    • SimpleDecoratingRpcClient extends SimpleDecoratingClient<RpcRequest, RpcResponse>
  • RpcService has been added for your convenience. #1881 #1925

    • RpcService extends Service<RpcRequest, RpcResponse>

Improvements

  • The output type of RequestLog sanitizer functions has been relaxed to ? so that a user can write much simpler and more efficient sanitizer function. #1810 #1879
    // Before
    Function<HttpHeaders, HttpHeaders> sanitizer = headers -> {
        return headers.toBuilder().removeAndThen("authorization").build();
    };
    // After
    Function<HttpHeaders, Object> sanitizer = headers -> {
        // No need to construct a new HttpHeaders object.
        return headers.toBuilder().removeAndThen("authorization").toString();
    };
    // Even more efficiently
    Function<HttpHeaders, Object> sanitizer = headers -> "sanitized!";
  • A glob path mapping is not translated into a regex path mapping when combined with path prefix anymore. #1929
  • ByteBufHttpData.toInputStream() does not perform extra memory copy anymore. #1918 #1919

Bug fixes

  • Armeria client now sends OPTIONS * HTTP/1.1 instead of HEAD / HTTP/1.1, so that the initial protocol upgrade does not trigger business logic when a server has business logic bound at /. #1895 #1896
  • Response content is not sanitized twice anymore. #1879
  • gRPC message compression is now enabled by default on the server side, so that the default behavior matches that of the upstream implementation. #1885 #1889
  • The max-age attribute in a set-cookie header is now handled correctly when using Spring WebFlux. #1904
  • Fixed a bug where the base URL of the received request is set incorrectly when using Spring WebFlux. #1904
  • HttpHealthCheckedEndpoint does not leak connections and requests after close() is called. #1899
  • BraveClient does not trigger RequestLogAvailabilityException anymore when the request being traced has failed without sending any data. #1911 #1912
  • @ConsumesJson annotation now accepts JSON documents with any charsets rather than only UTF-8. #1920
  • The IllegalStateException raised by pushIfAbsent() is now propagated properly to the CompletableFuture created by RequestContext.makeContextAware(). #1920

Deprecations

  • HttpHealthCheckService and SettableHttpHealthCheckService have been deprecated in favor of HealthCheckService and its builder. #1878

Breaking changes

  • ClientRequestContext.endpoint() may return null since this release. #1917
  • The Endpoint returned by ClientRequestContext.endpoint() now always refers to a single host, not an EndpointGroup. #1917
    • Use ClientRequestContext.endpointSelector().group() to retrieve the related EndpointGroup.

Dependencies

  • gRPC 1.21.0 -> 1.22.1
  • Netty 4.1.37 -> 4.1.38
  • Tomcat 9.0.21 -> 9.0.22, 8.5.42 -> 8.5.43

Thank you