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.
Related
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.
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...
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.
When dealing with an enterprise integration flow in Spring-integration, is it more "proper" to handle concerns such as transmission validation and state tracking in Channel Interceptors, or endpoints like Service Activators and Filters? Or is that purely a matter of style?
Generally it's just style but most people prefer to limit interceptors for simple stuff like wiretapping, logging, etc, or something you want to apply globally to multiple channels via a global interceptor that matches on channel name patterns.
But, it's not unusual to do validation in an interceptor.
Not sure what you mean by "state tracking" but, generally, that's handled in message headers (when you want to pass state from one endpoint to another).
I am sending a JMS message with the outbound channel adapter like this:
<intjms:outbound-channel-adapter
destination-name="MY.QUEUE"
connection-factory="myConnectionFactory"
channel="mySender"/>
After this I need to know the JMS Message Id. How can I get it?
There is a way to do it in a custom JmsTemplate I could provide in the adapter, but maybe there is a simpler solution for this problem.
I can not use the gateway because there is no response.
You can send JMS Message as a payload of Spring Integration Message to that adapter. And use its getJMSMessageID() after successful sending.
UPDATE
But this means I can not use the convencience of the JmsTemplate and have to deal with javax.jms.Connection and javax.jms.Session on my own to be able to create a javax.jms.Message, correct?
Well, no one forbid you to use even JmsTemplate directly as a reference from the general <service-activator>. The <outbound-channel-adapter> is one-way by the goal. So it is really not intended to return anything. Your corner case really requires something to do. And that is the javax.jms.Session hooks and tricks to create a JMS Message to be able to retrieve its ID afterwards. There is a ThreadLocal hole over the custom JmsHeaderMapper and the message access from its fromHeaders() implementation, but I think that for this case it would be better to use JmsTemplate directly.