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 #5653Server .builder() .multipartRemovalStrategy( MultipartRemovalStrategy.ON_RESPONSE_COMPLETION) ...- The default value is now
MultipartRemovalStrategy.ON_RESPONSE_COMPLETIONwhich removes the temporary files when the response is completed.
- The default value is now
A
ClientConnectionTimingsnow includes the time spent on the TLS handshake. #3647 #5647ClientConnectionTimings timings = ... assert timings.tlsHandshakeDurationNanos() > 0;You can now configure
TlsEngineTypeusingClientFactoryBuilderorServerBuilder. #4962ClientFactory .builder() .tlsEngineType(TlsEngineType.OPENSSL) // 👈👈👈 .build();You can now easily find both dynamic and static decorators that handle a request via
ServiceRequestContext.findService(). #5670ServerBuilder 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
MethodDescriptorby settingGrpcClientBuilder.useMethodMarshaller()andGrpcServiceBuilder.useMethodMarshaller(). #5103 #5630GrpcClientBuilder builder = ... builder.useMethodMarshaller(true); // 👈👈👈 GrpcServiceBuilder builder = ... builder.useMethodMarshaller(true); // 👈👈👈You can now programmatically retrieve the server side metrics via
ServerMetrics. #4992 #5627ServerMetrics metrics = serverConfig.serverMetrics(); metrics.activeConnections(); metrics.pendingRequests(); metrics.activeRequests();You can now use a
CoroutineHttpServicethat runs your service in a coroutine scope. #5442 #5603ServerBuilder sb = ... sb.service( "/hello", CoroutineHttpService { ctx, req -> HttpResponse.of("hello world") })You can now specify options for an
HttpServiceviaServiceOptions. #5071 #5574static 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
ServiceRequestContextto an annotated service using@Attributeannotation. #5514 #5547class 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 #5489ClientFactory .builder() .http2GracefulShutdownTimeoutMillis(1000) .build();You can now specify an
EndpointGroupwhen building aClientRequestContext. #5292 #5298ClientRequestContext ctx = ClientRequestContext .builder(request) .endpointGroup(endpointGroup) .build();You can now set a
GraphQLinstance directly to theGraphqlServiceBuilder. #5269GraphQL 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
XdsEndpointGroupnow supports Slow start mode. #5688 #5693- Priority and locality based load balancing is now available for an
XdsEndpointGroup. #5610 - You can now view connection related information in the request logs. #5730
- CORS headers are added to responses even if an exception is raised while handling a request. #5632
AnnotatedServiceis now available through a public API. #5382 #5628- The metrics for failed requests while retrying now include the cause of the failure. #5405 #5583
- The
RequestLogfrom a retrying client now includes the current attempt number. #5716 #5719 - A colon is now allowed in the path for binding a service. #4577 #5676
- Timer histogram metrics now repects user-provided
serviceLevelObjectives. #5661 ServiceErrorHandler.renderStatus()can now access the currentServiceRequestContextif available. #5634SamlSingleSignOnHandler.loginFailed()can now access theMessageContextfor error handling if available. #5401 #5622- The copied cURL command from a doc service, is now quoted correctly. #5566
🛠️ Bug fixes
- Fixed a bug where
RetryingClientgets to deadlock whenOAuth2Clientfails to obtain an access token. #5715 - Armeria client always uses HTTP/2 connection preface for
h2c, regardless of the value ofClientFactoryOptions.useHttp2Preface(). #5706 ArmeriaServerConfiguratornow properly overrides the properties set byArmeriaSettings. #5009 #5692- Armeria server now returns a 408 status if a service didn't receive the request fully and the request times out. #5579 #5680
- A
NullPointerExceptionisn't raised anymore when running Armeria with a self-signed certificate. #5669 It happened when the following conditions are all met:- DEBUG-level logging of JDK security event is enabled.
- A user has no Bouncy Castle dependency.
@Descriptionannotations at the super class or interface are now used for the parameter description. #5195 #5562- The specfied
ObjectMappertoWebClientRequestPreparation.asJson()isn't ignored anymore. #5454 #5512 GrpcExceptionHandlerFunctionis now applied to convert a gRPC cancellations. #5329 #5398- In Spring integration, the default
ClientFactoryis now gracefully closed after the server shuts down. #5742 - A connection is not reused anymore after a
WriteTimeoutExceptionis raised. #5738 ServiceRequestContextis now correctly propagated whenServerErrorHandler.onServiceException()is invoked. #5746
🏚️ Deprecations
PrometheusMeterRegistriesandPrometheusExpositionServiceare deprecated. #5698- Use the same classes in the
armeria-prometheus1module.
- Use the same classes in the
HttpResultis deprecated. UseResponseEntityinstead. #4910 #5586GraphqlConfiguratorand various setter methods for building aGraphQLinstance are deprecated.- Use
GraphqlServiceBuilder.graphql()instead. #5269
- Use
☢️ Breaking changes
- We updated Micrometer to 1.13.0 that has breaking changes in its Prometheus support. #5698
- If you want to keep the old behavior that uses Prometheus Java client 0.x,
use the
io.micrometer:micrometer-registry-prometheus-simpleclient:1.13.0module. - If you want to use Prometheus Java client 1.x, add
com.linecorp.armeria:armeria-prometheus1module. - More details can be found in the Micrometer migration guide.
- If you want to keep the old behavior that uses Prometheus Java client 0.x,
use the
AbstractEndpointSelector.updateNewEndpoints()now returns aCompletableFuture. #5752- The following builder classes now have the
SELFtype parameter. #5733
⛓ 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