0.88.0 release notes

3rd July 2019

New features

  • ClientRequestContext.current() and ServiceRequestContext.current() have been added so you don't need to downcast RequestContext to ClientRequestContext or ServiceRequestContext. It also makes sure the current context is client-side (or server-side), preventing a ClassCastException. #1869 #1872
    ClientRequestContext cctx = ClientRequestContext.current();
    ServiceRequestContext sctx = ServiceRequestContext.current();
  • currentOrNull() static method has been added to (Client|Service)RequestContext, which is similar to current() but returning null when there's no current context. #1872
    // Before:
    RequestContext ctx = RequestContext.mapCurrent(Function.identity(), null);
    // After:
    ServiceRequestContext sctx = ServiceRequestContext.currentOrNull();
  • You can now specify different AccessLogWriters for different services. #1866
    Server server = new ServerBuilder()
                    .accessLogWriter(accessLogWriterForService1, true)
            .route().path("/svc2") // Will use the fallbackAccessLogWriter.
            .accessLogWriter(fallbackAccessLogWriter, true)
  • The metrics of the Executor specified in ServerBuilder.blockingTaskExecutor() will be exposed under executor{name=armeriaBlockingTaskExecutor}. #1683 #1841
  • Armeria client will send a DNS query via TCP when a DNS response is truncated due to UDP packet size limitation. #1873
  • You can now specify health check request interval using a Backoff, which means you can have more flexible delay strategy such as adding jitter. #1846
    HttpHealthCheckedEndpointGroup group = new HttpHealthCheckedEndpointGroup(...)
    • By default, HealthCheckedEndpointGroup will now add 20% jitter to the health check request interval.
  • A new module armeria-brave has been added to replace the deprecated armeria-zipkin. #1840
    • The package name has been changed from com.linecorp.armeria.{common,client,server}.tracing to com.linecorp.armeria.{common,client,server}.brave.
    • HttpTracingClient and HttpTracingService have been renamed to BraveClient and BraveService.
  • You can now retrieve the retrofit2.Invocation object associated with the current Retrofit call via InvocationUtil.get(RequestLog), which can be useful when building a meter ID prefix. #1591 #1845
    public class MyRetrofitMeterIdPrefixFunction implements MeterIdPrefixFunction {
        public MeterIdPrefix apply(MeterRegistry registry, RequestLog log) {
            final Invocation invocation = InvocationUtil.getInvocation(log);
            final String service;
            final String method;
            if (invocation != null) {
                service = invocation.method().getDeclaringClass().getSimpleName();
                method = invocation.method().getName();
            } else {
                service = "unknown";
                method = log.method().name();
            return new MeterIdPrefix("call", "service", service, "method", method);
    • We also added RetrofitMeterIdPrefixFunction which provides the sensible default MeterIdPrefixFunction for Retrofit calls.


  • The content negotiation logic has been relaxed so that the server falls back to the service with less constraint when content negotiation fails. Previously, it was rejecting the request. #1860
  • More exceptions are now wrapped by UnprocessedRequestException to indicate whether the request can be safely retried without worrying about sending the request more than once. #1653 #1848
    • Any exceptions that occurred during a connection attempt.
    • Any exceptions that occurred during acquiring an existing connection from a connection pool.
    • We also made UnprocessedRequestException.getCause() is non-null, so you do not need to worry about the case where there is no cause in UnprocessedRequestException.

Bug fixes

  • Server will now allow specifying a @Default annotation with null value. #1858 #1864
  • The DEBUG level log message which occurs when a client sent an ill-formed Accept header is now easier to understand. #1849
  • THttpService now handles HttpStatusException and HttpResponseException correctly, which means they will not be translated into a 200 OK response that contains a TApplicationException anymore. For example, your Thrift clients will see 503 Service Unavailable response when your service throws an HttpStatusException.of(503) rather than 200 OK. #1839 #1867
  • DocService debug form will validate the endpoint path properly now. #1856 #1857
  • RequestContextCurrentTraceContext now calls decorateScope() when necessary. #1840
  • Spring Web and WebFlux integration do not ignore the ssl.keyAlias property anymore. #1843 #1865
  • You will not see an ERROR log message when a client sends a HEAD request to your Spring WebFlux endpoint. #1847 #1859


  • HttpHealthCheckedEndpointGroupBuilder.retryInterval(Duration) has been deprecated. Use retryBackoff(Backoff). #1846
  • Everything in armeria-zipkin has been deprecated. Use armeria-brave. #1840


  • Brave 5.6.3 -> 5.6.6
  • FastUtil 8.2.2 -> 8.2.3
  • Hibernate Validator 6.0.16 -> 6.0.17
  • javax.annotation-api -> jakarta.annotation-api 1.3.4
  • Jetty 9.4.18 -> 9.4.19
  • Micrometer 1.1.4 -> 1.2.0
  • Netty 4.1.34 -> 4.1.37
    • TCNative BoringSSL 2.0.23 -> 2.0.25
  • protobuf-jackson 0.4.0 -> 1.0.0
  • RxJava 2.2.9 -> 2.2.10
  • Spring Boot 2.1.5 -> 2.1.6

Thank you