rabbitmqspring-cloud-streamspring-rabbit

spring.cloud.stream.output-bindings What's its actual purpose or use?


What is the real use of spring.cloud.stream.output-bindings property if i am using streambridge instead of supplier for producer ? what if i skip this property ? Is it mandatory with use of Streambridge ?

from here, though its mentions that binding will be pre-created but its not giving complete clarity. Is this property man

My yml looks something like this below -:

Spring:
  cloud:
    function:
      definition: consumerinput
  stream:
    output-bindings: hardstopproducer
    bindings:
      consumerinput-in-0:
        group: team.queue.cit.user
        contentType: application/json
        binder: rabbit
      consumerretry:
        group: team.queue.cit.user
        destination: team.river.retry
        contentType: application/json
        binder: rabbit
      hardstopproducer:
        destination: team.river
        contentType: application/json
        binder: rabbit

I am getting below issue if i use output-binding-:

message":"Shutdown Signal: channel error; protocol method: #method<channel.close>(reply-code=403, reply-text=ACCESS_REFUSED - configure access to exchange 'hardstopproducer' in vhost 'dev' refused for clinical 'hardstopproducer' In rabbitMQ user , access has been provides such that only this exchanges starting with "team" keyword will be allowed to created.

My expectation is spring cloud stream should not try to create an exchange with the name i have provided in the producer binding since the name provided under output-bindings and the binding name are same. So no autoProvisioning should be done here.


Solution

  • I just tested this feature with Spring Boot 3.3 and Spring Cloud Azure with Azure Service Bus, so I think I can provide an answer with my personal experiences.

    (This framework feature should be message queue vendor agnostic, so the same should apply if one uses RabbitMQ.)


    Your 1st question

    What is the real use of spring.cloud.stream.output-bindings property if i am using streambridge instead of supplier for producer ?

    Let's refer to the official doc that talks about this property:

    Sending arbitrary data to an output (e.g. Foreign event-driven sources)

    Refer to this paragraph underneath the sample code using StreamBridge:

    However, if you want to pre-create an output binding at the initialization (startup) time you can benefit from spring.cloud.stream.output-bindings property where you can declare the name of your sources. The provided name will be used as a trigger to create a source binding.

    1. According to this paragraph, the output-bindings property pre-creates producer bindings at application startup phase.
    2. ⚠️ Otherwise, if not pre-created at startup, then it's during runtime (i.e. at a later stage when your app is already running healthily and serving requests).
    3. You should notice that this paragraph is under the section about sending messages using StreamBridge instead of the Java 8 Supplier functional programming style.
    4. This means that this output-bindings feature is closely related to using StreamBridge API.

    💡💡💡

    Now, here's the answer to why you'd ever want to use this property:

    1. Imagine that you have a project that uses Spring Cloud Stream to send messages "only" using StreamBridge.
    2. With this property, when you start up this Spring Boot app, it pre-creates (eagerly rather than lazily) the binding, which then also creates the binder and caches the binder.
    3. Apparently, in this project, message sending is triggered either with a REST endpoint or a scheduler that runs on its own at certain time.
    4. Let's say it's a REST endpoint. Now, when you call this REST endpoint, Spring Cloud Stream will simply use your binding and the cached binder to send the message to your MQ broker.

    Your 2nd question

    What if i skip this property ? Is it mandatory with use of Streambridge ?


    Conclusion

    When you are only using StreamBridge on a binder,

    Note that, if you are NOT only using StreamBridge but also the Supplier functional programming style that automatically produces a message every 1 second with spring.cloud.function.definition (this registers the producer function), Spring Cloud Stream will still create and cache a binder at startup phase because this periodical auto-send feature starts at the time your app starts up.

    I hope all these make sense. 😊