How to change Failed Message of Messaging Exception in Spring - java

I am using spring integration based Component. That components receives some XML and enriched that XML with some more content.
However, if an exception occurs , then i want to sent the received input XML as the failed message, however in current scenario, it will hold the partially enriched XML as there failed Message.
Is there any way through which I can change the failed message of the Exception , which in turn is wrapped by the Messaging Exception.

As it is so specific case, we need to see your configuration and especially where is an error-channel and how you enrich XML.
However, keep in mind, that Message is immutable object and each interaction with it provides a new Message. But the payload is out of scope of the messsaging and it might not be immutable. And if change of some property of your payload and then you get some exception, you end up in the ErrorMessage with inbound message (failed), but payload might change its state.
Looks like it is your case.
You should think about some payload-cloning variant before you start to enrich it.
Here are some advices on the matter: https://jira.springsource.org/browse/INT-2979

Related

How can I route messages in Spring Integration, which an exception was thrown during processing?

I have the following Integration Flow:
Integration Flow
If an exception is thrown during the second split method, inside the parser, I would like to channel that message to an error channel, is that possible somehow?
One way is to have an output channel for spitter as an ExecutorChannel or QueueChannel. This way every splitted item is going to be processed in the separate thread. You can then apply any available error handling options for those asyn channels.
See docs for more info: https://docs.spring.io/spring-integration/docs/5.2.0.RELEASE/reference/html/error-handling.html#error-handling
Another one is to use a .gateway() with its errorChannel option downstream after the second splitter, so every item is going to be processed in isolation again.
Also an ExpressionEvaluatingRequestHandlerAdvice (maybe together with a RequestHandlerRetryAdvice) can be used downstream on the specific endpoint to deal with its own exceptions: https://docs.spring.io/spring-integration/docs/5.2.0.RELEASE/reference/html/messaging-endpoints.html#message-handler-advice-chain

Spring Data REST Bean Validation

Consider a Person entity with a property name that is annotated as #NotNull. Then a simple PersonRepository and this repo exposed with Spring Data Rest.
When I POST to create a new Person, if the name property is null a ValidationException occurs as expected. But what I actually get on the client is an Internal Server Error (500) and the message is a TransactionSystemException that happened much later in the exception chain.
What I'd expect to get is a Bad Request (400) with the actual ValidationException and all it's useful information so the client can know what's wrong with the posted data.
There seems to be a way to attach custom validators with SDR as explained here. But the thing is, this is not a custom validator, it's a standard bean validation that happens when the repository is asked to save data. So I'm not really sure how those two come together.
So questions:
What are my options to let the client know what's wrong with the submitted data when using SDR?. Things like what fields are invalid and what's the error for each field would be awesome.
Are there any examples about this anywhere?
Thanks a lot.
What you need is a proper ExceptionHandler, it will handle back end exceptions and send meaningful rich messages (json/xml) to the front end client.
Take a look a this git repository

Spring AMQP MessageProperties:all headers were removed during deadlettering

I have got a question about Spring AMQP Message:
During processing I was able to update headers of message properties in String AMQP Message with some specific values.
After DeadLettering of this message, all specific headers were disappeared/removed.
Is this behaviour correct ?
Looking forward to your response.
Regards, Anton.
spring-rabbit.version: 1.3.5.RELEASE
spring.version: 4.1.1.RELEASE
The broker knows nothing about your client-side consumer changes; the original message (with its orignal headers) is dead-lettered by the broker (with an x-death header added to indicate the reason - rejection, expiry etc).
In order to do what you want, you need to publish your modified message yourself rather than using dead-lettering.
See the RepublishMessageRecoverer for an example using Spring retry. You can make a custom recover, or simply catch the exception in your listener to republish.

Different dead-letter-queues in Spring Amqp + RabbitMQ based on exception

Given a basic MessageListener implementation which consumes messages from a RabbitMQ queue, how can I send the message to different dead-letter-queues based on the type of exceptions that could be thrown while processing it?
The queue were the messages are originally published has the x-dead-letter-exchange and x-dead-letter-routing-key set on it, but this is not enough in my case.
In case it matters, my application is using Spring 4 and Spring Amqp.
As far as I understand RabbitMQ documentation and Spring AMQP, it is not possible to send a message to different DLQs based on conditions from inside the code. The reason I say this is that my understanding from debugging the code is that when a message has to be send to a DLQ, the code doesn't specify the exchange or the routing key and RabbitMQ uses the ones defined when the message was published.
So, the only solution I found is to implement something like this:
try {
try_to_do_useful_stuff(message);
} catch (BusinessException e) {
resend_the_message_to_business_dlq(message);
}
This way, if a business exception is thrown, then the message is manually send to the business DLQ. Of course, some details get lost, like originating queue, but this is not an issue if they're not used.
When a non-business exception is thrown then the standard path is followed: retry (if configured) and then route to the defined DLQ.

Spring Integration Gateway with no arguments

On my gateway, I have a method
#Gateway
String commsTest();
The idea is that I can call commsTest from the bean and use spring integration to wire it up to the service activator that will check comms.
When I do that I get a receive is not supported, because no pollable reply channel has been configured error. I realise that this is because a method with no params means "I am trying to poll a message from the channel"
This is a two part question.
What does it mean to poll a message from the channel.
How can I get the functionality I want.
Spring Integration currently has no concept of a message without a payload. By default, a gateway method with no arguments implies you want to receive data (rather than sending data or sending and receiving data).
You can change that default behavior, as described in the reference documentation.

Categories