Technology: Spring Cloud Stream is the framework for building message-driven applications using spring boot. It provides a way to integrate with other applications, without depending on other applications, it uses Spring Integration to communicate with other applications.
Spring cloud stream provides abstractions, primitives for an easy way to develop message-driven applications.
Application Model:
Spring cloud stream consists of middleware and application core. The application will communicate with the outside world using input/output channels which are injected by spring cloud stream.
Channels are connected to middleware using binders spring cloud stream provides various binders for different middleware like Apache Kafka, RabbitMQ.
Binder Abstraction:
Applications individually choose to which middleware they want to connect, by default spring cloud stream is dependent on spring boot autoconfiguration, if more than one binder is present on classpath then, using application.properties or application.yml we need to provides the binder configurations, we can also choose binder at channel level also, means for one channel we can use Kafka middleware and for other channel we can choose the RabbitMQ channel etc…
Persist Publish-Subscribe:
Communication between applications will use a publish-subscribe model where data shared among the all connected client. The below diagram shows a typical flow between applications.
Where data is coming from HTTP source will send to spring cloud stream application endpoint, and it will process, the incoming data and it will publish the data to middleware the connected applications to middleware will get the data. This model will reduce the complexity of the producer and consumer, allows to add the new application to middleware without disturbing the existing flow. Using the middleware, Basic Support Spring Cloud Stream, our models make it easy to publish messages to different middleware applications.
Consumer Groups:
The Publish subscribe provides the ability to scale up by creating multiple instances of the application. When multiple instances of, the same application running we need to consume message by only one of the instance of the application. Spring cloud stream implements this behavior by providing the group name for the consumer so that only one of the instance per group will handle. We can specify the group name in the application.properties file:
spring.cloud.stream.bindings.<channelName>.group
All the groups subscribed to groups will receive a copy of published data, but only one of the group member will receive the message from the destination when the group is not specified spring cloud stream assigns an anonymous group and independent single member consumer group along with other consumer groups.
Durability: The applications sent to consumer group y default are durable, the binder implementations ensure that they are persistent, once at least one subscription for a group created, the group will receive messages, even if they sent while all applications in the group stopped. We must specify group name so that no duplicate messages handled again.
Programming Model: we can turn spring application into spring cloud stream by adding @EnableBinding on one of the application configuration files, this annotation is meta-annotated with, @Configuration and it triggers the annotation of spring cloud stream.
@Configuration @Import({ChannelBindingServiceConfiguration.class, BindingBeansRegistrar.class, BinderFactoryConfiguration.class, SpelExpressionConverterConfiguration.class}) @EnableIntegration public@interfaceEnableBinding { /** * A list of interfaces having methods annotated with {@link Input} and/or * {@link Output} to indicate bindable components. */ Class<?>[] value() default {}; }
This annotation will accept one or more than one interfaces contains methods which represent the bind methods.
Creating a binding interface:
Spring cloud stream application can have any number of input, output channels defined in an interface annotated with @Input, @output, and we need to pass this interface in @EnableBinding annotation, this will trigger the spring cloud stream and creates orders, hot drinks, cold drinks message channels.
public interface Hotel { @Input SubscribableChannelorders(); @Output MessageChannelhotDrinks(); @Output MessageChannelcoldDrinks(); }
Customizing the Channel names: we can customize the channel name using value attribute in Input, Output annotation.
public interface Hotel { @Input("inboundOrders") SubscribableChannelorders(); ... }
The created bound channel will named inboundOrders.
Spring cloud stream provides 3 interfaces for common use cases.
Sink: It is interface used for single inbound channel.
Source: It is interface used for single outbound channel.
Processor: It is interface used for both single inbound/outbound channel. Spring cloud stream does not provide any special handling for these interfaces they provided only for reference.
Injecting interfaces into Spring Beans: Then methods specified in interfaces provided in @EnableBinding annotation will create a channel based on its type (like input channel for @Input and output channel for @Output), and using methods in interfaces we can send/receive the messages.
Injecting Message Channels Directly: Instead of depending these interfaces we can also directly inject channels directly into beans.
@Component public class SendingBean { privateMessageChannel output; @Autowired publicSendingBean(MessageChannel output) { this.output = output; } public void sayHello(String name) { output.send(MessageBuilder.withPayload(body).build()); } }
MessageChannel injected with, channel name output, we can also customize bypassing channel name to MessageChannel.
Eg: @Output("customOutput") MessageChanneloutput();
Spring cloud stream also supports spring-messaging and spring-integration annotations like @SendTo, @MessageMapping,@Transformer,@ServiceActivator etc..
Binders: Spring cloud stream provides a Binder interface for interacting with different middleware providers.
The interface has bindProducer method to return the producer, the method has three arguments, and the first argument takes the channel name, and the second argument is the channel instance to send the messages, third parameter points to channel additional properties.
The interface has bindConsumer method is to return the consumer, the method has four arguments, the first argument refers to destination name, and the second argument refers to the logical group name, the third argument refers to channel instance to receive the message and four arguments, refers to additional consumer properties.
public interface Binder<T, C extends ConsumerProperties, P extends ProducerProperties> { Binding<T>bindConsumer(String name, String group, T inboundBindTarget, C consumerProperties); Binding<T>bindProducer(String name, T outboundBindTarget, P producerProperties); }
Specifying Properties for each channel:
We can also specify properties for each channel like specifying binder, binder configuration, content-type of the message and max-retries for each channel, etc.
We can specify channel properties using the prefix in the application.properties file.
spring.cloud.stream.bindings.<channelName>
List of properties supported by channel specific are present in BindingProperties.java file.
We can specify the producer related properties using prefix spring.cloud.stream.bindings.
<channelName>.producer
Consumer properties using spring.cloud.stream.bindings.<channelName>.consumer prefix.
We can also specify the host details of binder using spring.cloud.stream.binders.<binding-name>.environment.spring.rabbitmq.host property.
Conclusion: Spring cloud stream is a framework for developing a stream-based application in an accessible way, which is used to develop an application in a modular way (independent applications), we can easily host on spring data flow servers, we can integrate with various middleware applications using native middleware support. We can also specify the global configuration and also channel specific binder properties, and also if the application is hosted on cloud using cloud connectors we can specify the cloud instances of middleware applications.
You can download the producer and consumer of the applications using below GitHub repositories.
https://github.com/sravan4rmhyd/Spring-Stream-RabbitMQ.git
Have you tried Spring Cloud Stream for Java web development yet? Share your experience with the readers and let them know about this framework.
Tags: Java, Java web development, spring cloud stream