0.99.5 release notes

14th May 2020

🌟 New features

  • Added Server.blockUntilShutdown() which lets you wait for a Server to close. #2659

    Server server = Server.builder()...build();
    server.start().join();
    // Returns when server.close() or closeAsync() is called.
    server.blockUntilShutdown();
  • Added SystemInfo.defaultNonLoopbackIpV4Address() which returns the sensible IPv4 address of the current machine. #2679

  • You can now specify authorization credentials conveniently when building a client: #2680

    WebClient.builder("https://example.com/api")
             // Basic
             .auth(BasicToken.of("admin", "sesame"))
             // OAuth 1a
             .auth(OAuth1aToken.of(...))
             // OAuth 2
             .auth(OAuth2Token.of("token-0123456789abcdef"))
             .build();
  • New RetryRule and RetryRuleWithContent API let you define a complex retry policy conveniently. #1634 #2661 #2709

    Backoff myBackoff = Backoff.exponential(1000, 60000)
                               .withJitter(0.3)
                               .withMaxAttempts(10);
    RetryRule retryRule =
        RetryRule.of(RetryRule.builder()
                              .onUnProcessed()
                              .thenBackoff(myBackoff),
                     RetryRule.builder()
                              .onException(ResponseTimeoutException.class)
                              .thenBackoff(),
                     RetryRule.builder()
                              .onStatus(HttpStatus.TOO_MANY_REQUESTS)
                              .thenNoRetry())
    
    RetryingClient.newDecorator(retryRule);
  • CircuitBreakerListener now has a new event listener method onInitialized(), which is invoked when a circuit is initialized. By default, it simply delegates to onStateChanged(). #2675

  • You can now register your server to or retrieve the Endpoints from a Eureka registry server, which gives nice integration with Spring Cloud. #707 #2701

    • Use EurekaUpdatingListener for Servers:

      Server server = Server.builder()...build();
      server.addListener(EurekaUpdatingListener.of("https://my-eureka-registry.com/"));
      // Automatically registers when the Server starts.
      server.start().join();
      // Automatically deregisters when the Server stops.
      server.stop().join();
    • Use EurekaEndpointGroup for clients:

      // Periodically retrieves the endpoint list from the registry.
      EndpointGroup group = EurekaEndpointGroup.of("https://my-eureka-registry/");
      group.whenReady().join();
      
      // Sends a request to the endpoints, spreading the load w/ weighted round-robin.
      WebClient client = WebClient.of(SessionProtocol.HTTP, group);
      System.err.println(client.get("/some-resource")
                               .aggregate().join()
                               .contentUtf8());
  • You can now use the gRPC client stubs generated by grpc-kotlin #2662 #2669

  • Added a new Thrift serialization format TTEXT_NAMED_ENUM. It is a variant of TTEXT that serializes an enum as a string instead of an integer. This can be useful when you need to serialize a TBase object into a human-readable JSON. #2706

    ObjectMapper mapper = new ObjectMapper()
    mapper.registerModule(new ThriftJacksonModule(/* useNamedEnum */ true));
    String json = mapper.writeValueAsString(myTBaseStruct);
  • Added two Spring Boot annotations that inject the current local Armeria port(s) - @LocalArmeriaPort and @LocalArmeriaPorts, which is useful when you bind at an ephemeral port or more than one port: #2561 #2684

    @Configuration
    class MyConfiguration {
        @LocalArmeriaPort(SessionProtocol.HTTP)
        int httpPort;
        @LocalArmeriaPort(SessionProtocol.HTTPS)
        int httpsPort;
        @LocalArmeriaPorts
        List<Integer> ports;
    }

📈 Improvements

  • ZooKeeperUpdatingListener now updates the registry with both host name and IP address by default, so that the client does not have to do a DNS lookup. #2674 #2679
    • The IP address is retrieved from defaultNonLoopbackIpV4Address() of SystemInfo.

🛠️ Bug fixes

  • Fixed a bug where more than one thread can consume from a streaming message. #2687 #2683
  • You will not get a NullPointerException anymore when starting a JettyService with DEBUG level logging enabled. #2688 #2691
  • PING interval now works as expected even if idle timeout is disabled. #2702
  • A connection is now closed immediately when PING fails, rather than waiting for idle timeout. #2699
  • A request sent to an HTTP/1 server behind an HTTP CONNECT proxy server is now handled properly. #2705 #2698
  • An event loop does not block for too long anymore when:
    • Thrift TEXT protocol loads a class. #2692
    • A client makes a lot of requests for a short period. #2700

☢️ Breaking changes

⛓ Dependencies

  • Dropwizard 2.0.5 → 2.0.9
  • Dropwizard Metrics 4.1.5 → 4.1.7, 3.2.5 → 3.2.6
  • gRPC 1.28.0 → 1.29.0
  • Jackson 2.10.3 → 2.11.0
  • java-jwt 3.10.2 → 3.10.3
  • Jetty 9.4.27 → 9.4.28
  • Micrometer 1.3.6 → 1.5.1
  • Netty 4.1.48 → 4.1.50
  • Prometheus simpleclient 0.8.1 → 0.9.0
  • protobuf-jackson 1.0.0 → 1.1.0
  • Reactor 3.3.4 → 3.3.5
  • RxJava 3.0.1 → 3.0.3
  • snappy-java 1.1.7 → 1.1.7.5
  • Spring Boot 2.2.6 → 2.2.7
  • Tomcat 9.0.33 → 9.0.35, 8.5.53 → 8.5.55
  • ZooKeeper 3.5.7 → 3.5.8
  • Shaded dependencies
    • Bouncy Castle 1.64 → 1.65
    • Caffeine 2.8.1 → 2.8.2
    • Guava 28.2 → 29.0
  • Example dependencies
    • Kotlin 1.3.71 → 1.3.72
    • Kotlin Coroutines 1.3.4 → 1.3.6

🙇 Thank you