Skip to content

spring.cloud.stream.function.autodetect=true (default setting) for spring-webflux app with server.forward-headers-strategy=FRAMEWORK can't work #3177

@jonenst

Description

@jonenst

Describe the issue
Using a spring-webflux app with server.forward-headers-strategy=FRAMEWORK, autoconfiguration provides a ForwardedHeaderTransformer bean which breaks all use cases of spring.cloud.stream.function.autodetect :

  • if you have only output-bindings, a queue is createded and a consumer is registered on this queue which noone ever wants. If you send a message to this queue, you get
java.lang.ClassCastException: class [B cannot be cast to class org.springframework.http.server.reactive.ServerHttpRequest ([B is in module java.base of loader 'bootstrap'; org.springframework.http.server.reactive.ServerHttpRequest is in unnamed module of loader 'app')
  • if you had a single java.util.function.* bean and relied on autodetection, it doesn't work.:
17:59:09.253 [main] WARN  org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry - Multiple functional beans were found [forwardedHeaderTransformer, myConsumer], thus can't determine default function definition. Please use 'spring.cloud.function.definition' property to explicitly define it. 

To Reproduce
Steps to reproduce the behavior:
see above
all versions

Additional context
In the docs there is the following note:

In the event you only have single bean of type java.util.function.[Supplier/Function/Consumer], you can skip the spring.cloud.function.definition property, since such functional bean will be auto-discovered. However, it is considered best practice to use such property to avoid any confusion. Some time this auto-discovery can get in the way, since single bean of type java.util.function.[Supplier/Function/Consumer] could be there for purposes other then handling messages, yet being single it is auto-discovered and auto-bound. For these rare scenarios you can disable auto-discovery by providing spring.cloud.stream.function.autodetect property with value set to false.

To me, this would have been a good idea if there were really no easy cases where autodection breaks down. It depends on what "rare" means of course, but just a plain webflux springboot app with a single nonexotic property "server.forward-headers-strategy" doesn't seem to be that rare.

So maybe just make autodetection opt-in ? But then it doesn't make much sense, autodetection is for zero config (onboarding), so it's not interesting to add explicit autodetection=true configuration just to avoid some other configuration..

So maybe just delete autodetection entirely? You would lose the easy zero config onboarding.

Or make the autodection really reliable:

  • maybe the autodetection should only happen when there is zero spring.cloud.stream.bindings or output-bindings configuration ? zeroconfig onboarding would still work (unless the user chose webflux+forward-headers-strategy=FRAMEWORK to try it out) and normal applications with only output-bindings wouldn't get the spurious consumer
  • maybe find a way to exclude all "standard" beans. Based on the package ? Based on the function Signature (who would use Function<HttpServletRequest, HttpServletRequest>) ? Based on something else ?
  • another idea ?

Cheers,
Jon

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