1.32.0 release notes

5th March 2025

🌟 New features

  • Load Balancer: You can now create a LoadBalancer using various load balancing strategies to select an element from a list of candidates. #5289 #5779
    List<Endpoint> candidates = ...;
    LoadBalancer.ofRoundRobin(candidates);
    LoadBalancer.ofWeightedRoundRobin(candidates);
    LoadBalancer.ofSticky(candidates, contextHasher);
    LoadBalancer.ofWeightedRandom(candidates);
    LoadBalancer.ofRampingUp(candidates);
  • Filter Invalid IP address: You can now reject invalid IP addresses using ClientFactoryBuilder.ipAddressFilter(). #6106 #6111
    ClientFactory
      .builder()
      .ipAddressFilter(ip -> { // 👈👈👈
        if ("1.2.3.4".equals(ip.getAddress().getHostAddress())) {
          return false;
        }
        return true;
      }).build();
  • Graceful Shutdown: You can now use GracefulShutdown to terminate unfinished requests when a server stops. #5941
    GracefulShutdown gracefulShutdown =
      GracefulShutdown
        .builder()
        .quietPeriod(Duration.ofSeconds(10))
        .timeout(Duration.ofSeconds(15))
        .toExceptionFunction((ctx, req) -> {
          return new ServerStopException();
        })
        .build();
    Server.builder()
          .gracefulShutdown(gracefulShutdown);
  • DNS Channel Strategy: You can now set datagramChannelStrategy which provides an option to create a channel per-resolution for DNS queries. #6122 #6127
    DnsAddressEndpointGroup
      .builder("foo.com")
      .port(8080)
      .datagramChannelStrategy(
        DnsNameResolverChannelStrategy.ChannelPerResolution) // 👈👈👈
      .build();
  • Map Injection for an Annotated Service: The annotated service now supports the Map<String, Object> parameter. #6058 #6072
    @Get("/dogma/repos")
    public String repos(@Param Map<String, Object> repoOptions) {...}
  • Eureka InstanceInfo: You can now retrieve a Eureka InstanceInfo from an Endpoint via InstanceInfo.instanceInfo(). #6056 #6069
    EurekaEndpointGroup eurekaEndpointGroup = ...;
    eurekaEndpointGroup.endpoints().forEach(endpoint -> {
      InstanceInfo instanceInfo = InstanceInfo.instanceInfo(endpoint); // 👈👈👈
  • Client Preprocessor: You can now use a client Preprocessor to customize certain properties. #6057
    HttpPreprocessor preprocessor = (delegate, ctx, req) -> {
      ctx.setEndpointGroup(Endpoint.of("overriding-host"));
      return delegate.execute(ctx, req);
    };
    WebClient client =
      WebClient.builder()
               .preprocessor(preprocessor) // 👈👈👈
               .build();
  • Backoff Builder: You can now easily create a Backoff using builder. #5483 #5488
    Backoff backoff =
      Backoff.builderForExponential()
             .initialDelayMillis(100)
             .maxDelayMillis(10000)
             .multiplier(2.0)
             .build();

📈 Improvements

🛠️ Bug fixes

  • A cookie is correctly overwritten when a cookie with the same name, domain, and path is set. #5870 #6126
  • CorsPolicyBuilder.build() is exposed publicly again. #6121
  • Connections do not hold references on automatically aborted requests, resulting in less memory pressure. #6108
  • CircuitBreakerRuleBuilder.onTimeoutException() and Type://RetryRuleBuilder#onTimeoutException() now work when a connection or proxy establishment is timed out. #6107
  • DNS refresh query is executed by the correct executor. #5891 #6092
  • You can now choose whether to use the json_name field option when transcoding HTTP/JSON to gRPC messages. #5890 #6082
  • Automatic-Module-Names are correctly set by replacing a dot followed by a digit with an underscore. #6075 #6076
  • Delayed tasks for gRPC requests that have already been cancelled are not executed anymore. #6066
  • You no longer see a false positive warning log when HealthCheckedEndpointGroup is closing. #6063
  • An Endpoint no longer includes attributes in .toString(). #6061
  • Fixed a bug where a trailing dot was included in the hostname used by SNI. #6044 #6046
  • Log levels for responses are now correctly mapped based on the SuccessFunction. #6042
  • Resolved the Java module conflict with the NonBlocking interface. #6037
  • Unnecessary logs aren't left from an HttpResponseWrapper. #6035
  • Requests with a Content-Length header exceeding the allowed limit can now be rejected early for improving efficiency. #5880 #6032
  • You can now sample the stacktrace of ResponseCompleteException with verboseExceptionSampler. #5972
  • The ProxyConfig now correctly respect the TTL of a DNS record. #5843 #5960
  • A recovered HttpResponse by the ServiceErrorHandler now correctly produces a response content preview. #3969 #5076

🏚️ Deprecations

☢️ Breaking changes

⛓ Dependencies

  • Apache Client 5.4.1 → 5.4.2
  • BlockHound 1.0.10.RELEASE → 1.0.11.RELEASE
  • Brave 6.0.3 → 6.1.0
  • Brotli4J 1.17.0 → 1.18.0
  • Context Propagation 1.1.1 → 1.1.2
  • ControlPlane 1.0.46 → 1.0.48
  • GraphQL Kotlin 8.2.1 → 8.3.0
  • gRPC Java 1.68.1 → 1.70.0
  • Guava 33.3.1-jre → 33.4.0-jre
  • Jackson 2.18.1 → 2.18.2
  • JSoup 1.18.1 → 1.18.3
  • Kafka 3.8.1 → 3.9.0
  • Kotlin 1.9.25 → 2.1.10
  • Kotlin Coroutine 1.9.0 → 1.10.1
  • Kubernetes Client 6.13.4 → 6.13.5
  • Logback 1.5.12 → 1.5.16
  • Micrometer 1.13.6 → 1.14.4
  • Micrometer Tracing 1.3.5 → 1.4.3
  • Netty 4.1.115.Final → 4.1.118.Final
  • Netty Incubator IO_Uring 0.0.25.Final → 0.0.26.Final
  • Prometheus 1.3.2 → 1.3.6
  • Protobuf Jackson 2.6.0 → 2.7.0
  • Reactor 3.6.11 → 3.7.3
  • Resilience4J 2.2.0 → 2.3.0
  • RxJava 3.1.9 → 3.1.10
  • Sangria 4.2.2 → 4.2.5
  • Scala213 2.13.15 → 2.13.16
  • SLF4J2 2.0.16 → 2.0.17
  • Spring6 6.2.3
  • Spring Boot 3.3.5 → 3.4.3

🙇 Thank you