How to expose SOAP Web Service using MarshallingWebServiceInboundGateway (with Spring Integration DSL) - spring-integration

I’m struggling to find good examples of Spring Integration using the MarshallingWebServiceInboundGateway
I put together a working sample that uses MarshallingWebServiceInboundGateway to expose an Order service, and when called it consumes an order detail service using the MarshallingWebServiceOutboundGateway
https://github.com/yortch/spring-integration-demo/blob/outboundgateway/services/order-flow/src/main/java/com/demo/integration/order/OrderEndpoint.java
#ServiceActivator(inputChannel= ChannelNames.ORDER_INVOCATION, outputChannel = ChannelNames.ORDER_DETAIL_REQUEST_BUILDER)
OrderRequest getOrder(OrderRequest orderRequest) {
return orderRequest;
}
This is somehow working, however my expectation for the method below is that this should be the signature of the web service method, i.e. return an OrderResponse type. I had this initially working this way when I was manually building the OrderResponse by calling other POJOs, however I can’t figure out how to keep the original web service method signature and internally use Spring Integration for the implementation, i.e via calling a channel to do the transformation and in turn call the order detail service (using MarshallingWebServiceOutboundGateway).
If you know any code examples for doing this, please share. I came across this one, but this is directly building the response (without using Spring Integration channels): https://bitbucket.org/tomask79/spring-boot-webservice-integration/src/master/

Sounds like some misunderstanding what is Spring Integration flow and how its endpoints work.
Three first class citizens in Spring Integration: Message, Channel, Endpoint
Endpoints are connected via channels
Endpoints consume messages from their input channels
Endpoints may produce messages as a result of their calculation into the output channels.
So, in your case you want to expose a SOAP service which is going to call internally another SOAP service.
You have started properly with the MarshallingWebServiceInboundGateway. This one, I guess, produces into its channel an OrderRequest object. It expects an OrderResponse in its replyChannel (explicit or temporary in headers). I'm not sure what your getOrder() does, but if there is yet a transformer and MarshallingWebServiceOutboundGateway, you need to consider to connect them all into the flow. So, I think that a result of your service, should go to the channel which is an input for the transformer. An output of this transformer should go to the MarshallingWebServiceOutboundGateway. And result of this gateway may go to some other transformer to build an OrderResponse which may just go into the reply channel of the MarshallingWebServiceInboundGateway.
If that's not what you expect as an explanation, I then will request you to rephrase your question...

Related

Data Aggregator/composition service in Microservices

I am developing an application where there is a dashboard for data insights.
The backend is a set of microservices written in NodeJS express framework, with MySQL backend. The pattern used is the Database-Per-Service pattern, with a message broker in between.
The problem I am facing is, that I have this dashboard that derives data from multiple backend services(Different databases altogether, some are sql, some are nosql and some from graphDB)
I want to avoid multiple queries between front end and backend for this screen. However, I want to avoid a single point of failure as well. I have come up with the following solutions.
Use an API gateway aggregator/composition that makes multiple calls to backend services on behalf of a single frontend request, and then compose all the responses together and send it to the client. However, scaling even one server would require scaling of the gateway itself. Also, it makes the gateway a single point of contact.
Create a facade service, maybe called dashboard service, that issues calls to multiple services in the backend and then composes the responses together and sends a single payload back to the server. However, this creates a synchronous dependency.
I favor approach 2. However, I have a question there as well. Since the services are written in nodeJs, is there a way to enforce time-bound SLAs for each service, and if the service doesn't respond to the facade aggregator, the client shall be returned partial, or cached data? Is there any mechanism for the same?
GraphQL has been designed for this.
You start by defining a global GraphQL schema that covers all the schemas of your microservices. Then you implement the fetchers, that will "populate" the response by querying the appropriate microservices. You can start several instances to do not have a single point of failure. You can return partial responses if you have a timeout (your answer will incluse resolver errors). GraphQL knows how to manage cache.
Honestly, it is a bit confusing at first, but once you got it, it is really simple to extend the schema and include new microservices into it.
I can’t answer on node’s technical implementation but indeed the second approach allows to model the query calls to remote services in a way that the answer is supposed to be received within some time boundary.
It depends on the way you interconnect between the services. The easiest approach is to spawn an http request from the aggregator service to the service that actually bring the data.
This http request can be set in a way that it won’t wait longer than X seconds for response. So you spawn multiple http requests to different services simultaneously and wait for response. I come from the java world, where these settings can be set at the level of http client making those connections, I’m sure node ecosystem has something similar…
If you prefer an asynchronous style of communication between the services, the situation is somewhat more complicated. In this case you can design some kind of ‘transactionId’ in the message protocol. So the requests from the aggregator service might include such a ‘transactionId’ (UUID might work) and “demand” that the answer will include just the same transactionId. Now the sends when sent the messages should wait for the response for the certain amount of time and then “quit waiting” after X seconds/milliseconds. All the responses that might come after that time will be discarded because no one is expected to handle them at the aggregator side.
BTW this “aggregator” approach also good / simple from the front end approach because it doesn’t have to deal with many requests to the backend as in the gateway approach, but only with one request. So I completely agree that the aggregator approach is better here.

