1.27.0 release notes

30th January 2024

🌟 New features

  • xDS-based EndpointGroup: You can utilize xDS protocol to create XdsEndpointGroup for service discovery. #5342 #5336

    XdsBootstrap bootstrap = XdsBootstrap.of(...);
    EndpointGroup endpointGroup = XdsEndpointGroup.of(boostrap.listenerRoot("my-envoy-service"));
    WebClient client = WebClient.of(SessionProtocol.HTTP, endpointGroup);
  • GraphQL Subscriptions over WebSocket: You can now enable GraphQL subscriptions over WebSocket for live updates to your clients. #4999 #5280

    GraphqlService
      .builder()
      .enableWebSocket(true)
      .webSocketServiceCustomizer(ws -> {
        // Customize the underlying WebSocket service.
      })
      .build();
  • Service-specific EventLoopGroup: You can now assign a different EventLoopGroup to each service for finer grained resource control. #4099 #5233

    Server
      .builder()
      .serviceWorkerGroup(globalServiceWorkerGroup)
      .route()
         .path("/user")
         // Use userServiceWorkerGroup for the user service.
         .serviceWorkerGroup(userServiceWorkerGroup)
         .build(userService)
      .route()
         .path("/api")
         // Use apiServiceWorkerGroup for the API service.
         .serviceWorkerGroup(apiServiceWorkerGroup)
         .build(apiService)
      .build();
  • Thrift Service Decorators: You can now use @Decorator annotations to conveniently apply custom decorators to Thrift services. #4230 #5356

    @Decorator(ClassDecorator.class)
    class MyHelloService implements HelloService.AsyncIface {
      @Decorator(MethodDecorator.class)
      @Override
      public void hello(String name, AsyncMethodCallback<String> handler) throws TException {
        ...
      }
    }
  • Sensitive Header Masking: You can now easily mask request and response headers using HeadersSanitizer. #5175 #5188

    HeadersSanitizer<String> headersSanitizer =
     HeadersSanitizer
       .builderForText()
       .sensitiveHeaders("Authorization", "API-Key", "Proxy-Authorization")
       ...
       .build();
    
    LogFormatter
      .builderForText()
      .requestHeadersSanitizer(headersSanitizer)
      ...
  • Custom Exception Handling for gRPC clients: You can customize how your gRPC clients respond to exceptions by implementing GrpcExceptionHandlerFunction. #5347 #5351

    GrpcClients
      .builder("https://my-grpc-server.com")
      .exceptionHandler((ctx, cause, metadata) -> {
        // Handle the exception.
        return Status.INTERNAL.withDescription("Something went wrong");
      })
  • Kubernetes Client Integration: You can now use the popular Fabric Kubernetes client seamlessly on top of Armeria when using the armeria-kubernetes module. #5167

  • WebSocket Service Fallback: You can now set up a fallback service for WebSocketService to handle both WebSocket and non-WebSocket requests on the same path with WebSocketServiceBuilder.fallbackService() #5368

    WebSocketService webSocketService =
      WebSocketService
        .builder()
        // The fallback service is used when the request
        // is not a WebSocket request.
        .fallbackService(httpService)
        .build();
    Server
      .builder()
      .service("/ws-or-http", webSocketService)
      .build();
  • WebSocket Frame Aggregation: You can now enable to aggregate WebSocket continuation frames for simplified message processing using WebSocketServiceBuilder.aggregateContinuation(). #5357

    WebSocketService
      .builder()
      // Aggregate continuation frames into a single frame.
      .aggregateContinuation(true)
      .build();
  • Active Connection Monitoring: You can monitor the number of active connections with armeria.client.connections#value{state="active"} for your clients when using ConnectionPoolListener.metricCollecting() #4277 #5288

    ConnectionPoolListener connectionPoolListener =
      ConnectionPoolListener.metricCollecting(meterRegistry);
    
    ClientFactory clientFactory =
      ClientFactory
        .builder()
        .connectionPoolListener(connectionPoolListener)
        .build();
  • Graceful Executor Shutdown: You can now gracefully terminate a custom ExecutorService in sync with the Server's shutdown procedure. #5031 #5087

    ServerListener
      .builder()
      // Shutdown the executor service when the server is stopping.
      .shutdownWhenStopping(preStopExecutorService)
      // Shutdown the executor service when the server is stopped.
      .shutdownWhenStopped(postStopExecutorService)
      .build()
  • Session Protocol in RoutingContext: You can now acquire SessionProtocol directly from RoutingContext.sessionProtocol() for enhanced routing and ExchangeType decisions.

  • Eureka Health Check Customization: You can override the default health check URL when registering a service with Eureka. #5369

    EurekaUpdatingListener
      .builder()
      // Override the default health check path provided by HealthCheckService.
      .healthCheckUrlPath("/healthcheck")
      .build();

📈 Improvements

🛠️ Bug fixes

📃 Documentation

🏚️ Deprecations

  • N/A

☢️ Breaking changes

  • N/A

⛓ Dependencies

  • Apache Curator 5.5.0 → 5.6.0
  • Brave 5.16.0 → 6.0.0
  • Brotli4j 1.12.0 → 1.15.0
  • Envoy control plane 1.0.42 (new)
  • Dropwizard 2.1.8 → 2.1.10
  • Dropwizard Metrics 4.2.21 → 4.2.24
  • GraphQL Java 20.4 → 21.3
  • Fabric Kubernetes client 6.10.0 (new)
  • gRPC Java 1.58.0 → 1.61.0
  • gRPC Kotlin 1.4.0 → 1.4.1
  • Guava 32.1.3 → 33.0.0
  • Jackson 2.15.3 → 2.16.1
  • Jetty 9.4.51 → 9.4.52, 10.0.17 → 10.0.19, 11.0.17 → 11.0.19, 12.0.5 (new)
  • JUnit 5.10.0 → 5.10.1
  • Kafka client 3.6.0 → 3.6.1
  • Kotlin 1.9.0 → 1.9.22
  • krotoDC 1.0.5 - 1.0.6
  • Logback 1.2.11 → 1.2.13, 1.3.11 → 1.3.14, 1.4.11 → 1.4.14
  • Micrometer 1.11.5 → 1.12.2
  • Micrometer Tracing 1.1.6 → 1.2.2
  • Netty 4.1.100 → 4.1.106
  • Netty io_uring 0.0.23 → 0.0.24
  • Protobuf 3.24.0 → 3.25.1
  • Reactor 3.5.11 → 3.6.2
  • Resilience4j 2.1.0 → 2.2.0
  • ScalaPB 0.11.13 → 0.11.15
  • Spring 6.0.11 → 6.1.3
  • Spring Boot 2.7.14 → 2.7.18, 3.1.2 → 3.2.2
  • Tomcat 8.5.94 → 8.5.98, 9.0.82 → 9.0.85, 10.1.15 → 10.1.18

🙇 Thank you