Skip to main content
info

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

v1.9.0

June 23, 2021

🌟 New features

  • A new module armeria-graphql integrates with GraphQL Java to let you serve GraphQL requests. #3318 #3373

    ServerBuilder sb = ...;
    sb.service("/graphql",
    GraphqlService.builder()
    .schemaFile(schemaFiles)
    .runtimeWiring(w -> ...)
    .configureDataLoaderRegistry(registry -> ...)
    ...
    .build());
    tip

    armeria-graphql is currently experimental. We're looking forward to your feedback.

  • You can now transform the objects of HttpRequest and HttpResponse using a function. #3606 #3624

    HttpRequest req1 = ...;
    HttpRequest req2 =
    req1.mapHeaders(headers -> headers.toBuilder()
    .add("TraceId", "1")
    .build())
    .mapData(data -> HttpData.ofUtf8(data.toStringUtf8() + '\n'))
    .mapTrailers(trailers -> trailers.toBuilder()
    .add("trailer-key", "val")
    .build())

    HttpResponse res1 = ...;
    HttpResponse res2 =
    res1.mapHeaders(headers -> headers.toBuilder()
    .add("SessionId", "123")
    .build())
    .mapInformational(informational -> {
    return informational.withMutations(builder -> {
    builder.add(HttpHeaderNames.USER_AGENT, "Armeria");
    });
    })
    .mapData(data -> HttpData.ofUtf8(data.toStringUtf8()
    .replaceAll("\n", "<br/>")))
    .mapTrailers(trailers -> trailers.toBuilder()
    .add("result", "0")
    .build());
  • You can now collect the all elements of a StreamMessage with StreamMessage.collect(). #3603

    StreamMessage<Integer> stream = StreamMessage.of(1, 2, 3);
    CompletableFuture<List<Integer>> collected = stream.collect();
    assert collected.join().equals(List.of(1, 2, 3));
  • You can exclude a Route from another Route when configuring a service. #2737 #3562

    ServerBuilder sb = ...;
    sb.route()
    .pathPrefix("/api")
    .exclude("prefix:/api/admin")
    .exclude(Route.builder()
    .pathPrefix("/api/v1")
    .consumes(MediaType.JSON)
    .build())
    .build(apiService);

    sb.routeDecorator()
    .pathPrefix("/api")
    .exclude("prefix:/api/admin")
    .build(MetricCollectingService.newDecorator());
  • You can now update the service bindings without restarting a Server using Server.reconfigure(). #3041 #3362 Note that there are some limitations on the Server reconfiguration. Please check out #3041 for details.

    Server server = ...;
    server.reconfigure(sb -> {
    sb.service("/dynamic", new LazyService());
    });
  • You can now use RequestOptions to configure various options at request level. #3593

    HttpRequest req = ...;
    WebClient client = ...;
    RequestOptions options =
    RequestOptions.builder()
    .responseTimeout(Duration.ofSeconds(20))
    .writeTimeout(Duration.ofSeconds(5))
    .maxResponseLength(2048)
    .attr(foo, "bar")
    .build();
    // Specify RequestOptions when sending a request.
    client.execute(req, options);

    // You can also specify the options when building a request
    // using WebClientRequestPreparation.
    client.prepare()
    .get("/some/path")
    .responseTimeout(Duration.ofSeconds(20))
    .writeTimeout(Duration.ofSeconds(5))
    .maxResponseLength(2048)
    .attr(foo, "bar")
    .execute();
  • You can now fluently build a BlockingTaskExecutor using BlockingTaskExecutorBuilder. #3315 #3389

    BlockingTaskExecutor.builder()
    .daemon(true)
    .numThreads(500)
    .threadNamePrefix("my-blocking-task-executor")
    .build();
  • You can now easily get a boolean value from QueryParams and HttpHeaders. #3600

    HttpHeaders headers = HttpHeaders.of("checked", "true", "valid", "1");
    assert headers.getBoolean("checked");
    assert headers.getBoolean("valid");
    QueryParams params = QueryParams.of("checked", "false", "valid", "0");
    assert !params.getBoolean("checked");
    assert !params.getBoolean("valid");
  • You can now conveniently configure a loopback port with ServerBuilder.localPort(). #3599 #3601

    Server.builder()
    .localPort(8080)
    .localPort(9090, SessionProtocol.HTTP, SessionProtocol.HTTPS);
  • All Jackson modules in the class loader are registered automatically by default via Jackson's built-in SPI mechanism for your convenience.

  • TCP user timeout option is now enabled by default when an idle timeout is enabled. #3509

    • TCP_KEEPIDLE and TCP_KEEPINTVL options are enabled when a PING interval is greater than 0.
  • You can now get the last value of a header or a query parameter using HttpHeaders.getLast() and QueryParams.getLast(). #3438 #3568

    HttpHeaders headers =
    HttpHeaders.builder()
    .add(HttpHeaderNames.X_FORWARDED_FOR,
    List.of("203.0.113.195", "150.172.238.178"))
    .build();
    assert headers.getLast(HttpHeaderNames.X_FORWARDED_FOR)
    .equals("150.172.238.178");

    QueryParams params =
    QueryParams.builder()
    .add("items", List.of("1", "2", "3"))
    .build();
    assert params.getLastInt("items").equals(3);
  • ContentTooLargeException now provides you the following 3 properties about why the exception was raised. #3520, #3616

    • The maximum allowed content length
    • The content length specified in the content-length header
    • The number of bytes transferred so far
  • You can now convert a Multipart into an HttpResponse. #3642

  • You can now warm up an EventLoopGroup using EventLoopGroups.warmUp(). #3363 #3610

  • You can now figure out the number of connections managed by a ClientFactory with ClientFactory.numConnections(). #3596 #3613

  • You can now specify the number of event loop threads and blocking task threads more conveniently. #3597 #3602

    Server.builder()
    .workerGroup(3)
    .blockingTaskExecutor(10)
    ...
    .build();

    ClientFactory.builder()
    .workerGroup(3)
    .build();
  • You can now clear the mocking state of a MockWebServerExtension using MockWebServerExtension.reset(). #3629

