javaspringspring-cloud-stream

How to properly implement a binder?


Question was heavily edited during discussion with Oleg

I'm trying to implement a binder for BigQuery in Spring Cloud Stream.

Full code of application is avaiable on GitHub.

So far, I've written a BigQueryBinderConfiguration class which returns a BigQueryBinder the following way

@Configuration @EnableConfigurationProperties({ BigQueryConfiguration.class })
public class BigQueryBinderConfiguration {
    @Autowired BigQueryConfiguration configuration;

    @Bean
    BigQueryBinder bigQueryMessageChannelBinder(BigQueryConfiguration configuration, BigQueryProvisioningProvider provisioningProvider) {

        return new BigQueryBinder(configuration, provisioningProvider);
    }

    @Bean BigQueryProvisioningProvider provisioningProvider() {
        return new BigQueryProvisioningProvider(configuration);
    }
}

My problem is that when doing so, my other binders (Rabbit and Kafka) are no more recognized.

My testing protocol is as follows : I start my application and check in rabbitmq admin interface if my application registers as a consumer. This is not the case when this code is uncommented.

When debugging call to bigQueryMessageChannelBinder(....), I observe the following things.

The DefaultBinderFactory#getBinder(...) method always return my BigQueryBinder instance. Debugging indicates that the call to this.context.getBeansOfType(Binder.class); returns a list that only contains my BigQueryBinder. I'm puzzled, because the other binders are in my classpath, and if I remove the factory method BigQueryBinderConfiguration#bigQueryMessageChannelBinder(....), everything works fine.

I've discovered during debug that DefaultBinderFactory is the class that is used to associate a binder to a configuration name. I've also discovered that Binder implementations should not appear in Map<String, Binder> binders. But unfortunatly, my Binder implementation appear in that list. i guess it has something to do with the bean nature. But how ?


Solution

  • I think the best thing you can do is to first look at our new TestChannelBinder.java. Basically it's a full blown binder backed by Spring Integration. In other words Spring Integration and it's channels play a role of a message broker the same was Rabbit, Kafka, GCP and other binders. What's important about this binder is that it effectively demonstrates a bare minimum of what's required to implement a functioning binder.