How to get JMSMessageId after sending it with an outbound-channel-adapter? - spring-integration

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.

Related

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.

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

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...

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.

Spring Integration Channel Interceptor SOAP Envelope

Is there any way to get the entire SOAP message inside channel interceptor call back methods ? Is there any MessageContext injected by default to any of the callback methods?
The question doesn't sound good. The ChannelInterceptor does not do anything with SOAP. They know only about the channels and messages to pass.
In general Spring Integration is stateless, so no any context injected to the channel interceptor.
Any MessageContext is responsibility of your own application.
One of the approach is a MessageHeaders as I recommend you in your other questions: before sending message to the channel you store something to its headers and than you have access to that object from the channel interceptor methods via provided message.

Resources