spring integration with jms, weblogic, message appears in queue even after message is consumed into channel - jms

I am using spring integration with weblogic jms. my logic is to put the json object in jms queue, and consume it from queue into the channel, validate it and route it based on a particular field. if there is any error, do the fix and put it back into the queue. I have two issues. 1. when the message is consumed into the object, I still can see the object as pending in administrative console of weblogic. 2. After fixing the validation, if put the modified object in the queue, I am getting the original object from queue.
<int-jms:outbound-channel-adapter id="jmsOutbound"
channel="requestChannel" connection-factory="queueConnectionFactory"
destination="inputQueue" />
<int-jms:message-driven-channel-adapter
id="jmsInbound" connection-factory="queueConnectionFactory"
destination="inputQueue" channel="routingChannel" />
if (message.getHeaders().get("documentType").equals("sec"))
routingChannels.add(outboundSecChannel);
else if (message.getHeaders().get("documentType").equals("unds"))
routingChannels.add(outboundFChannel);
else if (message.getHeaders().get("documentType").equals("CH"))
routingChannels.add(outboundAChannel);
else{
routingChannels.add(errorChannel);
}
putting in channel using routing
thanks for your help.

I think you should distinguish the consuming part from producing to the separate threads. I don't tell that you have to switch to the transactions, but at least the simple acknowledge for the consumed message should be done.
Since you tell that you are going to putt the message back to the queue, that's definitely the fact to always acknowledge the consumed message independently of the error fact. So, what I suggest is something like to place a QueueChannel or an ExecutorChannel somewhere after <int-jms:message-driven-channel-adapter> and before <int-jms:outbound-channel-adapter> to let them do their hard work with the WebLogic JMS in their own threads.

Related

Method annotated with Spring Kafka listener is not receiving message if previous message processing is blocked

In my project, I am using Spring Kafka listener to consume messages from Kafka. I have a doubt that if the consume method code gets blocked due to some reason and never returned back, in this case, will this listener be able to receive new messages and proceed further or it will be hanged? In my case, it looks like, Kafka listener also got blocked and not processing further messages, even, another consumer of same group is also not receiving messages.
No; you will not get more records while a thread is blocked, unless the concurrency is > 1 and there are at least that many partitions. Even then, you will receive no more messages for the partition(s) assigned to the blocked consumer.

Spring JMS: How work with `ActiveMQ Advisory Message`

For a Spring Framework app working with ActiveMQ and with/without WebSocket
The requirement is prior to send any message to a Topic a check should be done about Number Of Consumers, if it returns 1 the message can be sent safely. If it returns 0, the message can't be sent.
The clients could be come from websocket and consider there is no durable subscription. Thus if a message is sent, and there are no clients, the message arrives to the Topic and practically is lost (never consumed) and Messages Enqueued increments +1
I already did a research and I have read the following:
JMSTemplate check if topic exists and get subscriber count
Notify ActiveMQ producer if consumer on the destination is down
ActiveMQ get number of consumers listening to a topic from java
Detect change in Consumers of an ActiveMQ topic
Practically all is based on Advisory Message. I already have read:
Advisory Message
Handling Advisory Messages
Apache ActiveMQ Advisory Example
I understand that if exists a Topic named abc.xyz then ActiveMQ creates ActiveMQ.Advisory.Consumer.Topic.abc.xyz, until here I am ok with this pattern. I can confirm this approach through ActiveMQ Web Console
What is confuse for me is that practically all the examples available from the previous links works around creating a Session and uses mostly the onMessage method. For the latter I know it works how a listener.
Question 01: Thus who is expected to call that ActiveMQ.Advisory.Consumer.Topic.abc.xyz? It to trigger that onMessage method? That is my confusion.
What I need is work with the Spring Framework API (The app is already working and running with a CachingConnectionFactory, thus a Connection can be retrieved and other #Beans about infrastructure about ActiveMQ) and get access to that ActiveMQ.Advisory.Consumer.Topic.abc.xyz destination and retrieve the Number Of Consumers value.
Note: even when exists ActiveMQTopic declared with #Bean and is possible to retrieve that Destination for some #Component, sadly the API does not offer a method such getConsumers().
Question 02: How can be accomplished this?
I am assuming the JMS API for 2.0.x could help perhaps in someway.

Where discarded messages are going in SpringIntegration?

We have a discard channel for some filters and aggregators, but we have seen that discard channel is a regular direct channel.
So, where those discarded messages go ? to DLQ ?
And also, do they live forever there ? Because we are struggling with memory consumption and we would like those messages to be deleted (garbage collected ) as soon they arrive to the DLQ.
Even if Spring Integration is based on the Messaging concepts, it is just a tool to build integration solutions. It isn't a Broker and therefore doesn't provide out-of-the-box state management like queue persistence and DLQ.
You are correct, the discardChannel is just a MessageChannel and you can inject any implementation there and do some desired logic in the discard flow on that channel. Sending to DLQ is already your particular use-case and you really should do that manually. There is nothing specific for Spring Integration on that discard channel. And if it is just regular QueueChannel without any poller on the matter, you really end up once with the OOM because messages are stored in the memory forever.

JMS with Spring Integration or Spring Batch

Our project is to integrate two applications, using the REST API of each and using JMS (to provide asynchronous nature). Application-1 writes the message on the queue. The next step is to read the message from the queue, process it, and send it to application2.
I have two questions:
Should we use one more queue for storing messages after processing and before sending them to application2?
Should we use spring batch or spring integration to read/process the data?
Or you don't show the whole premise, or you really try to overhead your app. If there is just need to read messages from the queue, there is just enough to use Spring JMS directly... From other side with the Spring Integration and its Adapters power you can just process messes from the <int-jms:message-driven-channel-adapter> to the <int-http:outbound-channel-adapter>.
Don't see reason to store message somewhere else in the reading and sending process. Just because with some exception here you just rollback your message to the JMS queue back.

How do I hold a jms message in queue until it is saved?

I just started using Weblogic JMS. I was able to send messages to the queue and pull them off with a messagebean. Now I want to save the message to a database.
So my question is, how do I tell JMS not to delete the message from the queue until I have successfully written the message to the database?
Thanks
I was able to send messages to the queue and pull them off with a
messagebean.
I suppose you are talking about message-driven bean (MDB)?
So my question is, how do I tell JMS not to delete the message from
the queue until I have successfully written the message to the
database?
MDBs are part of implicit container-managed transaction and the message will not be removed as long as your transaction hasn't commited (that is, as long as your onMessage method hasn't reached its end).
In case of rollback (i.e. you throw an exception or call context.setRollbackOnly() on the MessageDrivenContext), message will be redelivered. You can avoid this behaviour by making transaction bean-managed or using #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED), but in your situation that should not be the case. Stick with default configuration and everything should work as you wish.

Resources