问题
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 ?
回答1:
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.
回答2:
Based on the conversations in this issue #1623 .
I want to consume/produce messages from/to Spring Cloud Stream channels to an internal event bus from Axon Framework.
Is the model in this photo correct?
Application model with internal and external binder
If it is correct,I think we should use the channels from Stream in custom binder by injecting beans or other methods.
In TestChannelBinder
class the channels have been created in user code with calling constructor,How to use channels managed by Spring Cloud Stream in custom binder?
private SubscribableChannel provisionDestination(String name, boolean pubSub) {
String destinationName = name + ".destination";
SubscribableChannel destination = this.provisionedDestinations
.get(destinationName);
if (destination == null) {
destination = pubSub ? new PublishSubscribeChannel() : new DirectChannel();
((AbstractMessageChannel) destination).setBeanName(destinationName);
((AbstractMessageChannel) destination).setComponentName(destinationName);
this.provisionedDestinations.put(destinationName, destination);
}
return destination;
}
来源:https://stackoverflow.com/questions/54921839/how-to-properly-implement-a-binder