📈 Improvements

🛠️ Bug fixes

⛓ Dependencies

  • Bouncy Castle 1.68 → 1.69
  • Dropwizard 2.0.21 → 2.0.23
  • Dropwizard Metrics 4.1.21 → 4.2.2
  • Eureka 1.10.13 → 1.10.15
  • gRPC-Java 1.37.0 → 1.38.1
  • gRPC-Kotlin 1.0.0 → 1.1.0
  • JBoss logging 3.4.1 → 3.4.2
  • Jetty 9.4.39 → 9.4.42
  • Kotlin 1.5.0 → 1.5.10
  • Kotlin Coroutines 1.4.3 → 1.5.0
  • Netty 4.1.63 → 4.1.65
  • netty-tcnative-boringssl-static 2.0.38 → 2.0.39
  • Prometheus 0.10.0 → 0.11.0
  • Reactor 3.4.6 → 3.4.7
  • RESTEasy 4.6.0 → 4.6.1
  • RxJava 3.0.12 → 3.0.13
  • Scala
    • 2.12.13 → 2.12.14
    • 2.13.5 → 2.13.6
  • ScalaPB runtime 0.11.2 → 0.11.3
  • ScalaPB json4s 0.11.0 → 0.11.1
  • SLF4J 1.7.30 → 1.7.31
  • Spring 5.3.7 → 5.3.8
  • Spring Boot 2.4.5 → 2.5.1
  • Tomcat
    • 8.5.64 → 8.5.68
    • 9.0.44 → 9.0.46
  • Thrift 0.14.1 → 0.14.2

🙇 Thank you

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

@minwoox@KarboniteKream@ikhoon@heowc@anuraaga@serajin00@kojilin@jrhee17@hexoul@trustin@max904-github@kezhenxu94@amitvc@hyangtack@nirvanarsc@mauhiz@haithamgabr@JunoJunho

Like Armeria?
Star us ⭐️

×