1.19.0 release notes
13th September 2022
🌟 New features
You can now repeatedly aggregate an
HttpRequest
andHttpResponse
when usingHttpRequest.aggregate()
andHttpResponse.aggregate()
. If anHttpRequest
or anHttpResponse
is aggregated before, the cachedAggregatedHttpRequest
orAggregatedHttpResponse
is returned for subsequent calls. #3789 #4366HttpRequest request = ...; AggregatedHttpRequest aggregatedReq0 = request.aggregate().join(); AggregatedHttpRequest aggregatedReq1 = request.aggregate().join(); assert aggregatedReq0 == aggregatedReq1; HttpResponse response = ...; AggregatedHttpResponse aggregatedRes0 = response.aggregate().join(); AggregatedHttpResponse aggregatedRes1 = response.aggregate().join(); assert aggregatedRes0 == aggregatedRes1;
You can now customize the behavior of auto-refresh for an
AddressResolverGroup
withDnsResolverGroupBuilder
. #4400// Disable auto refresh ClientFactory .builder() .domainNameResolverCustomizer(customizer -> { customizer.enableAutoRefresh(false); // 👈👈👈 }) .build(); // Set a constant refresh timeout ClientFactory .builder() .domainNameResolverCustomizer(customizer -> { customizer.autoRefreshTimeout(Duration.ofDays(1)); // 👈👈👈 }) .build(); // Build a flexible refresh timeout depending on the hostname ClientFactory .builder() .domainNameResolverCustomizer(customizer -> { customizer.autoRefreshTimeout(hostname -> { // 👈👈👈 if (hostname.endsWith("busy.domain.com")) { // Automatically refresh the cached domain for 7 days. return Duration.ofDays(7).toMillis(); } if (hostname.endsWith("sporadic.domain.dom")) { // Don't need to refresh a sporadically used domain. return 0; } ... }); }) .build();
You can now export
RequestOnlyLog.requestCause()
andRequestLog.responseCause()
to MDC by specifyingreq.cause
andres.cause
to an appender of a Logback configuration.<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="RCEA" class="com.linecorp.armeria.common.logback.RequestContextExportingAppender"> ... <export>req.cause</export> <!-- 👈👈👈 --> <export>res.cause</export> <!-- 👈👈👈 --> ... </appender> </configuration>
You can now trace a
RequestContext
leak by specifying-Dcom.linecorp.armeria.requestContextLeakDetectionSampler=<sampler-spec>
or implementing a customFlagsProvider
. #4100 #4232public final class LeakDetectingFlagsProvider implements FlagsProvider { @Override public Sampler<? super RequestContext> requestContextLeakDetectionSampler() { // Samples all request contexts. return Sampler.always(); } }
DocService
now automatically generates a specification of annotated services for well known types. #4309 #4322- Java POJO
- Kotlin data class
- Scala case class
- Protocol Buffers'
Message
- ScalaPB's
GeneratedMessage
You can now upload files to your
GraphqlService
using GraphQL multipart requests. #3971 #4199You can now use
armeria-version-catalog
module to easily import Armeria and Armeria's direct dependencies using Gradle's version catalog. #4377// in settings.gradle dependencyResolutionManagement { versionCatalogs { create("armeriaDeps") { from("com.linecorp.armeria:armeria-version-catalog:1.19.0") } } }
📈 Improvements
CompositeException
now shows full stack traces of all nested exceptions when-Dcom.linecorp.armeria.verboseExceptions=true
is set. #4347 #4356
🛠️ Bug fixes
You can now use Armeria Spring actuator with WebFlux correctly. #4396 #4408
You no longer see
ClassCastException
when an invalid path request is received. #4405Annotated services now correctly return
204 No Content
status whenvoid
,Publisher<Void>
orCompletionStage<Void>
and@ProducesJson
are used at the same time. #4390 #4398// 200 OK status and "null" string body is returned @Get("/null-content") @ProducesJson public Publisher<Void> nullBody() { return Mono.empty(); } // 204 No Content status and no body is returned @Get("/no-content") @StatusCode(204) @ProducesJson public Publisher<Void> noBody() { return Mono.empty(); }
Armeria server no longer sends chunked encoding header with
304 Not Modified
status. #4386HTTP/2 graceful shutdown timeout is correctly set using
ClientFactory.idleTimeoutMillis()
. #4381Unframed
GrpcServices
now supportapplication/x-protobuf
andapplication/x-google-protobuf
media types. #4355 #4364You can now use a custom
JsonFormat.Printer
forProtobufResponseConverterFunction
. #4301 #4336
📃 Documentation
- You can now learn how to write a gRPC service and client with Armeria by walking through
the gRPC tutorial. #3987
- Special thanks to @freevie who volunteered for this.
🏚️ Deprecations
DnsResolverGroupBuilder.refreshBackoff()
has been deprecated in favor ofDnsResolverGroupBuilder.autoRefreshBackoff()
. #4400
☢️ Breaking changes
- The method signature of
ResponseConverterFunctionProvider.createResponseConverterFunction()
has been changed.ResponseConverterFunctionProvider
no longer takes aResponseConverterFunction
as the second parameter. UseDelegatingResponseConverterFunctionProvider
to create a newResponseConverterFunction
based on the delegatingResponseConverterFunction
.
⛓ Dependencies
- Brave 5.13.10 → 5.13.11
- Brotli4J 1.7.1 → 1.8.0
- Dropwizard Metrics 4.2.10 → 4.2.12
- gRPC-Java 1.48.0 → 1.49.0
- Jackson 2.13.3 → 2.13.4
- Micrometer 1.9.2 → 1.9.3
- Reactor 3.4.21 → 3.4.22
- Sangria 3.0.1 → 3.2.0
- Scala 3.1.3 → 3.2.0
- Spring Boot 2.7.2 → 2.7.3