Feeding one publish subscribe channel from two JMS Inboundchannel adapters? - spring

I just want to ask whether following SI configuration is OK from your point of view....
Let's have following publish subscribe channel with some subscribers...
<int:publish-subscribe-channel id="channelName" ignore-failures="false"/>
and feed it from two JMS message driven adapters:
<jms:message-driven-channel-adapter channel="channelName"
destination="JMSQueue1"
connection-factory="JMSQueue1CF1"
concurrent-consumers="1"
max-concurrent-consumers="10"
error-channel="errorChannel"
acknowledge="transacted"
task-executor="mySimpleTaskExecutor1"/>
<jms:message-driven-channel-adapter channel="channelName"
destination="JMSQueue2"
connection-factory="JMSQueue2CF2"
concurrent-consumers="1"
max-concurrent-consumers="10"
error-channel="errorChannel"
acknowledge="transacted"
task-executor="mySimpleTaskExecutor2"/>
If both of these JMS Inbound channel adapters are going to have same output channel ("channelName"), are they going to interfere their processing somehow?
My guess is that every message from both queues is going to be consumed in the different thread so processing of message from JMSQueue1 won't be waiting on message from JMSQueue2.
True or not true?

There are no issues with having multiple producers on the same channel; the threads won't "interfere" with each other.
It's exactly the same as having concurrency in the message-driven adapter (which you have).

Related

Spring integration jms:message-driven-channel-adapter message is not deleted from Qpid queue

I have a spring integration project. Which reads message from the qpid queue and starts some processing. To mu understanding once message is read it should be cleared from the queue.
But Even after the processing is complete. The message stays in queue in acquired state. Even if i clear the queue and drop new message the message is not picked up by the adapter.
Following is my configuration.
<jms:message-driven-channel-adapter destination-name="incoming.queue" channel="transform-jms-message-channel" connection-factory="qpidConnectionFactory"
concurrent-consumers="1" error-channel="errorChannel" acknowledge="transacted" />
<int:transformer input-channel="transform-jms-message-channel" id="reportRequestTransformer" ref="reportRequestMessageTransformer" method="transform"
output-channel="validate-parameters-channel"/>
Any help is appreciated.

Inserting messages in a JMS queue and then sending back the acknowledgement using Spring Integration

I have a service which receives xml messages via an http inbound adapter and then transforms them into text that becomes the content of an email that gets sent out.
I now need to first insert these messages into a JMS queue and send the acknowledgement back as a 200 ok after the message is inserted into the Q and then carry-on with the rest of the processing.
<int-http:inbound-channel-adapter channel="inputChannel"
id="httpInbound"
auto-startup="true"
request-payload-type="java.lang.String"
path="/message"
supported-methods="POST"
error-channel="logger" >
<int-http:request-mapping consumes="application/xml" />
</int-http:inbound-channel-adapter>
<int:chain id="chain" input-channel="inputChannel" >
<int:service-activator ref="mailTransformerBean" method="transform" />
</int:chain>
The service-activator takes care of the processing to convert the xml into an email.
Before that I need to incorporate a JMS Queue into which the received messsages will be inserted and then the acknowledgement is sent back. This is so as to retain the messages and retry in case of a failure of the service.
I would like to set this up as a Transaction with the JMS queue as a endpoint.
How do i approach this?
If you are seeking something like a in-process persistence storage, take a look, please, into the SubscribableJmsChannel :
The channel in the above example will behave much like a normal <channel/> element from the main Spring Integration namespace. It can be referenced by both "input-channel" and "output-channel" attributes of any endpoint. The difference is that this channel is backed by a JMS Queue instance named "exampleQueue".

How to restart the message consumer in Spring Integration?

