spring-projects / spring-projects/spring-grpc
BearerTokenAuthenticationInterceptor: lambda constructor call became ambiguous after adding TokenSupplier overload in 1.1.1
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 413
- Forks
- 95
- Avg merge
- 4d 6h
- Merged PRs (30d)
- 2
Description
Bug description
Since 1.1.1 (added in #378), BearerTokenAuthenticationInterceptor has three constructors:
public BearerTokenAuthenticationInterceptor(String token) { ... }
public BearerTokenAuthenticationInterceptor(Supplier<String> token) { ... }
public BearerTokenAuthenticationInterceptor(TokenSupplier token) { ... }
Supplier<String> and TokenSupplier are both functional interfaces with a single, argument-less method returning String (get() vs. token()). Because they are structurally identical from the compiler's point of view, any call
site that passes an inline, un-targeted lambda expression to the constructor no longer compiles - it now fails with reference to BearerTokenAuthenticationInterceptor is ambiguous, because both the Supplier<String> and the
TokenSupplier overload are equally applicable.
This is a well-known Java overloading pitfall (see Effective Java, Item 52: "avoid overloading with different functional interface parameters in the same argument position") and effectively breaks source compatibility for existing
1.1.0 users who wrote code like:
new BearerTokenAuthenticationInterceptor(() -> jwt.getTokenValue())
even though adding a new overload is normally considered a backwards-compatible, additive change.
Steps to reproduce
- Take any code compiled against spring-grpc 1.1.0 that constructs a
BearerTokenAuthenticationInterceptorwith an inline lambda, e.g.:@Bean MyServiceGrpc.MyServiceBlockingStub myServiceBlockingStub(GrpcChannelFactory channels) { return MyServiceGrpc.newBlockingStub(channels.createChannel("myService")) .withInterceptors( new BearerTokenAuthenticationInterceptor( () -> SecurityContextHolderJwtHelper.getJwt().getTokenValue())); } - Bump spring-grpc to 1.1.1 (no other code changes).
- Compile.
Actual behavior
Compilation fails with:
reference to BearerTokenAuthenticationInterceptor is ambiguous
both constructor BearerTokenAuthenticationInterceptor(java.util.function.Supplier<java.lang.String>) in org.springframework.grpc.client.interceptor.security.BearerTokenAuthenticationInterceptor
and constructor BearerTokenAuthenticationInterceptor(org.springframework.grpc.client.interceptor.security.TokenSupplier) in org.springframework.grpc.client.interceptor.security.BearerTokenAuthenticationInterceptor match
Expected behavior
Adding the new TokenSupplier constructor in a patch/minor release should not silently break source compatibility for existing consumers using the previously-recommended inline-lambda style.
Possible fixes
- Deprecate and eventually remove the
Supplier<String>overload now thatTokenSupplierexists, instead of keeping both indefinitely. - Alternatively, make
TokenSupplierextendSupplier<String>(with a defaulttoken()/get()bridging method) so there is only one truly distinct SAM type at this argument position, removing the ambiguity. - At minimum, document this as a known source-incompatible change in the 1.1.1 release notes so users know to add an explicit cast (
(TokenSupplier) () -> ...or(Supplier<String>) () -> ...) when upgrading.
Environment
- spring-grpc: 1.1.1 (regression vs. 1.1.0)
- Java: 21
- Spring Boot: 4.x
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the BearerTokenAuthenticationInterceptor constructors and the TokenSupplier definition, then reproduce the Java 21 compilation failure with the inline lambda shown in the issue. Compare the proposed compatibility options and add regression coverage for the selected API behavior. Done means existing 1.1.0-style lambda call sites compile against 1.1.1 without ambiguity.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend-api-design, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100