What’s the difference between AbstractMessageSource and MessageProducerSupport in Spring Integration? - spring

When developing inbound channel adapters, I couldn’t find any place that mentions the differences between AbstractMessageSource and MessageProducerSupport in Spring Integration. I’m asking this question in the context of reactive streams, so I’m actually looking at AbstractReactiveMessageSource, but I guess it doesn’t matter for my question. I also wonder whether MessageProducerSupport supports project reactor and doesn’t have an equivalent to AbstractReactiveMessageSource.

There is some documentation about these types of components: https://docs.spring.io/spring-integration/docs/current/reference/html/overview.html#finding-class-names-for-java-and-dsl-configuration
The inbound message flow side has its own components, which are divided into polling and listening behaviors.
So, the MessageProducerSupport is for those protocols which provide a listening callback for us. So, we can hook up into that, build message and produce it into a channel provided by the MessageProducer. So, it is self-eventing component which really has everything to listen to the source system and produce messages from the callback. This type of channel adapters called event-driven and samples of them are JMS, AMQP, HTTP, IMAP, Kinesis etc.
From here it is wrong to try to compare the MessageProducerSupport with an AbstractMessageSource because the are not relevant. The one you should look into is a SourcePollingChannelAdapter. Exactly this one is that kind of flow beginning endpoint which is similar to MessageProducerSupport. With only the problem that it is based on a periodic scheduled task to request for messages in the provided MessageSource. This type of component is for those protocols which don't provide listening callback, e.g. local file system, (S)FTP, JDBC, MongoDb, POP3, S3 etc.
You probable would expect something similar to MessageSource for the MessageProducer level, but there is not that kind of layer because everything single event-driven protocol has its own specifics, therefore we cannot extract some common abstraction like in case of polling protocols.
If your source system provides for you a reactive Publisher, you don't need to look into a SourcePollingChannelAdapter and MessageSource. You just need a MessageProducerSupport and call its subscribeToPublisher(Publisher<? extends Message<?>> publisher) from the start() implementation.
There is no need in the reactive implementation for the polling since Publisher is not pollable by itself it is event-driven. Although it has its own back-pressure specifics which is out of MessageProducerSupport scope.
There is also some explanation in this section of the doc: https://docs.spring.io/spring-integration/docs/current/reference/html/reactive-streams.html#source-polling-channel-adapter. And see a couple next paragraphs.

Related

Development compromises in using Spring Cloud Stream

