Skip to main content
info

You're seeing the release note of an old version. Check out the latest release note.

v1.10.0

August 19, 2021

🌟 New features

  • A new module armeria-sangria that integrates with Sangria GraphQL is introduced to let you serve a GraphQL request in Scala. #3703 #3704

    val schema: Schema[CharacterRepo, Unit] = Schema(Query)
    Server.builder()
    .service("/graphql",
    SangriaGraphqlService.builder(schema, new CharacterRepo)
    .enableTracing(true)
    .maxQueryDepth(10)
    .build())
  • You can now configure WebClient to automatically follow redirections. #2489 #3641

    WebClient.builder()
    .followRedirects()
    .build();
    // Customize redirection policy
    RedirectConfig config = RedirectConfig.builder()
    .maxRedirects(10)
    .allownDomains("foo.com", "bar.com")
    .build();
    WebClient.builder("https://example.com")
    .followRedirects(config)
    .build();
  • You can now recover a failed HttpResponse with a fallback HttpResponse. It would be useful for handling an error of HttpResponse in a decorator. #3674

    HttpResponse response =
    HttpResponse.ofFailure(new IllegalStateException("Oops..."));
    // The failed HttpResponse will be recovered by the fallback function.
    HttpResponse recovered =
    response.recover(cause -> HttpResponse.of("Fallback"));
    assert recovered.aggregate().join().contentUtf8().equals("Fallback");
  • You can now resume a failed StreamMessage with a fallback StreamMessage. #3674

    DefaultStreamMessage<Integer> stream = new DefaultStreamMessage<>();
    stream.write(1);
    stream.write(2);
    stream.close(new IllegalStateException("Oops..."));
    StreamMessage<Integer> resumed =
    stream.recoverAndResume(cause -> StreamMessage.of(3, 4));
    assert resumed.collect().join().equals(List.of(1, 2, 3, 4));
  • You can now transform an error of StreamMessage into another using StreamMessage.mapError(). #3668

    StreamMessage stream =
    StreamMessage.aborted(ClosedStreamException.get());
    StreamMessage transformed = stream.mapError(ex -> {
    if (ex instanceof ClosedStreamException) {
    return new IllegalStateException(ex);
    } else {
    return ex;
    }
    });
  • You can now automatically encode an object into JSON for a response payload using HttpResponse.ofJson(). #3662

    MyObject myObject = ...;
    HttpResponse.ofJson(myObject);
    MyError myError = ...;
    HttpResponse.ofJson(HttpStatus.INTERNAL_SERVER_ERROR, myError);
  • You can now fluently inject io.grpc.ServerInterceptors using GrpcServiceBuilder.intercept().

    GrpcService.builder()
    .addService(myService)
    .intercept(myInterceptror)
    .build();
  • You can now easily add Accept headers with RequestHeadersBuilder.accept(). #3704

    RequestHeaders.builder()
    .accept(MediaType.JSON)
    .accept(MediaType.PLAIN_TEXT);
  • You can now initiate graceful connection shutdown using ServiceRequestContext.initiateConnectionShutdown(). #3516 #3715

  • You can now specify the default ObjectMapper using JacksonObjectMapperProvider. #3728

    public class MyObjectMapperProvider
    implements JacksonObjectMapperProvider {

    @Override
    public ObjectMapper newObjectMapper() {
    return JsonMapper
    .builder()
    .addModules(new KotlinModule())
    .enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
    .build();
    }
    }
  • You can now serve application/grpc-web+proto and application/grpc-web-text+proto protocols using AbstractUnaryGrpcService. #3638 #3716

  • gRPC trailers are available in the RequestContext for unary gRPC server and client. #3724 #3739

    UnaryGrpcClient client = ...;
    try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
    client.execute("/com.example.MyService/UnaryCall", request);
    ClientRequestContext ctx = captor.get();
    HttpHeaders trailers = GrpcWebTrailers.get(ctx); // 👈👈👈
    }
  • You can now compress and decompress content with Brotli when using EncodingService, DecodingService and DecodingClient. #3544 #3686

  • You can now create an HttpResponseException with a cause. #3674

  • You can now easily capture ServiceRequestContexts using ServerExtension in tests. #3648

  • You can now suppress the inconsistent Netty version warning by specifying -Dcom.linecorp.armeria.warnNettyVersions=false. #3572 #3766

