Search code examples
javaspring-bootrabbitmqamqpspring-cloud-stream

How to configure spring boot to bind a supplier to a rabbitmq queue with spring-cloud-stream and rabbit-binder?


I want to send messages to a rabbitmq queue demo-queue using a very simple spring boot app:

package com.example.demo;

import java.time.LocalDateTime;
import java.util.function.Supplier;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
    @Bean
    public Supplier<String> sampleProducer() {
        return () -> {
            System.out.println("producing message");
            return LocalDateTime.now().toString();
        };
    }
}

I currently have the following application.yml:

---
spring:
  rabbitmq:
    addresses: amqp://guest:guest@localhost:5672

When I start the application it logs that its connected to rabbitmq and prints out messages in the console written in the sampleProducer. So the supplier is started and queried for new messages. However I don't see a queue in rabbitmq being created and filled with the produced messages.

The pom.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

I'm lost in the spring documentation and examples because I haven found an example in there that puts a message created by a Supplier into a queue.

What do I need to do in order to actually send the messages to the queue? I would like to only change application.yml and not add additional code if that's possible.


Solution

  • RabbitMQ producers don't publish to queues, they publish to exchanges.

    Spring Cloud Stream producers don't bind a queue to the destination exchange by default.

    RabbitMQ discards unroutable messages by default.

    You can add

    spring.cloud.stream.bindings.sampleProducer-out-0.producer.required-groups=foo
    

    and the producer will bind a queue to the destination exchange.