1

I want to implement spring integration for my current requirement. The requirement is as follows -

  1. I have a service and I need to call 3 services parallelly from it.
  2. All the 3 calls are independent calls.
  3. Out of the 3 calls 2 calls are HTTP calls(1 GET, 1 POST) and another is a native method call.
  4. Once I make a POST call to my service then internally the three services should be called parallelly.
  5. The request body that I'm using to do the POST call should be used as an input for the other 3 calls but I need to change the input JSONs as per need. The exact input I'm not going to be using for the other 3 services but I'll be modifying the input as per my need.
  6. In the end once I get the response from the 3 mentioned services then I'll use a method to aggregate the JSONs and will use that Aggregated and transformed JSON as an input for another new service's input.

Kindly suggest me a correct pattern and with a little elaboration if possible as I'm totally new to Spring Integration.

Arun Sai Mustyala
  • 1,736
  • 1
  • 11
  • 27

1 Answers1

1

So, to make a 3 parallel calls for the same payload and then aggregate their result, you need to look into a Scatter-Gather pattern: https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#scatter-gather.

According to your description, you have to use a configuration based on the PublishSubscribeChannel (Auction) with a TaskExecutor provided. The subscribers to this channel could be plain HTTP message handler, service activator or even transformers to manipulate a payload before target service call.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks @Artem. I have one more doubt. If I want to manipulate the payloads then I'm not able to do. Actually if I'm passing a POJO to the gateway and it's going to all the parallel services and if I'm trying to manipulate the payload it's saying I'm not allowed to manipulate that POJO. But on contrary if I'm passing a JSON string or JSON Object then I can convert that JSON into Map and can manipulate that map and send as a payload. But in real scenario I need to send a Java Object through the gateway, and I need to modify the input for one or two services. Kindly suggest me a way. – Somnath Mukherjee Jun 23 '22 at 16:19
  • Well, that's really not good. You send the same object to different threads, of course it is expected that modifying this object in one thread would reflect it in others. `Race condition` in other words. If you still want to deal with POJOs, consider to have them as `java.lang.Cloneable`. The first transformer in all your sub-flows should call a `clone()` of that incomming POJO and only after that you ca modify it in the context of the current sub-flow. – Artem Bilan Jun 23 '22 at 16:25
  • Thanks @Artem, actually for the two http calls I need to use the input POJO that's coming from the gateway at the same time I need to add and modify few fields on that payload then I need to send as request body to the calls. The payload is being scattered to the different parallel services through different channels right. And also in parallel processing different threads are being used right not the same thread. So kindly help me understand what is the problem here – Somnath Mukherjee Jun 23 '22 at 16:43
  • Your last comment is too complicated and feels like you ask the same as in the previous one which I have answered. Not sure why you ask the same again... The memory in your machine is single. If you create a mutable object, it is placed in some memory slot. It doesn't matter which thread deals with this object, its actions affect the same same memory slot. So, when other threads deals with this object, they take the data from the same memory slot. As long as you need the same data and modify it some how, but only in the context of the current thread and service call, you need that `clone()`. – Artem Bilan Jun 23 '22 at 16:52
  • It does not happen with String just because it is immutable object: as long as we change it, a new object is created. Therefore you don't see a race condition problem with JSON converted to a `Map`. – Artem Bilan Jun 23 '22 at 16:53
  • This has nothing to do with Spring Integration. This is a one of the fundamental concepts of the Java Concurrency: https://jenkov.com/tutorials/java-concurrency/thread-safety-and-immutability.html – Artem Bilan Jun 23 '22 at 16:55
  • Thanks @Artem. Sorry if the question felt repetitive to you. I'll clone the object and I'll use that. You said it's not good so just wanted to know if there's some other pattern that I should use here. – Somnath Mukherjee Jun 23 '22 at 17:01
  • The pattern is good, just not good to share the same object if you are going to mutate it. Well, technically you definitely may just start with immutable objects model from the beginning, as we do with the `Message` object by itself: every single endpoint creates a new `Message` to not effect others. As far as I remember even Joshua Bloch recommends to design with immutable objects in the mind: https://medium.com/javarevisited/effective-java-by-joshua-bloch-a-must-read-book-for-java-developers-5292197a279e – Artem Bilan Jun 23 '22 at 17:20
  • Okay @Artem. Sorry if I'm asking very basic question but when u say that every endpoint creates a new message what did u mean? Actually I want that every endpoint should receive new message as request body to make http call. – Somnath Mukherjee Jun 24 '22 at 06:30
  • The message is a fundamental entity of Spring Integration. Typically target project should not care about message API and just deal with the payload. I doubt that your HTTP service really expect from you a whole `Message` as a request not just some payload. I mean that message is immutable even if it’s content is similar to the previous , but it is safe to mutate it: no any other parallel process will be affected . Same I suggest for your POJO in the payload and to achieve the immutability we can use cloning feature in Java. I think your question go already beyond the original request. Ask new – Artem Bilan Jun 24 '22 at 12:44