📃 Documentation

  • You can now learn how to write a REST service with Armeria by walking through the brand-new tutorials. #3420
    • Special thanks to @freevie who volunteered for this.

📈 Improvements

🛠️ Bug fixes

🏚️ Deprecations

☢️ Breaking changes

  • ExceptionHandler now returns HttpResponse instead of AggregatedHttpResponse. #3674

    // Before:
    ExceptionHandler handler = (ctx, cause) -> {
    if (cause instanceof IllegalArgumentException) {
    return AggregatedHttpResponse.of(HttpStatus.BAD_REQUEST);
    }
    return null;
    }

    // After:
    ExceptionHandler handler = (ctx, cause) -> {
    if (cause instanceof IllegalArgumentException) {
    return HttpResponse.of(HttpStatus.BAD_REQUEST); // 👈👈👈
    }
    return null;
    }
  • RequestContext is added as the first parameter of GrpcStatusFunction. #3692 #3693

    // Before:
    GrpcService.builder()
    .exceptionMapping((throwable, metadata) -> {
    if (throwable instanceof IllegalArgumentException) {
    return Status.INVALID_ARGUMENT;
    }
    return null;
    });

    // After:
    GrpcService.builder()
    .exceptionMapping((ctx, throwable, metadata) -> { // 👈👈👈
    if (throwable instanceof IllegalArgumentException) {
    return Status.INVALID_ARGUMENT;
    }
    return null;
    });
  • JacksonModuleProvider has been removed in favor of JacksonObjectMapperProvider.

  • ResponseConverterFunctionProvider.createResponseConverterFunction(Type,ResponseConverterFunction,ExceptionHandlerFunction) has been removed in favor of ResponseConverterFunctionProvider.createResponseConverterFunction()?full . #3674

  • OAuth2AuthorizationGrant.withAuthorization() has been removed. #3618

⛓ Dependencies

  • Curator 5.1.0 → 5.2.0
  • Dropwizard 2.0.23 → 2.0.24
  • Dropwizard Metrics 4.2.2 → 4.2.3
  • Jackson 2.12.3 → 2.12.4
  • Jetty 9.4.42 → 9.4.23
  • GraphQL-Java 16.2 → 17.1
  • gRPC-Java 1.38.1 → 1.40.0
  • Kotlin 1.5.10 → 1.5.21
  • kotlinx-coroutines-core 1.5.0 → 1.5.1
  • Logback 1.2.3 → 1.2.5
  • Micrometer 1.7.1 → 1.7.2
  • Netty 4.1.65 → 4.1.66
  • netty-tcnative-boringssl-static 2.0.39 → 2.0.40
  • netty-transport-native-io_uring 0.0.5 → 0.0.8
  • java-jwt 3.16.0 → 3.18.1
  • protobuf-java 3.12.0 → 3.17.2
  • Reactor 3.4.7 → 3.4.9
  • RESTeasy 4.6.1 → 4.7.1
  • RxJava 3.0.13 → 3.1.0
  • scala-collection-compat 2.4.4 → 2.5.0
  • ScalaPB 0.11.4 → 0.11.5
  • ScalaPB json4s 0.11.1 → 0.12.0
  • SLF4J 1.7.31 → 1.7.32
  • Spring 5.3.8 → 5.3.9
  • Spring Boot 2.5.2 → 2.5.3
  • ZooKeeper 3.6.2 → 3.6.3

🙇 Thank you

This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:

@mauhiz@anuraaga@jupiny@ghkim3221@heka1024@kezhenxu94@ks-yim@alexc-db@karellen-kim@imasahiro@kojilin@sfc-gh-pbennes@ikhoon@jrhee17@tobias-@freevie@trustin@icepeppermint@heowc@minwoox@mynameisjwlee

Like Armeria?
Star us ⭐️

×