The case for event-driven microservices such as Spring Cloud Stream is their asynchronous nature, which I do agree it makes them more scalable
But I have an issue regarding how to code it in a way where I don't lose certain key features that I have access to using synchronous services
In a servlet-based MS, I make full use of servlet context variables and servlet-based Spring autowiring functions
For e.g., I leverage heavily on HTTP headers to carry metadata between microservices without having to impact the payload. But in Spring Cloud Stream using Kafka, Kafka doesn't support message headers of any kind! I lose that immediately if I use SCS. Putting them into the payload causes all sort of changes in my model classes if I define the attributes clearly. Yes, I can use a simple Hashmap to simulate the HTTP header object but it really seems like reinventing the wheel to me.
On the auto-wiring side: I maintain an audit log record per request, which I implement by declaring a request-scoped Hashmap bean and autowiring it into any methods in the Servlet's call stack that needs to append data to the audit log. Basically it's just a global variable to hold some data within a single request. But in SCS, again, I lose that cos bean scopes that leverage on servlets are not available.
So far, there seems to be a lot of trade-offs that I have to make just to make Spring Cloud Stream work for me.
I thought about an alternative approach where I use SCS just to create an entry point but the Source method would just get the event, use a Processor to construct a HTTP request and send the request along to a HTTP endpoint. But, why go through all that trouble then?
Hoping that some more experienced devs would be able to shed some light on how they leverage on SCS.
#feicipet Thanks for the detailed question. let me try to address some of your concerns in the order you have listed them:
+1
+1
I am not sure why you are referring to it as servlet-based instead of Spring-based? Those are features provided by Spring, but read on. . .
Spring Cloud Stream doesn't use Kafka, the end user does while Spring Cloud Stream provides Kafka binder allowing Spring Cloud Stream to integrate with Kafka. Further more, while Kafka indeed did not support headers prior to version 0.11, Spring Cloud Stream always supported and will continue support headers even with Kafka pre-0.11, embedding them in the Message and then extracting them in the consumer side into the proper Message headers completely transparent to the end user. In other words one would assume that Kafka did support headers by simply using Spring Cloud Stream. With Kafka 0.11+ headers are supported natively and we have adjusted to that with the same level of transparency.
So, you don't need to put anything in the payload. Just create an appropriate Message<payload, headers> and SCSt will take care of the rest regardless of the broker (Kafka, Rabbit, Foo etc.).
Yes you do simply due to the fact that as you eluded earlier SCSt promotes an asynchronous and stateless architecture. However, I do not agree that what you are trying to accomplish is un-accomplishable. Rather it is accomplishable the way you are describing, but there are other way to maintain context and I would be more then glad to discuss it as a separate topic.
I would not call them trade-offs, rather difference in the architecture, that has its benefits, but it is a not one-size-fits-all architecture and therefore its viability should be discussed within the context of a concrete use case.
+1. You don't have to separate it as Source and Processor. You can simply create a custom Source app with exposed REST endpoint and custom processing logic. However we are currently working on enhancements i the framework to ensure that you could do the same with the existing starter apps.
Obviously we have touched on many points here and some of them would probably need to be debated further, but I hope this clears up some of your concerns.
Cheers

Microservices: Service discovery/ circuit breaker for Event-driven architecture

