Spring-boot app displaying JMS messages on WebPage via WebSocket - websocket

I need a simple web-app in spring-boot that listens for messages on a JMS queue and when arriving it should appear on a webpage via WebSocket.
I have searched for examples and found several individual; either WebSocket or JMS which I have tested on their own but have not succeeded in wiring it together.
I have searched for an example but not found any and in my mind I think it should be pretty easy since it's a very basic requirement.
Do you know about any example with JMS and HTML display via WebSocket that you can share or can give some hints or help for me to solve it?

The Spring Integration comes to the rescue.
You can write <int-jms:message-driven-channel-adapter> to read messages from JMS queue and forward them to the <int-websocket:outbound-channel-adapter>. Where the last one just sends messages to the connected WebSocket session(s).
See these Spring Integration samples on the matter:
https://github.com/spring-projects/spring-integration-samples/tree/master/basic/jms
https://github.com/spring-projects/spring-integration-samples/tree/master/basic/web-sockets
UPDATE
To send the message to all subscribed WebSocket session you should do something like this:
<int:splitter input-channel="enricheMessage" output-channel="sendMessage" apply-sequence="false">
<int-groovy:script>
#serverWebSocketContainer.sessions.keySet().collect {
org.springframework.integration.support.MessageBuilder.withPayload(payload)
.copyHeaders(headers)
.setHeader('simpSessionId', it)
.build()
}
</int-groovy:script>
</int:splitter>
With this Groovy script I retrieve session ids from the serverWebSocketContainer (all those connected clients), iterate over them to build messages to send them over their websocket. And split finally, to send to the <int-websocket:outbound-channel-adapter> one by one.

Related

Difference between SockJS and ActiveMQ/RabbitMQ

I have recently developed a simple messaging application with Spring Boot and Spring Security. The application takes in 2 users - user A and user B. Once, user A performs a specific task a notification is sent to user B. Currently I am doing this by adding a Spring Messaging dependency and SockJS and it works great.
Here is where I am confused and hoping to receive some guidance. I realize there are many tutorials that speak about RabbitMQ and ActiveMQ. From what I understand, they are message brokers. May I ask what is the difference between SockJS and RabbitMQ/ActiveMQ? And do I need RabbitMQ/ActiveMQ in my current application together with SockJS?
SockJS is JavaScript based WebSocket client library that runs in a browser. It can be used to send messages to or receive messages from a broker.
Both RabbitMQ and ActiveMQ are message brokers, examples of message-oriented middleware. They both support WebSocket clients which use a messaging protocol (e.g. STOMP or AMQP). Brokers receive messages from and dispatch messages to clients.
You haven't really provided enough information to determine whether or not you actually need to use either RabbitMQ or ActiveMQ in your current application given that it's already working as it is.

Get the stomp client used internally by Spring Broker Relay

I'm trying to setup a broker relay in Spring with RabbitMQ being the broker. Things work as intended when all events originate from my browser, however, sometimes I have events generated on the server side dynamically. I want to send these too to RabbitMQ to take advantage of things like durable topics or TTL for messages. As far as my understanding goes, using SimpleMessagingTemplate.convertAndSend() and convertAndSendToUser both end up sending the event to the browser instead of broker.
As of now, I'm trying to create a new stomp client to rabbitmq and send events through that. But I can't help feel it to be a bit hacky. Is there a way to get a hold on the stomp client used by Spring and forward my messages easily? Or am I missing something here?
Any help is appreciated, thanks!
Took a while but turns out you don't need to get a hold of the internal stomp client (it's actually an internal TcpClient from Reactor Netty though) or anything like that. Following are the steps you need to do when you want a little bit of customization:
Spring uses #EnableWebSocketMessageBroker to configure the broker or you can extend DelegatingWebSocketMessageBrokerConfiguration. I ended up extending it, it makes little difference though.
In configureMessageBroker(MessageBrokerRegistry registry), use the registry and enable stomp relay and the important part: for the registry in the same method, add ChannelInterceptors. You can get the stomp command and process it as required. The idea is identical to Spring Intercetpors. Add the headers needed inside that.
final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
StompCommand command = headerAccessor.getCommand();
Then finally, recreate the message for sending.
MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders());
Lastly, you can test if things are actually going to RabbitMQ management console to observe if messages are actually being sent.

How should you handle the retry of sending a JMS message from your application to ActiveMQ if the ActiveMQ server is down?

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.

Spring AMQP request-response across 2 web applications

I would like an example/sample code of 2 simple spring web/java applications where I need to send messages from the 1 and the 2nd application must receive the messages and respond back. I looked at few that had request/response in the same application but unable to separate them. I'm new to Amqp & RabbitMQ. Any help or direction would be greatly appreciated.
Thanks
See the stock trading sample, request reply messaging (client side) and MessageListenerAdapter which automatically handles request/reply on the server side (where your service is a POJO).

JMS request/reply pattern in grails

I am creating a grails web app which makes use of JMS messaging. I have installed the JMS plugin for grails and using activemq as the messaging provider. I want to implement a request/response pattern in grails.
I was successfully able to send a message to the queue using the
sendQueueJMSMessage("queueName",Map message) from a controller.
I then created a service which contains the onMessage() method that listens to the "queueName" as stated above.
The onMessage() method does some processing and successfully sends an email to the user.
The above scenario has been implemented successfully.
Now, I would like to receive a response from this onMessage() method.
Lets say I want to implement the below scenario.
The request is added to the queue and waits for a response. I looked around but I couldnt find any help.
Please give me a lead on this. I really appreciate it.
Spring JMS adds support for auto replies, which the Grails plugin supports. See: http://gpc.github.com/grails-jms/docs/manual/guide/5.%20Receiving%20Messages.html#5.3%20Listener%20Return%20Values
Here is a test exercising this stuff: https://github.com/gpc/grails-jms/blob/master/test/integration/grails/plugin/jms/test/reply/ReplyingListenerServiceSpec.groovy#L12
The other option is to just send another message from your first message receiving method.
you did not provide much to work with here so the my suggestion is to take a look at the samples in the Grails JMS Plugin - Reference Documentation: 5. Receiving Messages, or provide some code

Resources