springspring-integrationspring-integration-dslspring-dsl

Spring Integration Channeling With Bean Name vs Method Name


I have PublishSubscribeChannel like this:

@Bean(name = {"publishCha.input", "publishCha2.input"}) //2 subscribers
    public MessageChannel publishAction() {
        PublishSubscribeChannel ps = MessageChannels.publishSubscribe().get();
        ps.setMaxSubscribers(8);
        return ps;
    }

I have also subscriber channels:

@Bean
    public IntegrationFlow publishCha() {
        return f -> f
                .handle(m -> System.out.println("In publishCha channel..."));
    }


@Bean
    public IntegrationFlow publishCha2() {
        return f -> f
                .handle(m -> System.out.println("In publishCha2 channel..."));
    }

And finally another subscriber:

@Bean
    public IntegrationFlow anotherChannel() {
        return IntegrationFlows.from("publishAction")
                .handle(m -> System.out.println("ANOTHER CHANNEL IS HERE!"))
                .get();
    }

The problem is, when I call channel with method name "publishAction" like below from another flow, it only prints "ANOTHER CHANNEL HERE" and ignores other subscribers. However, if I call with .channel("publishCha.input"), this time it enters publishCha and publishCha2 subscribers but ignoring the third subscriber.

@Bean
    public IntegrationFlow flow() { 
        return f -> f
       .channel("publishAction");
    }

My question is, why those two different channeling methods yields different results?

.channel("publishAction") // channeling with method name executes third subscriber

.channel("publishCha.input") // channelling with bean name, executes first and second subscribers

Edit: narayan-sambireddy requested how I send messages to channel. I send it via Gateway:

@MessagingGateway
public interface ExampleGateway {

@Gateway(requestChannel = "flow.input")
    void flow(Order orders);
}

In Main:

Order order = new Order();
      order.addItem("PC", "TTEL", 2000, 1)
    ConfigurableApplicationContext ctx = SpringApplication.run(Start.class, args);
    ctx.getBean(ExampleGateway.class).flow(order);

Solution

  • Your problem with the third subscriber that you miss the purpose of the name in the @Bean:

    /**
     * The name of this bean, or if several names, a primary bean name plus aliases.
     * <p>If left unspecified, the name of the bean is the name of the annotated method.
     * If specified, the method name is ignored.
     * <p>The bean name and aliases may also be configured via the {@link #value}
     * attribute if no other attributes are declared.
     * @see #value
     */
    @AliasFor("value")
    String[] name() default {};
    

    So, method name as a bean name is ignored in this case, therefore Spring Integration Java DSL doesn't find a bean with the publishAction and creates one - DirectChannel.

    You can use method reference though:

    IntegrationFlows.from(publishAction())
    

    Or, if that is in a different configuration class, you can re-use one of the predefined name"

     IntegrationFlows.from(publishCha.input)
    

    This way DSL will re-use existing bean and will just add one more subscriber to that pub-sub channel.