I'm fairly new to Microservices...
I've taken an interest in learning more about two main patterns like service discovery and circuit breaker and I have conducted research on how these could be implemented.
As a Java Developer, I'm using Spring Boot. From what I understand, these patterns are useful if microservices communicate via HTTP.
One of the topics I've recently seen is the importance of event-driven architecture, which makes use of an event message bus that services would use to send messages to for other services, which subscribe to the bus
and process the message.
Given this event-driven nature, how can service-discovery and circuit breakers be achieved/implemented, given that these are commonly applicable for services communicating via HTTP?
From what I understand, these patterns are useful if microservices communicate via HTTP.
It is irrelevant that the communication is HTTP. The circuit breaker is useful in prevention of cascade failures that are more probable to occur in the architectures that use a synchronous communication style.
Event-driven architectures are in general asynchronous so cascade failure is less probable to occur.
Service discovery is used in order for the microservices to discover each other but in Event-driven architectures microservices communicate only to the messaging infrastructure (i.e. the Event store in Event sourcing) so discoverability could be used only at the infrastructure level.
I. circuit breaker and service discovery are patterns. When we say Pattern they can be implemented with any programming language. 'HTTP' protocol is for transfer of data.
circuit breaker can be implemented within Java. You can find many implementations (of course, with varying capabilities and interpretation of pattern) on github.
Some of the well-known, built for purpose implementations are :
Hysterix from NetflixOSS For using Hysterix: You can follow Spring Guide - Spring Circuit Breaker
Apache Polygene - which has example of JMX circuit breaker
Resilience4j
II. About,
Given this event-driven nature, how can service-discovery and circuit
breakers be achieved/ implemented, given that these are commonly
applicable for services communicating via HTTP?
It seems you need bit more research on topic of Microservices interactions.
There are two ways to which microservices interactions are possible. You have to choose one over the other. You can/should not mix both.
Orchestration: An interaction style that has an intelligent controller that dispatches events to processes. Please note the word 'processes' which is representing business processes here. Orchestration style was preferred in old SOA implementations as well.
Choreography: An interaction style that allows processes to subscribe to events and handle them independently or through integration with other processes without the need for a central controller.
These topics are greatly covered under
Orchestration vs. Choreography
Need of Service Discovery:
With choreography, two or more microservices can coordinate their activities and processes to share information and value.
But, these microservices may not be aware of each other's existence i.e. There are no hard-coded or service references of dependency endpoints configured or coded into them. Why we do this, is for avoiding any kind of coupling between services. So, the question remains is how one service, if required will find another services' endpoint? This is where service discovery mechanism is used.
Another perspective is, with microservices deployment with containers etc, microservices endpoints will not be even tied to any hosts etc. [due to spin-up and spin-down of containers]. So, for this case as well, we need 'service discovery' mechanism.
So, In service discovery mechanism, a centralized service discovery tool helps services to register themselves and to discover other services via a DNS or HTTP interface.
Service discovery can be implemented with
1. Server-side service discovery
2. Client Side service discovery
Consul,etcd, zookeeper are some of the key-tools names within service discovery space.
Spring Boot integrates well with Spring Cloud. And Spring Cloud provides Eureka (for service discovery) as well as Hystrix (for circuit breaker patterns). Also, Spring Cloud Stream to provide event driven patterns
Very easy to use with Spring Boot
I believe there is a misunderstanding in the question in that you assume that event-driven architectures cannot be implemented on top of HTTP.
An event-driven architecture may be implemented in many different ways and (when the architecture is that of a distributed system), on top of many different protocols.
It can be implemented using a message broker (i.e. Kafka, RabbitMQ, ActiveMQ, etc) as you suggested it too. However, this is just a choice and certainly not the only way to do it.
For example, the seminal book Building Microservices by Sam Newman, in Chapter 4: Integration, under Implementing Asynchronous Event-Based Collaboration says:
“Another approach is to try to use HTTP as a way of propagating
events. ATOM is a REST-compliant specification that defines semantics
(among other things) for publishing feeds of resources. Many client
libraries exist that allow us to create and consume these feeds. So
our customer service could just publish an event to such a feed when
our customer service changes. Our consumers just poll the feed,
looking for changes. On one hand, the fact that we can reuse the
existing ATOM specification and any associated libraries is useful,
and we know that HTTP handles scale very well. However, HTTP is not
good at low latency (where some message brokers excel), and we still
need to deal with the fact that the consumers need to keep track of
what messages they have seen and manage their own polling schedule.
I have seen people spend an age implementing more and more of the
behaviors that you get out of the box with an appropriate message
broker to make ATOM work for some use cases. For example, the
Competing Consumer pattern describes a method whereby you bring up
multiple worker instances to compete for messages, which works well
for scaling up the number of workers to handle a list of independent
jobs. However, we want to avoid the case where two or more workers see
the same message, as we’ll end up doing the same task more than we
need to. With a message broker, a standard queue will handle this.
With ATOM, we now need to manage our own shared state among all the
workers to try to reduce the chances of reproducing effort. If you
already have a good, resilient message broker available to you,
consider using it to handle publishing and subscribing to events. But
if you don’t already have one, give ATOM a look, but be aware of the
sunk-cost fallacy. If you find yourself wanting more and more of the
support that a message broker gives you, at a certain point you might
want to change your approach.”
Likewise, if your design uses a message broker for the event-driven architecture, then I'm not sure if a circuit breaker is needed, because in that case the consumer applications control the rate at which event messages are being consumed from the queues. The producer application can publish event messages at its own pace, and the consumer applications can add as many competing consumers as they want to keep up with that pace. If the server application is down the client applications can still continue consuming any remaining messages in the queues, and once the queues are empty, they will just remain waiting for more messages to arrive. But that does not put any burden on the producer application. The producer and the consumer applications are decoupled in this scenario, and all the work the circuit breaker does in other scenarios would be solved by the message broker application.
Somewhat similar can be said of the service discovery feature. Since the producer and the consumer do not directly talk to each other, but only through the message broker, then the only service you need to discover would be the message broker.

Spring Integration : QueueChannel guarantee no data loss?