My consumer, e.g. service activator that is consuming messages coming from ActiveMQ fromChannel should be restarted when exception occurs or ActiveMQ fails. How to do it for the following spring integration context ?
<!-- RECEIVER. message driven adapter -> jmsInChannel -> activator. -->
<si:channel id="fromChannel"/>
<int-jms:message-driven-channel-adapter id="messageDrivenAdapter"
channel="fromChannel" destination="forward" connection-factory="connectionFactory"
max-concurrent-consumers="2" auto-startup="true" acknowledge="auto" extract-payload="false" />
<si:service-activator id ="activator"
input-channel="fromChannel"
ref="messageService"
method="process"/>
<bean id="messageService" class="com.ucware.ucpo.forward.jms.MessageService"/>
My first idea was to use Retry Advice and add to a service but am not sure if this a right solution for unhandled exceptions. I also would like the receiver to restart if the ActiveMQ server is down.
The listener container within the message-driven-channel-adapter will automatically keep trying to reconnect when it loses connectivity to the broker.
If you set `acknowledge="transacted"' the message will be rolled back on an exception and the broker will resubmit it.
A stateful retry advice would allow you to give up and take some other action after some number of retries (but you can also configure that into ActiveMQ itself where it will send the message to a DLQ after some number of delivery attempts).
Reading your post I instantly thought of this video. Which gives a good insight on how to monitor and control SI application through itself.
Additionally you should have a look at ApplicationEvent documentation of SI.
Glueing that all together you could monitor the JMS message adapter with JMX and stop and restart it through sending an ApplicationEvent on issues. Regarding catching exceptions it depends on what Exceptions you actually want to handle. I'd create an errorChannel that receives exceptions being thrown by components and create a new service that restarts these components after receiving errors.
Following your idea leveraging Spring Retry's capabilites in SI.

Spring Integration <inbound-channel-adapter> Rabbit MQ getting disconnected

We are working on a POC to use Spring integration and Rabbit MQ.
We have two modules producer module and consumer module both are runs in different JVMs.
The Producer module listen on a Folder (input folder) as soon as new files arrives, creates a message then push to (incoming.q.in) queue and also move to process folder.
The Consumer module then pickups the messages from the incoming.q.in Queue then process the files them move to complete folder.
Both Producer and Consumer code is working fine but after some ideal item then consumer module is getting disconnecting from Rabbit MQ. We see messages in incoming.q.in queue but the consumer is not processing.
When I logged into Rabbit MQ Admin/Management tool “incoming.q.in” consumer list is empty and the message is “... no consumers ...”.
The consumer code
<int-amqp:inbound-channel-adapter channel="inBoundfile" queue-names="incoming.q.in" connection-factory="connectionFactory"
error-channel="error.in">
</int-amqp:inbound-channel-adapter>
<int:header-enricher input-channel="inBoundfile" output-channel="serviceInbound">
<int:header name="FILEID" expression="payload.fileID" />
</int:header-enricher>
<int:service-activator ref="routerService" method="processFile" input-channel="serviceInbound" output-channel="fileHandler.router.in" />
....
I appreciate your help.
Turn on DEBUG logging on the consumer side; you'll see lots of logging and reconnection attempts if/when a connection is lost.

Spring Integration: JMS Exception Handling

Using Spring Integration's own JMS Outbound Channel Adapter that is connected to Websphere MQ v7.1:
<!-- plugging xyz channel into a JMS xyzQueue -->
<channel id="xyzChannel"/>
<jms:outbound-channel-adapter channel="xyzChannel"
destination="xyzQueue"/>
<!-- will listen on all packets matched, and forward them to a xyzChannel -->
<beans:bean id="xyzSender" class="com.custom.XyzSender">
<beans:constructor-arg name="messageChannel" ref="xyzChannel"/>
</beans:bean>
In case MQ broker (its channel) goes down for a split of a second, the exception is logged:
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2537;AMQ9558: The remote channel 'XYZ_CHANNEL' is not currently available ('MQRC_CHANNEL_NOT_AVAILABLE').
From MQ docs these are possible reasons for this error:
The channel is currently in stopped state.
The channel has been stopped by a channel exit.
The queue manager has reached its maximum allowable limit for this channel from this client.
The queue manager has reached its maximum allowable limit for this channel.
The queue manager has reached its maximum allowable limit for all channels.
However Spring Integration seems to eat it exception up, and in a split second after the MQ channel is available again, other messages get processed as nothing happened. Of course it results in a message drop, which is not an expected scenario.
What would be a way to handle this exception? There does not seem to be an error channel attribute on jms:outbound-channel-adapter.

Resources