Difference between Spring Inbound channel adapters and application event listing message producers

I am working on a POC using Spring Integration and STOMP. The initial POC is successful.
I followed the adapters configuration mentioned in https://docs.spring.io/spring-integration/reference/html/stomp.html#stomp
In my POC, I did not include the last two #Bean definitions from the above link.
Inbound Channel Adapter and Message Handlers were sufficient to handle the incoming messages.
Now, my question is:
What is the difference between Inbound channel adapters and application event listing message producers?
Is ApplicationListener used when we follow DSL as mentioned in an example here?
Thanks,
Mahesh
Well, as you noticed in that Spring Integration documentation about STOMP support there is some bunch of ApplicationEvents emitted by STOMP Channel Adapters. You indeed can handle them using regular ApplicationListener (#EventListener) if your logic for handling those events is pretty much simple and doesn't need further distribution. But if your logic is much complicated and you may need store an even (or its part) in some database, or send via email, do that in parallel after some aggregtion, etc., then indeed that ApplicationEventListeningMessageProducer is much better solution when we have Spring Integration on board already.
However if you talk about a StompInboundChannelAdapter nature and relationship with those mentioned events, you need to take a look into the StompIntegrationEvent implementations. You quickly realize that there is no events for payload in the STOMP frame. So, that is what is done really by the StompInboundChannelAdapter - it produces messages based on the body from STOMP frame.
All the mentioned events emitted fro that channel adapter are more about that adapter state sharing for possible management in your application.

what is the difference between int:gatway vs int-ws:inbound-gatway or int-ws:outbound-gatway in spring integration

I have seen <int:gateway ..../> configuration in some place and <int-jms:inbound-gateway ../> or <int-ws:outbound-gateway ../> in other place or together in spring integration configuration. I am not able to find out the main differences between them.
I got that gatway's are two way connection. then
As the int:gatway can be used both directional communication, can't we use it in place of other inbound/outbound gatway? - I beleive the answer will be they are used for specific type of request like WS or JMS to do specific task. But still I am confused if the same can be done using the int:gatway.
Also What is the use of int:gatway if there are specific type of gatway present for all different services ( like JMS or WS).
Consider an <int:gateway/> as a gateway from legacy java code into a messaging flow.
public interface MyGate {
Bar fooToBar(Foo foo);
}
Then, in legacy java code (e.g. a REST Controller), you "send" a Foo which is wrapped in a message and the flow returns a Bar in the reply Payload and the framework unwraps it for you.
The client code does not know it was interacting with a messaging system.
The end of the flow, for example, might call a <ws:outbound-gateway/>.
So, the gateway abstracts away from the messaging from the client's perspective.

Spring integration - Difference between AmqpOutboundEndpoint and RabbitTemplate

i am trying to write my first AMQP publisher via spring integration using an instance of AmqpOutboundEndpoint.
I don't understand what is the difference between RabbitTemplate and AmqpOutboundEndPoint since AmqpOutboundEndpoint is using an instance of RabbitTemplate.
I would like to use an AMQP gateway to separate 2 different components of my application (Business component and Integration component)
Is it valid to use an AqmpOutboundEndPoint to publish a message when i need to switch the routing key according to the published message type? All examples i found in internet are using a hardcoded routing key for the AMQP gateway.
Thanks
Well, welcome to the Enterprise Integration Patterns
So, first of all you are right, AmqpOutboundEndpoint is really fully based on the RabbitTemplate because it is a good implementation for sending messages over AMQP.
On the other hand the endpoint is a Channel Adapter to receive messages via internal Integration channel.
So, you have to decide for yourself if you really need the whole Integration solution or just sending to the AMQP from your own code is enough.
That endpoint allows you to determine routingKey at runtime against requestMessage using SpEL.
See documentation on the matter: http://docs.spring.io/spring-integration/docs/4.3.11.RELEASE/reference/html/amqp.html#amqp-inbound-ack

Send data to a Channel from a callback method (Spring Integration)

I have a method that is called as a callback from some communication library when data are received.
Using Spring Integration, I would like to send data to a specific Channel that will be later picked up by some Sender and some Database Recorder. These two may work in parallel. How could I do it?
I prefer not to use XML for anything.
These two may work in parallel.
For this purpose Spring Integration provides PublishSubscribeChannel. With its executor option you really can make subscribers working in parallel.
I would like to send data to a specific Channel
So, just do that from that callback method.
You can consider to use Messaging Gateway for dependency injection instead of direct channel injection for sending.
That way you will call the gateway's method from that callback and the data will be send to predefined PublishSubscribeChannel channel for distribution between its subscribers.
how do I create that "existing channel"
That's all about Spring and its inversion of control implementation.
You may consider to consult existing Spring Integration Samples for ideas.

Resources