I want my system to guarantee there is no data loss even if the system is shutting down.
What this mean is that the system must not miss the request message. So, I will change the way that accept http reqeust. Now, I am using http gateway/webservice gateway in spring integration. But, This isn't receive the message even if the system dies. So, I want to add the queue between the http client and the http receiver. So, I want to use a queue channel. Here is the question.
① I have to install other queue program such as activemq or rabbitmq and have to connect to the queue channel in spring integration?
② and which one is the best combination with spring integration? I heard that rabbit mq is the best one.
please give me a elaborate explanation. thanks.
First of all you description isn't clear...
If you don't want to lose messages from the QueueChannel use some Persistence MessageStore, like JdbcChannelMessageStore:
http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/system-management-chapter.html#message-store
From other side there are channel wrappers for the AMQP as well as for JMS:
http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/amqp.html#d4e5846
http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/jms.html#jms-channel
Which really provide the same persistence durability, fault tollerant options for your use-case.
Re. activemq VS rabbitmq. I can say by my own expiriance that the last one is better, by configuration, usage from Spring Integration (Spring AMQP is under the shell). And its performance is really better.
All other info you can find in the Internet.

Pattern for handeling multiple message types with spring JMS in a multi module maven setup

I' m currently investigation the implementation of queue's or topic, based on activeMQ within our project. The setup is pretty straight forward in which we are using maven modules to seprate business logic according to the business domain. One common module allows us to assemble common logic.
simplified Example:
common module
products module
clients module
One of the requirements is that certain operations are asynchronous towards a backend (by means of a activeMQ) which in turn responds with a result message.
The second requirement is that it should be possible to horizontally scale the application by creating a new deployable artifact with only that module that needs more juice.
We are using spring 4 with of course jms and activeMQ.
On to my question. We would like to use just one queue or topic for backend connectivity. Which would mean our common module would handle jms configuration (jms factory, jms-configuration) and different types of messages will be send over that one queue/topic.
How would can I make sure that product related messages get handled by the "products" module and client related messages get handled by the "clients" module? How can I make sure only one of the "products" modules logic would handle a message if the module was deployed two times? What approach would you recommend or is this one queue/topic "nuts"?
I was myself thinking in the direction of using a topic because of the publ/subsc pattern... , or maybe queue listener acting as publisher in a observer pattern to which product- or client subscribers might subscribe to take over handling the message?
Thanks for your help.
Why using a Topic if you want just one of the "products" modules to handle one message? With Topic you'd have one message - multiple subscribers each getting the message. The Queue ensures only one consumer gets a message (point-to-point), with Topic you'd have one message dispatched to all subscribers.
Regarding the "filtering" of messages, this should be something provider specific. Looking at ActiveMQ docs I see this. So, basically each consumer should get the messages the broker, based on selector, will dispatch. I don't know the specifics, but this would be the first place I would start this investigation.
On the same idea, have a look at this discussion from the Spring forum. It is, indeed, related to Spring Integration, but it's on the same idea of message selection. On the other hand, you could consider adopting Spring Integration in your project: it's kind of an abstraction of integration patterns and fits well with everything message oriented.
Few interesting ideas from that forum post:
JmsTemplate from Spring contains a doReceive method that takes as a parameter a String as message selector
Message selectors are in the JMS spec (scroll down to "Message Properties" section)
Relevant section in the Spring Integration documentation is here

how do we configure multiple pollers to send messages to one transformer

How do i get multiple pollers of same type to route messages to a single transformer .I don't mind having the messages queued before the transformer
Well, I think you just want to reuse a message flow for all your <int-mail:imap-idle-channel-adapter>s. It's just enough to configure them all to the same channel.
Actually there is no difference with classical OOP design, when you inject the same service to different actions, like MVC controller, or JMS listeners.
But here we do exactly the same, but inject a MessageChannel to send results of those entry point to it and don't think what's going on underneath.
Please, read more books about Enterprise Integration Patterns

Resources