Unable to get message in priority sequence Spring camel rabbitmq - spring

I am a beginner in using spring camel rabbitmq.
I am able to set message priority in message header by setting it in exchange out headers on the producer side, like this :
exchange.getOut().setHeader("rabbitmq.PRIORITY", 1);
BUT while consuming the messages they dont come in there order of priority. HELP !!
I can see in web interface of rabbitmq that priority header in appropriately set

Please carefully read the "Interaction with consumers" section of this document. You should also search for an answer on the RabbitMQ Users List or post your question there if it has not been asked.

got the issue.
problem was that I was not able to set x-max-priority using camel endpoints.
Need to add it in queueArgsConfigurer option in queue.
To do this we need to implement ArgsConfigurer interface like this :
#Component(value="QueueArgsConfigurer")
public class QueueArgsConfigurer implements ArgsConfigurer {
#Override
public void configurArgs(Map<String, Object> map) {
map.put("x-max-priority", 3);
}
}
And add to queue endpoint queueArgsConfigurer option like this:
queueArgsConfigurer=#QueueArgsConfigurer
Since I am using spring I get the QueueArgsConfigurer by its bean name.

Related

Spring jms listener overwrites id header when converting to Message<Object>

I have a jms message with an attribute named id in the header.
In my listener when this jms message is converted to Message
#JmsListener(id = "cis-listener", destination = "${amiga.service.jms.cis-listener.destination-fqdn}",
containerFactory = "containerFactoryListener")
public void receiveMessage(Message<Object> event) throws UnknownMessageException {
...
this attribute is overwrited with a generated UUID, when the MessageHeaders are instantiated:
protected MessageHeaders(#Nullable Map<String, Object> headers, #Nullable UUID id, #Nullable Long timestamp) {
this.headers = (headers != null ? new HashMap<>(headers) : new HashMap<>());
if (id == null) {
this.headers.put(ID, getIdGenerator().generateId());
}
...
Is there some option to rename the id header attribute i receive in the message to keep the value?
I can access to this attribute by changing the object received by the listener, using the javax.jms.Message but i prefer to use the spring-jms Message implementation.
You can add a custom JmsHeaderMapper to the listener adapter.
set the container factory autoStartup to false.
get the container from the JmdListenerContainerEndpointRegistry (by id).
get the message listener from the container and cast it to AbstractAdaptableMessageListener.
set the custom header mapper.
start the container.
Your mapper should map your external id header to something else. id is reserved in spring-messaging. It can be a subclass of SimpleJmsHeaderMapper.
Hello Gary Russell first of all thank you for your responses and your help, it's a very big pleasure to be answered by one of the developers of the part of spring i'm having doubts.
In your solution i don't like to be forced to disable the autoStartup. In our project we don't force the autoStartup but if we need to this property will be ignored because we force the start after the custom header mapper is set. We should to define other property and check its value before the container start. It's a little bit odd to change the meaning of the container autostartup property.
I'm also having doubts about the MessageHeader definition. I consider the Message and MessageHeader classes as wrappers / decorators of the jms Message class. I understand that those two classes are defined to make easier the instantiation and access to message and header properties.
That's why i don't get why the timestamp and id values are overwriten. I think that a wrapper shouldn't add this kind of logic, especially when is not so rare to receive an id attribute in the header of the message. If spring needs an id to work with the message maybe, before the creation, should check if an attribute id exists and use other name instead id, the same with timestamp.
Those two attribute names are reserved by spring but the jms deffinition doesn't disallow its use.
I don't like the solution but i think that we will be forced to change our listener to receive a jms message, even though it's more difficult to instantiate the messages to testing it, I think it is a better option.
Thank you again for your time and your help.

Spring Boot - Camel - Tracking an exchange all the way through

We are trying to setup a very simple auditing database table for a very complex Spring Boot, Camel application with many routes (mostly internal routes using seda://)...the idea being we record in the database table each route's processing outcome. Then when issues arise we can login to the database, query the table and pinpoint exactly where the issue happened. I thought I could just use the exchange-id as the unique tracking identifier, but quickly learned that all the seda:// routes make new exchanges, or at least that's what I'm seeing (camel version 2.24.3). Frankly, I don't care what we use for the unique identifier...I can generate a UUID easily enough and the use the exchange.setProperty("id-unique", UUID).
I did manage to get something to work using the exchange.setProperty("id-exchange", exchange.getExchangeId()) and have it persist the unique identifier thru the routes...(I did read that certain pre-defined route prefixes such as jms:// will not persist exchange properties though). The thought being, the very first Processor places the exchangeId (unique-id) on the exchange properties, my tracking logic is in a processor that I can include as part of the Route's definition :
#Override
public void configure() throws Exception {
// EVENTS : Collect statistics from Camel events
this.getContext().getManagementStrategy().addEventNotifier(this.camelEventNotifier);
// INITIAL : ${body} exchange coming from a simple URL endpoint
// POST request with an XML Message...simulates an MQ
// message from Central MQ. The Web/UI service places the
// message onto the camel route using producerTemplate.
from("direct:" + Globals.ROUTEID_LBR_INTAKE_MQ)
.routeId(Globals.ROUTEID_LBR_INTAKE_MQ)
.description("Loss Backup Reports MQ XML inbound messages")
.autoStartup(false)
.process(processor)
.process(getTrackingProcessor())
.to("seda:" + Globals.ROUTEID_LBR_VALIDATION)
.end();
}
This Proof-of-Concept (POC) allowed me to at least get things tracking like we want...note multiple rows with the same unique identifier :
ID_ROW ID_EXCHANGE PROCESS_GROUP PROCESS_STEP RESULTS_STEP RESULTS_MESSAGE
1 ID-LIBP45P-322256M-1603188596161-4-6 Loss Backup Reports lbr-intake-mq add lbr-intake-mq
2 ID-LIBP45P-322256M-1603188596161-4-6 Loss Backup Reports lbr-validation add lbr-intake-mq
Thing is, this POC is proving to be rigid and difficult to record outcomes such as SUCCESS versus EXCEPTION.
My question is, has anyone done anything like this? And if so, how was it implemented? Or is there a fancy way in Camel to handle this that I just couldn't find on the web?
My other ideas were :
Set an old fashion Abstract TrackerProcessor class that all my tracked Processors extend. Then just have a handful of methods in there to create, update, etc... Each processor then just calls inherited methods to create and manage the audit entries. The advantage here being the exchange is readily available with all the data involved to store in the database table.
#Component
public abstract class ProcessorAbstractTracker implements Processor {
#Override
abstract public void process(Exchange exchange) throws Exception;
public void createTracker ( Exchange exchange ) {
}
public void updateTracker ( Exchange exchange, String theResultsMessage, String theResultsStep ) {
}
}
Set an #Autowired Bean that every tracked Camel Processor wires in and put the tracking logic in the bean. This seems to be simple and clean. My only concern/question here is how to scope the bean (maybe prototype)...since there would be many routes utilizing the bean concurrently, is there any chance we get mixed processing values...
#Autowired
ProcessorTracker tracker;
Other ideas?
tia, adym

How to write webSockets for Rest calls in Spring-boot?

I'm new to web socket programming. I have more than 10 methods annotated with #GetMapping, where the returned data is read from a MySQL database.
Can anyone help me to know how to write WebSockets.
My WebRestController.java looks like the below:
#CrossOrigin(origins = "http://localhost:4200", allowedHeaders="*")
#RestController
#RequestMapping("/api")
public class WebRestController {
#GetMapping("/summary")
public String Summary() { /* ... */}
#GetMapping("/erday")
public String Erday(String erday) { /* ... */}
#GetMapping("/count")
public String Count(#RequestParam Map<String,String> queryParam,
String date, String target) { /* ... */}
#GetMapping("/details")
public String Details(#RequestParam Map<String,String> queryParam,
String date, String target) { /* ... */}
#GetMapping("/devmawah")
public String DevMawah(#RequestParam Map<String,String> queryParam,
String date, String target) { /* ... */}
// ....
}
I tried before many times in internet to find the solution, but couldn't find it. All I found are examples for Chat applications, which have 2 endpoints to send and receive.
WebSockets are used for bi-directional communication, not really for REST style services (where HTTP is superior in my opinion). The core difference being that HTTP is fundamentally a request-reply protocol, which fits very well to REST whereas WebSocket is centred around messages. Of course, you can argue that request-reply is a specialisation of message-based communication.
There are several articles on this topic (google REST over WebSocket) and even some StackOverflow questions which detail the pros and cons, for example Is ReST over websockets possible?.
The only way that I know of which allows you to do something resembling REST over WebSocket without having to re-write the RestController is swagger-socket, but I would not recommend using it as the project seems to be inactive now and it seems to not have been used extensively.
Alternatively, you can replace your #RequestMapping or #GetMapping annotations with #MessageMapping annotations and model your API through messages (e.g. the client sends a "GET" message to a given destination, and you send back a message containing the resources).
I can say 99% of reasons that brings us to the idea of Rest Over Websocket is just because we are looking at the problems from wrong direction.
But I wrote such library because I am going to need it in another dummy project I will write later, and you can check it out.
Basically what it does is to scan your controllers, and create a websocket handler that can pass data to those controllers, depending on path, method, and inputs. But there is a lot more it handles internally to achieve this goal.
I havent started the docs yet, so, you can check the sample from website for now.
Well... Just my little contribution...
First you you should code your websocket handler (taking into account the potential size the payload). Then, you should create a config class to register your hander (I am thinking not in a stomp version).
In your handler, after you stablish the connection with the websocket server, you should have a custom component to hold the sessions (maybe a map of usernames and a session wrapper). This is useful, as you you could send messages not only through the ws connection but also through a rest api endpoint (you could hit an endpoint or using an scheduler tasks to periodically send messages to certain users upon certain conditions). Will post again a link later

Can I configure Spring JMS to send custom errors to a queue/topic?

I have a Spring JMS project and I need to catch certain types of Exceptions, convert them to an Error object, and then send them to a custom destination. I could use a try/catch as shown below and this should work, but I would like to know if there is a Spring class out there that I can use where I can put this kind of code, so that it is out of the way. I was looking at the ErrorHandler Interface which looks promising, but I need some of the headers that come in from the inbound request, which is not suitable for the handleError(Throwable t) method. Any suggestions, or thoughts are very much appreciated!
...
public void onMessage(Message<AnObject> inboundMsg, Map<String,Object> headers){
try{
someServiceCall(inboundMsg);
}catch(SomeException se){
AnError error = convertToError(se);
jmsMessagingTemplate.convertAndSend("error-destination",error,headers);
}
}
...
Thank you very much in advance,
Juan
It looks like I should be going with the approach that I laid out above. The answer is in the following thread.
spring jms error handler access to message.

Spring Boot - Websockets - How to see subscribers

I'm working on a websocket application where I'm trying to have one websocket that feeds information in, and then outputs to subscribers to the endpoint. I've figure that out, but I'm wondering if there is a way to see what subscribers are subscribed and to what path?
Here is a code sample of what I'm working on.
#Autowired
private SimpMessagingTemplate template;
#MessageMapping("/{companyId}/{departmentId}")
#SendTo("/{companyId}/{departmentId}")
public void companyInformation(#DestinationVariable String companyId, #DestinationVariable String departmentId, CompanyMessage companyMessage){
String destination = "/" + companyId + "/" + departmentId;
template.convertAndSend(
destination, processCompanyMessage(companyMessage, departmentId));
}
The idea is that the information poster sends companyMessage object to the #MessageMapping endpoint, the companyId and departmentId are retrieved from this mapping.
This message is then processed based on what the departmentId is and is posted to every department that has an active subscriber to the #SendTo path.
e.g.
There are 3 websocket subscribers,
/smallCompany/booking, /smallCompany/sales, /smallCompany/inventory.
#MessageMapping gets a message from /smallCompany/sales. The method processes the message based on the departmentId and posts to EVERY subscriber with the same /{companyId}, even if the /{departmentId} differs.
Any ideas if this is possible, and if not, any ideas to push me in the right direction would be great.
I know it's too late to answer! but I saw this question now!
So, to guide others that will see this question, I should say:
You have several solutions:
1- SimpUserRegistry:
#Autowired private SimpUserRegistry simpUserRegistry;
public Set<SimpUser> getUsers() {
return simpUserRegistry.getUsers();
}
Check this link:
Is there a Spring WebSocketSession repository?
2- Global list:
You've certainly configured the web-socket in spring boot, so, probably you have a derived class from WebSocketMessageBrokerConfigurer, with override configureClientInboundChannel to call setInterceptors...
You should implement custom interceptor derived from ChannelInterceptorAdapter and override preSend to access MessageHeaderAccessor.getAccessor(...).command
These commands defined in StompCommand (CONNECT, DISCONNECT, SUBSCRIBE, UNSUBSCRIBE,...)
By checking accessor.command with StompCommand.SUBSCRIBE/UNSUBSCRIBE you can create and sync a global static list of subscribers, and use it everywhere you need.
3- Other solution:
Check this link:
how to capture subscribe event in my webSocket server with Spring 4

Resources