1.29.0 release notes

12th June 2024

🌟 New features

  • Armeria HTTP/JSON to GRPC transcoding service now supports Custom methods. #5613

    rpc Watch(WatchRequest) returns (WatchResponse) {
      option (google.api.http) = {
        post: "/v1:watch" // 👈👈👈
        body: "*"
      };
    }
  • You can now specify when to remove multipart temporary files using MultipartRemovalStrategy. #5652 #5653

    Server
      .builder()
      .multipartRemovalStrategy(
        MultipartRemovalStrategy.ON_RESPONSE_COMPLETION)
      ...
  • A ClientConnectionTimings now includes the time spent on the TLS handshake. #3647 #5647

    ClientConnectionTimings timings = ...
    assert timings.tlsHandshakeDurationNanos() > 0;
  • You can now configure TlsEngineType using ClientFactoryBuilder or ServerBuilder. #4962

    ClientFactory
      .builder()
      .tlsEngineType(TlsEngineType.OPENSSL) // 👈👈👈
      .build();
  • You can now easily find both dynamic and static decorators that handle a request via ServiceRequestContext.findService(). #5670

    ServerBuilder sb = ...
    sb.decorator(CorsService.builderForAnyOrigin().newDecorator());
    ...
    ServiceRequestContext ctx = ...
    CorsService corsService = ctx.findService(CorsService.class);
    assert corsService.config().isAnyOriginSupported();
  • You can now use the marshaller specified by gRPC MethodDescriptor by setting GrpcClientBuilder.useMethodMarshaller() and GrpcServiceBuilder.useMethodMarshaller(). #5103 #5630

    GrpcClientBuilder builder = ...
    builder.useMethodMarshaller(true); // 👈👈👈
    
    GrpcServiceBuilder builder = ...
    builder.useMethodMarshaller(true); // 👈👈👈
  • You can now programmatically retrieve the server side metrics via ServerMetrics. #4992 #5627

    ServerMetrics metrics = serverConfig.serverMetrics();
    metrics.activeConnections();
    metrics.pendingRequests();
    metrics.activeRequests();
  • You can now use a CoroutineHttpService that runs your service in a coroutine scope. #5442 #5603

    ServerBuilder sb = ...
    sb.service(
      "/hello",
      CoroutineHttpService { ctx, req ->
        HttpResponse.of("hello world")
      })
  • You can now specify options for an HttpService via ServiceOptions. #5071 #5574

    static final ServiceOptions SERVICE_OPTIONS =
      ServiceOptions
        .builder()
        .requestTimeoutMillis(5000)
        .maxRequestLength(1024)
        .requestAutoAbortDelayMillis(1000)
        .build();
    
    HttpService httpService = new HttpService() {
      ...
      @Override
      public ServiceOptions options() {
        return SERVICE_OPTIONS;
      }
    };
    
    // Or use annotation for an annotated service.
    class MyService {
        @ServiceOption(requestTimeoutMillis = 5000, maxRequestLength = 1024)
        @Get("/hello")
        public HttpResponse hello() {
            return HttpResponse.of("Hello!");
        }
    }
  • You can now inject a custom attribute from a ServiceRequestContext to an annotated service using @Attribute annotation. #5514 #5547

    class MyAttributes {
      public static final AttributeKey<String> USERNAME =
        AttributeKey.valueOf(MyAttributes.class, "USERNAME");
    }
    
    class MyAnnotatedService {
    
      @Get("/hello")
      public HttpResponse hello(
        @Attribute(prefix = MyAttributes.class, value = "USERNAME") // 👈👈👈
        String username) { ... }
    }
  • You can now specify a graceful shutdown timeout for an HTTP/2 connection in ClientFactory. #5470 #5489

    ClientFactory
      .builder()
      .http2GracefulShutdownTimeoutMillis(1000)
      .build();
  • You can now specify an EndpointGroup when building a ClientRequestContext. #5292 #5298

    ClientRequestContext ctx =
      ClientRequestContext
        .builder(request)
        .endpointGroup(endpointGroup)
        .build();
  • You can now set a GraphQL instance directly to the GraphqlServiceBuilder. #5269

    GraphQL graphQL = new GraphQL.Builder(graphqlSchema).build();
    GraphqlServiceBuilder builder = ...
    builder.graphql(graphQL);
  • You can now specify a delay to close an HTTP/1.1 connection from the server side, allowing the client an opportunity for active closing. #4849 #5616

  • You can now configure the maximum length of a TLS client hello message that a server allows by using the -Dcom.linecorp.armeria.defaultMaxClientHelloLength=<integer> JVM option. #5747

📈 Improvements

🛠️ Bug fixes

🏚️ Deprecations

☢️ Breaking changes

⛓ Dependencies

  • Blockhound 1.0.8.RELEASE → 1.0.9.RELEASE
  • Control Plane 1.0.44 → 1.0.45
  • GraphQL Kotlin 7.0.2 → 7.1.1
  • gRPC Java 1.63.0 → 1.64.0
  • Jackson 2.17.0 → 2.17.1
  • Kotlin Coroutine 1.8.0 → 1.8.1
  • Kubernetes client 6.11.0 → 6.12.1
  • Mircometer 1.12.4 → 1.13.0
  • Netty 4.1.108.Final → 4.1.110.Final
  • Reactor 3.6.4 → 3.6.6
  • Scala2.13 2.13.13 → 2.13.14
  • Scala Collection compat 2.11.0 → 2.12.0
  • Spring 6.1.5 → 6.1.8
  • Spring Boot 3.2.4 → 3.3.0

🙇 Thank you