Skip to content

default-channel properties are not applied to explicitly defined named channels; the #345 fix was never released and regressed in the Spring Boot module move #423

Description

@ParkerHarrelsonFBG

Summary

spring.grpc.client.default-channel.* properties are silently ignored for channels that are explicitly defined under spring.grpc.client.channels.<name>.*. This was reported and fixed in #345, but the fix was never published in any release — and the behavior has since regressed again in the code's new home in Spring Boot 4.1's spring-boot-grpc-client module. Filing this to (a) surface that the #345 fix never shipped, and (b) ask that its semantics be restored in whichever tracker is the right home (happy to re-file on spring-projects/spring-boot if that's preferred).

Current behavior (spring-grpc 1.0.3, Spring Boot 4.0.x)

GrpcClientProperties.getChannel(String name) returns an explicitly defined named channel as-is; default-channel is only used as a template for channel names that have no entry under channels:

ChannelConfig channel = this.channels.get(name);
if (channel != null) {
    return channel;                       // defined channel returned as-is — no merge
}
channel = this.defaultChannel.copy();     // default is a template ONLY for undefined names

All consumers (ClientPropertiesChannelBuilderCustomizer for keep-alive/idle/default-deadline, NamedChannelCredentialsProvider for negotiation-type) resolve config through this method, so a configuration like the following silently drops every default-channel value for the named channel:

spring:
  grpc:
    client:
      default-channel:
        negotiation-type: TLS
        keep-alive-time: 15m
        keep-alive-timeout: 10s
        idle-timeout: 30m
        default-deadline: 5s
      channels:
        my-service-client:
          address: dns:///my-service:9090
          default-load-balancing-policy: round_robin

Effective config for my-service-client: PLAINTEXT (not TLS), no default deadline (RPCs can hang indefinitely), keep-alive 5m/20s, idle-timeout 20s. We hit exactly this in production configuration and only caught it by reading the library source.

Paper trail — the fix existed but never shipped

  1. Allow named channels to inherit default configuration #345 ("Allow named channels to inherit default configuration") reported this. Community PRs Allow named channels to inherit configuration from default-channel #346 / Allow named channels to inherit default configuration #347 by @o-shevchenko were iterated on and superseded.
  2. The maintainer-reworked fix landed on main as commit 0bc8c88bc21c0c77e03bd1affb591bc62432ee56 ("Allow channels to inherit configuration from default configurations", resolves Allow named channels to inherit default configuration #345, milestone 1.1.0-M1). It introduced a channel-defaults block plus an opt-in per-channel inherit-defaults flag with proper unset-vs-explicit merge semantics (ChannelConfig.mergeWith).
  3. Before v1.1.0-M1 was tagged, the client auto-configuration modules (spring-grpc-client-spring-boot-autoconfigure, starters) were removed from this repository as part of the auto-configuration move into Spring Boot itself (cf. Migrate autoconfiguration to Spring Boot #234, Moves autoconfiguration and starters to Spring Boot #388). The v1.1.0-M1 and v1.1.0 trees contain no auto-configure module, so no released spring-grpc artifact contains the fix. The commit is an ancestor of the v1.1.0 tag, but the module it modified was deleted before the tag was cut.
  4. The fix was also never backported to the 1.0.x line (verified against the published 1.0.3 sources).
  5. Spring Boot 4.1.0's new spring-boot-grpc-client module (org.springframework.boot.grpc.client.autoconfigure, @since 4.1.0) reimplemented the property model (spring.grpc.client.channel.<name>.* with a reserved default map key), and its resolution is again whole-object fallback with no merging — inherit-defaults does not exist there:
// PropertiesGrpcChannelBuilderCustomizer (spring-boot main / v4.1.0)
private Channel getChannel(String target) {
    Channel channel = this.properties.getChannel().get(target);
    channel = (channel != null) ? channel : this.properties.getChannel().get("default");
    return (channel != null) ? channel : STOCK_DEFAULT_CHANNEL;
}

So a user who defines channel.default.* plus a named channel still loses every default for that named channel — the same trap #345 fixed, in new syntax.

Ask

  • Restore the Allow named channels to inherit default configuration #345 inherit-defaults / merge semantics (or equivalent) in the code's current home, spring-boot-grpc-client.
  • Alternatively/additionally: document prominently that default-channel (1.0.x) / the default channel entry (Boot 4.1+) is a whole-object fallback for undefined channel names only, and is never merged into defined channels. The current property naming strongly implies inheritance, and misconfiguration fails silently (most dangerously by dropping default-deadline).
  • If this belongs on the Spring Boot tracker, let me know and I'll re-file there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions