There are multiple servers that are listening to activemq. The chain is configured to make the http [outbound gateway] call. Suppose one of the server picks up the message and in-between if the http call fails for some reason. The message should be put back to the queue, so that another server can pick up the message and process. Can this be achieved using Spring Integration. I read lot on Transaction, however unable to find workable way.
Yes, simply set acknowledge="transacted" on the <int-jms:message-driven-channel-adapter/> and, as long as you use only direct channels (no <queue/> on the channel or task-executor on the channel's dispatcher) then any failure will cause the message to roll back.
Related
I'm using Camel with JMS and Spring Boot and would like to build a route for next scenario:
User 1 (MQTT client) sends a message (topic) to ActiveMQ Artemis.
Camel (by using from) catch that message and print it out with a help of log.
Thing I would like to do is - create a new thread (asynchronous) for caught message. Send that message from Camel to microservice (python program) that should take message and insert some extra strings, and then send changed message back to Camel and ActiveMQ.
On the end, from ActiveMQ changed message will be sent to User 2.
Can you give me some directions or route examples of how to do something like that?
So, key points are to create new thread for every message and create route to and back from that microservice.
The route could look like this
from("jms:queue:inputQueue")
.log("${body}")
.to("http://oldhost")
.to("jms:queue:outputQueue")
Some notes:
You can call a downstream HTTP endpoint with .to(). The current message body is used as request body. The response of the service overwrites the message body.
I don't know why you want to create a new thread for a synchronous call. You can leverage parallel processing by consuming multiple messages from Artemis in parallel with multiple consumers. Like this, every message is processed in its own thread. If your motivation is resilience, there is also a Circuit Breaker EIP in Camel
If you use Camel 2.x, use the HTTP4 Component ("http4://") to use the newer HTTP client lib. In Camel 3.x the old one was dropped and the new one is simply called HTTP component
Using Spring boot #RabbitListener, we are able to process the AMQP messages.
Whenever a message sent to queue its immediately publish to destination exchange.
Using #RabbitListener we are able to process the message immediately.
But we need to process the message only between specific timings example 1AM to 6AM.
How to achieve that ?
First of all you can take a look into Delayed Exchange feature of RabbitMQ: https://docs.spring.io/spring-amqp/docs/current/reference/html/#delayed-message-exchange
So, this way on the producer side you should determine how long the message should be delayed before it is routed to the main exchange for the actual consuming afterwards.
Another way is to take a look into Spring Integration and its Delayer component: https://docs.spring.io/spring-integration/docs/5.2.0.BUILD-SNAPSHOT/reference/html/messaging-endpoints.html#delayer
This way you will consume messages from the RabbitMQ, but will delay them in the target application logic.
And another way I see like start()/stop() the listener container for consumption and after according your timing requirements. This way the message is going to stay in the RabbitMQ until you start the listener container: https://docs.spring.io/spring-amqp/docs/current/reference/html/#containerAttributes
So using JMS and ActiveMQ, I can be sure that my message sent from my Spring Boot application using JmsTemplate will reach it's destination application even if that destination application is down at the time I send the message to ActiveMQ. As when the destination application starts up, it grabs the message from the queue. Great!
However.
What happens if my Spring Boot application tries to send a JMS message to a queue on the ActiveMQ server, but the ActiveMQ server is down at that point or the network is down and I get a connection refused exception?
What is the recommended way to make sure my application keeps trying to re-sends the message to ActiveMQ until it is successful? Is this something I have to develop into my application myself? Are there any nifty Spring tools or annotations which do this for me? Any advice on best practice or how I should be handling this scenario?
You can try Spring-Retry. Has lots of fine grain controls for it:
http://www.baeldung.com/spring-retry
https://github.com/spring-projects/spring-retry
If it is critical that you don't lose this message, you will want to save it to some alternative persistent store (e.g. filesystem, local mq server) along with whatever retry code you come up with. But for those occasional network glitches or a very temporary mq shutdown/restart, Spring-Retry alone should do the trick.
Couple of approaches I can think of
1. You can set up another ActiveMq as fallback. In your code you don't have to do anything, just change your broker url from
activemq.broker.url=tcp://amq01.blah.blah.com:61616
to
activemq.broker.url=failover:(tcp://amq01.blah.blah.com:61616,tcp://amq02.blah.blah.com:61616)?randomize=false
The rest is automatically taken care of. i.e. when one of them is down, the messages are sent to other.
Another approach is to send to a internal queue (like seda, direct) when activemq is down and read from there.
Adding failover to the url is one appropriate way.
And another reasonable way is to making sure activemq always online , as activemq has the master-slave mode(http://activemq.apache.org/masterslave.html) to get high availability.
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.
I am new to spring and so not sure if what I intend to do is possible.
I need to create an asynchronous webservice and a worker server (broker), both using the model & controller aspects of spring.
The webservice needs to send it's client's requests on to the broker via JMS and then instantly send a response back to the client indicating the request has been queued.
The broker is intended to remain live, processing messages from multiple webservice instances and sending back the results via an output JMS queue. The reason the broker needs to remain live is because the work to process each webservice message involves calling other webservices, some of which may be asynchronous and which may take a lot of time to process.
Additionally I do not want to spawn multiple instances of the broker as it is designed to handle multiple concurrent messages.
Is it possible to create both the webservice and broker within the same spring project, with both running in a web container such as tomcat or do I need to code them in separate projects, with perhaps the broker as a traditional standalone server rather than a web container servlet?
If so could someone point me in the right direction to creating a stay-alive broker within spring/tomcat.
I understand the webservice and JMS side of things, so do not need any help with that.