Spring integration http outbound gateway logging errors - spring

I have an integration flow where I'm reading messages from a jms channel and sending them through a REST api call using http-outbound-gateway.
Now when I get a 5xx Http server error I'd like to log the the URL of the service along with the response message.
I see that the RestTemplate instance already logs the URL and calls a ResponseErrorHandler which can be a custom implementation.
My problem is: the ResponseErrorHandler only receives a ClientHttpResponse as a parameter and I can't know the URL from that instance. What I need is to log the server error like: 'Error URL - Response ...'
How can I do that? I can't override RestTemplate's error handling and the ResponseErrorHandler doesn't have enough info.
Thank you very much.

Well, what I see there.
The HttpRequestExecutingMessageHandler (<int-http:outbound-gateway>) catches all underlying exceptions:
catch (Exception e) {
throw new MessageHandlingException(requestMessage, "HTTP request execution failed for URI ["
+ (realUri == null ? uri : realUri.toString())
+ "]", e);
}
Including the result of that DefaultResponseErrorHandler from the RestTemplate.
And as you see we use here for the MessageHandlingException uri as well as the requestMessage.
Further this exception will be delegated to that jms channel.
Why isn't that enough for you?
From other side you can add <request-handler-advice-chain> to the <int-http:outbound-gateway> with ExpressionEvaluatingRequestHandlerAdvice to get deal with that MessageHandlingException just in place: http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/messaging-endpoints-chapter.html#expression-advice

Related

Error handling with feign client - resilence4j

My spring boot app has a feign client that POST a payload to external endpoint.
There is requirement to audit all the calls, especially when any errors occurs in calling the endpoint (connection, unauthorized etc), after retry are exhausted. To audit,
need some information from original payload
http status
underlying exception message,
backup original payload for reference
endpoint
I tried below approaches (for error handling), but still unable to find a solution that covers all above
feign Fallbackfactory - it has handle to exception, but unable to effectively capture feign response/original payload
fallbackMethod with resilence4j - here i get access to original payload and exception, but again unable to capture actual response status (401, 503 etc)
CustomErrorDecoder - Here able to get access to feign Response, but then have to map response body (any request body/payload). Also have to map exception
Appreciate any suggestion/ advise?

How to handle exceptions and error in apache camel route

I have a file watcher route and azure blob container route. I would like to handle/throw exceptions and errors. Can someone assist me with some examples ?
I would like to handle cases like if there is any exception while connecting to blob container or while processing files from the directory.
#Override
public void configure() {
onException(Exception.class).handled(true)
.setHeader(AppConstants.FILENAME , simple("${headers.camelFileName}"))
.setHeader(AppConstants.EXCEPTION_INFO, simple("General Exception"))
.setHeader(AppConstants.EXCEPTION_LOG, simple("${exception}"))
.log("${exception} Exception occured while processing the file:::${in.headers.camelFileName}")
.to("file://error")
.end();
onException(BlobStorageException.class).handled(true)
.setHeader(AppConstants.CONTAINERNAME , simple("${headers.CamelAzureStorageBlobContainerName}"))
.setHeader(AppConstants.EXCEPTION_INFO, simple("Communication Exception"))
.setHeader(AppConstants.EXCEPTION_LOG, simple("${exception}"))
.log("${exception} Exception occured while Connecting to Azure Blob :::${in.headers.camelFileName}")
.to("file://error")
.end();
from("file-watch:hello?events=CREATE&antInclude=**/*.csv&recursive=true")
.routeId("fileWatch")
.log("File Consumed Name: ${header.CamelFileName}")
.to("direct:uploadFileToBlob")
.end();
from("direct:uploadFileToBlob")
.routeId("uploadFile")
.log(LoggingLevel.INFO,"Container Name: ${header.CamelAzureStorageBlobContainerName}")
.toD("azure-storage-blob://jdawmsdevsa/${header.CamelAzureStorageBlobContainerName}?blobName=${header.CamelFileName}&operation=uploadBlockBlob&serviceClient=#serviceClient")
.log(LoggingLevel.INFO,"${header.CamelFileName} Uploaded to ${header.CamelAzureStorageBlobContainerName} Container Successfully")
.end();
}
So far, I have handled the above General Exception and BlobStorage connectivity exceptions.Any suggestion to further enhance error and exception cases ?
Route scope exceptions
Instead of using global scope for all exceptions you could use route specific scope instead which allows you to handle exceptions that are for example specific to your uploadFile route.
Redelivery options
With connection errors you could also configure redelivery policy to make the route more robust against minor connectivity issues.

Throwing exception outside of Flux/Mono reactive pipeline

In my spring JMS listener onMessage method, I am using a reactive pipeline as as below where I receive a JMS message from a queue and transform that to a different format and publishing to another topic. Without the reactive flow, in the case of failure in output publishing, I can throw a runtimeexception for the same message to redeliver from the queue. But by using the below flow of reactive approach, I cannot find a way to throw an exception outside. Can you please help on what should be the approach here for throwing the exception outside to get the message redelivered
public void onMessage(Message message) {
Mono.just(message)
.doOnNext(LoggingUtil::logMessage)
.flatMapIterable(messageTransformer::transformToTriggerEvents)
.doOnNext(LoggingUtil::logTriggerEvent)
.doOnNext(triggerEventPublisher::publish)
.subscribe();
}

Getting Error message as NULL while invoking a service in one spring boot application from another spring boot application using RestTemplate

AM trying to invoke a spring boot microservice from another application.
Here is my Server code, if any exception occurs
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new com.test.models.ResponseEntity("Tenant details
not found"));
Here is my client code,
ResponseEntity<Object> uploadResponse =
restTemplate.exchange("http://TESTAPPLICATION/v1/object",
HttpMethod.POST, requestEntity, Object.class);
Am getting a response as
Caused by: org.springframework.web.client.HttpClientErrorException: 403 null
If I hit my endpoint from PostMan, am getting proper response message.
But from my client-side application am getting response message as null. Please let me know what is going wrong.
UPDATE:
Screenshot.
Client Responds with INTERNAL_SERVER_ERROR. But from my server iam responding 403.

how to prevent message re-queue within rabbitmq server?

I'm using direct exchange to publish messages to certain queues with routing keys, all configured in rabbit-server not code, I'm consuming messages with spring micro-service then some failures happens within the receiving method, then the message re-queued causing loop, so I'd like to add a policy with rabbit-server to prevent that kind of re-queuing, could it be added as an argument while binding queue with exchange with specific routing key, or it should be a policy ?
On any exception by default spring send nack with requeue "true". If in your spring consumer application you want to send requeue false, then throw the exception "AmqpRejectAndDontRequeueException". So your consumer code should loook something like this :
`void onMessage(){
try{
// Your Code Here
} catch(Exception e){
throw new AmqpRejectAndDontRequeueException();
}
}`

Resources