You're seeing the release note of an old version. Check out the latest release note.
v0.96.0
November 23, 2019
🌟 New features
-
The type signature of clients and services has been greatly simplified. Note that this involves various breaking changes unfortunately. See the 'Breaking changes' section for the details. #2239 #2254
// Before:
public class FooHttpService implements Service<HttpRequest, HttpResponse> { ... }
public class FooRpcService implements Service<RpcRequest, RpcResponse> { ... }
public class FooHttpClient implements Client<HttpRequest, HttpResponse> { ... }
public class FooRpcClient implements Client<RpcRequest, RpcResponse> { ... }
Service<HttpRequest, HttpResponse> foo(Service<HttpRequest, HttpResponse> bar) { ... }
Function<Service<HttpRequest, HttpResponse>,
? extends Service<HttpRequest, HttpResponse>> httpServiceDecorator;
Function<Service<RpcRequest, RpcResponse>,
? extends Service<RpcRequest, RpcResponse>> rpcServiceDecorator;
Function<Client<HttpRequest, HttpResponse>,
? extends Client<HttpRequest, HttpResponse>> httpClientDecorator;
Function<Client<RpcRequest, RpcResponse>,
? extends Client<RpcRequest, RpcResponse>> rpcClientDecorator;
// After:
public class FooHttpService implements HttpService { ... }
public class FooRpcService implements RpcService { ... }
public class FooHttpClient implements HttpClient { ... }
public class FooRpcClient implements RpcClient { ... }
HttpService foo(HttpService bar) { ... }
Function<? super HttpService, ? extends HttpService> httpServiceDecorator;
Function<? super RpcService, ? extends RpcService> rpcServiceDecorator;
Function<? super HttpClient, ? extends HttpClient> httpClientDecorator;
Function<? super RpcClient, ? extends RpcClient> rpcClientDecorator; -
You can now specify service-level settings for annotated services, just like other service types. #2180 #2222
Server server =
Server.builder()
.annotatedService().pathPrefix("/api")
.requestTimeoutMillis(5000)
.exceptionHandler((ctx, req, cause) -> ...)
.build(new Object() { ... }))
.build(); -
RequestContextnow has its ownRequestId, which is a 64-bit random integer by default. #2001 #2174 #2203 #2224Server server =
Server.builder()
.service("/", (ctx, req) -> {
return HttpResponse.of("Request ID: %s", ctx.id().text());
})
.build(); -
You can now add a cause to an
HttpStatusException. #2253HttpService service = (ctx, req) -> {
try (FileInputStream in = new FileInputStream(...)) {
...
} catch (FileNotFoundException e) {
throw HttpStatusException.of(HttpStatus.NOT_FOUND, e);
}
}; -
Armeria server now always has a fallback service which is matched when no routes match a request. #1625 #2255
- As a result, a route decorator bound at
prefix:/can intercept any requests, even the requests not handled by any services:// CorsService will intercept any requests,
// even the ones not handled by any services.
Server server =
Server.builder()
.service("/foo", fooService)
.service("/bar", barService)
.routeDecorator().pathPrefix("/")
.build(CorsService.newDecorator(...))
.build();
- As a result, a route decorator bound at
-
You can now determine the log level of
LoggingClientandLoggingServicedynamically. #2250 #2258LoggingClient.builder()
.requestLogLevel(log -> ...)
.responseLogLevel(log -> {
if (log.responseCause() == null ||
log.responseCause() instanceof HarmlessException) {
return LogLevel.INFO;
} else {
return LogLevel.WARN;
}
}); -
ClientFactoryOptionshas been added to allow programmatic access to theClientFactorysettings. #2230ClientFactory factory = ...;
boolean pipelining = factory.options().useHttp1Pipelining(); -
You can now disable Armeria's Netty-based asynchronous DNS resolver by specifying
-Dcom.linecorp.armeria.useJdkDnsResolver=trueJVM option. Use it only when the default resolver does not work. #2261
💪 Improvements
-
Armeria client does not block a request anymore when DNS resolution takes long time. #2017 #2217 #2231
-
You do not have to prepend
none+prefix to non-RPC URIs anymore. #2219 #2241// Before:
Clients.of("none+https://...", ...);
// After:
Clients.of("https://...", ...);- The behavior of
Scheme.parse()andtryParse()has been improved in the same manner:// Scheme.parse() now uses SerializationFormat.NONE automatically:
assert Scheme.parse("http") == Scheme.parse("none+http");
- The behavior of
🛠️ Bug fixes
- Armeria Spring auto-configuration now works correctly even when only
GrpcServiceRegistrationBeans are given. #2234 RequestContextis not pushed more often than necessary anymore when notifyingRequestLogListeners. #2227DynamicEndpointGroupnow handles the case where an endpoint address does not change but only a weight. #2240HttpStatusExceptionnow respectsFlags.verboseExceptionSampler(). #2253AccessLogWriterdoes not fail with aClassCastExceptionanymore. #2259- Fixed a bug where a service receives an
OPTIONSrequest even if the service did not opt-in forOPTIONSmethod. #2263
🏚️ Deprecations
ClientFactory.DEFAULThas been deprecated in favor ofClientFactory.ofDefault().- The getters for host-level settings in
ServerConfighave been deprecated. #2244 #2246// Before:
HttpService service = (ctx, req) -> {
return HttpResponse.of("maxRequestLength: %d",
ctx.server().maxRequestLength());
};
// After:
HttpService service = (ctx, req) -> {
return HttpResponse.of("maxRequestLength: %d",
ctx.virtualHost().maxRequestLength());
}; - Continuing the migration to static
builder()factory methods, the following classes have switched from constructors to staticbuilder()methods: #2221ClientCacheControlClientConnectionTimingsClientDecorationClientFactoryClientOptionsClientRequestContextEndpointInfoFieldInfoHttpClientLoggingClientLoggingServiceRequestContextCurrentTraceContextRetrofitMeterIdPrefixFunctionServerCacheControlServiceRequestContext
☢️ Breaking changes
-
The signatures of
RequestContext.newDerivedContext()have been changed so they always requireRequestId,HttpRequestandRpcRequestfor less ambiguity. #2209 #2224 -
Scheme.parse()andtryParse()do not fail anymore even if the scheme does not start withnone+: #2219 #2241// Scheme.parse() now uses SerializationFormat.NONE automatically:
assert Scheme.parse("http") == Scheme.parse("none+http"); -
ClientBuilderParams.uri()does not return a URI withnone+prefix anymore. #2219 #2241 -
HttpClientinterface has been renamed toWebClient.HttpClientis now a different interface that extendsClient<HttpRequest, HttpResponse>. #2254// Doesn't work:
HttpClient client = HttpClient.of("https://www.google.com/");
// Good:
WebClient client = WebClient.of("https://www.google.com/"); -
Services must implement
HttpServiceorRpcServiceand clients must implementHttpClientorRpcClient: #2239 #2254// Before:
public class FooHttpService implements Service<HttpRequest, HttpResponse> { ... }
public class FooRpcService implements Service<RpcRequest, RpcResponse> { ... }
public class FooHttpClient implements Client<HttpRequest, HttpResponse> { ... }
public class FooRpcClient implements Client<RpcRequest, RpcResponse> { ... }
// After:
public class FooHttpService implements HttpService { ... }
public class FooRpcService implements RpcService { ... }
public class FooHttpClient implements HttpClient { ... }
public class FooRpcClient implements RpcClient { ... }-
You'll have to change any
Service<...>andClient<...>usages in your code intoHttpService,RpcService,HttpClientorRpcClient, unless you intended to express both HTTP- and RPC- level types.// Before:
Service<HttpRequest, HttpResponse> foo(Service<HttpRequest, HttpResponse> bar) { ... }
// After:
HttpService foo(HttpService bar) { ... } -
Similarly, you must use
SimpleDecoratingHttpClientorSimpleDecoratingRpcClientinstead ofSimpleDecoratingClient, andSimpleDecoratingHttpServiceorSimpleDecoratingRpcServiceinstead ofSimpleDecoratingService.// Does not work:
class MyDecoratorService extends SimpleDecoratingService<HttpRequest, HttpResponse> {
MyDecoratorService(Service<HttpRequest, HttpResponse> delegate) {
super(delegate);
}
...
}
// Good:
class MyDecoratorService extends SimpleDecoratingHttpService {
// Note the constructor parameter change.
MyDecoratorService(HttpService delegate) {
super(delegate);
}
...
} -
If you implemented your decorator without extending the
SimpleDecorating{Http,Rpc}ServiceorSimpleDecorating{Http,Rpc}Client, then you must make sure that it implementsHttpService,RpcRequest,HttpClientorRpcClient.// Does not work:
class MyDecoratorService implements Service<HttpRequest, HttpResponse> {
final Service<HttpRequest, HttpResponse> delegate;
MyDecoratorService(Service<HttpRequest, HttpResponse> delegate) {
this.delegate = delegate;
}
...
}
// Good:
class MyDecoratorService implements HttpService {
// Note the type change.
final HttpService delegate;
// Note the constructor parameter change.
MyDecoratorService(HttpService delegate) {
this.delegate = delegate;
}
...
}
-
-
Service.decorate()has been pushed down toHttpServiceandRpcService: #2239 #2254// Does not work:
Service<HttpRequest, HttpResponse> service = (ctx, req) -> ...;
service.decorate(myDecorator); // No such method
// Good:
HttpService service (ctx, req) -> ...;
service.decorate(myDecorator); // OK! -
The type parameters of decorator
Functions have been changed. #2239 #2254// Before:
Function<Service<HttpRequest, HttpResponse>,
? extends Service<HttpRequest, HttpResponse>> httpServiceDecorator;
Function<Service<RpcRequest, RpcResponse>,
? extends Service<RpcRequest, RpcResponse>> rpcServiceDecorator;
Function<Client<HttpRequest, HttpResponse>,
? extends Client<HttpRequest, HttpResponse>> httpClientDecorator;
Function<Client<RpcRequest, RpcResponse>,
? extends Client<RpcRequest, RpcResponse>> rpcClientDecorator;
// After:
Function<? super HttpService, ? extends HttpService> httpServiceDecorator;
Function<? super RpcService, ? extends RpcService> rpcServiceDecorator;
Function<? super HttpClient, ? extends HttpClient> httpClientDecorator;
Function<? super RpcClient, ? extends RpcClient> rpcClientDecorator; -
Some types, which could be used at both HTTP- and RPC- level, have been split into two different types. For example:
DecoratingClientFunctionhas been split intoDecoratingHttpClientFunctionandDecoratingRpcClientFunction.DecoratingServiceFunctionhas been split intoDecoratingHttpServiceFunctionandDecoratingRpcServiceFunction.LoggingClienthas been split intoLoggingClientandLoggingRpcClient.ServiceWithRouteshas been split intoHttpServiceWithRoutesandRpcServiceWithRoutes.TransientServicehas been split intoTransientHttpServiceandTransientRpcService.
-
The following services are now provided only at HTTP-level. Please let us know if you need an RPC-level version of them.
LoggingServiceMetricCollectingServiceStructuredLoggingServiceKafkaStructuredLoggingService
⛓ Dependencies
- Brave 5.8.0 -> 5.9.0
- gRPC 1.24.1 -> 1.25.0
- Jackson 2.10.0 -> 2.10.1
- Micrometer 1.3.0 -> 1.3.1
- Netty TCNative BoringSSL 2.0.26 -> 2.0.27
- Protobuf 3.9.1 -> 3.10.0
- RxJava 2.2.13 -> 2.2.14
- SLF4J 1.7.28 -> 1.7.29
- Spring Boot 2.1.9 -> 2.1.10
🙇 Thank you
This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:

















