How to handle exceptions and error in apache camel route - spring-boot

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.

Related

How can I catch the ProvisioningException that can occur when Spring kafka cannot connect to Producer endpoint?

How can I catch the ProvisioningException that can occur when Spring kafka cannot connect to Producer endpoint during Spring-Boot initialization phase?
I am using the lib called spring-cloud-stream, or in my case, more specifically: spring-cloud-starter-stream-kafka .
I assume there must be a way to define a config-Bean, or AOP, that might be able to catch the null error thrown due to connection problems? The existing error is not informative enough when connectivity is gone:
Caused by: java.util.concurrent.TimeoutException: null
at org.apache.kafka.common.internals.KafkaFutureImpl$SingleWaiter.await(KafkaFutureImpl.java:108)
at org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:272)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopicAndPartitions(KafkaTopicProvisioner.java:355)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopicIfNecessary(KafkaTopicProvisioner.java:329)
at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createTopic(KafkaTopicProvisioner.java:306)
I'm talking about the "Bean Creation Phases" documented here: https://reflectoring.io/spring-bean-lifecycle/ which describes how to hook your own code to initialization phases but I want to hook 3rd party code.
NOTE: The bounty is expired. An answer outside of the context of Spring Kafka is ok the answer is still relevant to my question.
NOTE: I found another question that also does not provide a good answer: Spring - catch bean creation exception
you can for example Capture that in ExcepcionHander
#ControllerAdvice
#RestController
public class ExceptionHandler {
#ExceptionHandler(value = {ProvisioningException.class})
public void handleException(ProvisioningExceptione) {
....code....
}
I mean the main paoint is to know when do you get this error....
when invoking a method the method should throw it but instead if it is on the initializacion or something like that, it is diferent. I can see such information in your question, please be more specific

Global Exception Handling via Spring Advice In a MQ based Spring Boot Application

I've a MQ Spring Boot PaaS application where I need to implement exception handling via a common exception handler class (GlobalExceptionHandler). My PaaS application receives message from a source queue, perform some database operations via spring jpa and write the response back to a destination queue.
I need to handle all the database RuntimeException, custom business exceptions and other checked exceptions via GlobalExceptionHandler class.
My GlobalExceptionHandler will have handlers (method) defined for every exception. In my handler, I will be logging the exception first and then I will be creating a [error code, desc] and then I need to return it back to main flow.
I do not have any controller in my application. So I think, I can't use #ControllerAdvice. Currently I'm using spring AOP #AfterThrowing as below but I'm not able to return the [code, desc] from handlers.
#AfterThrowing(pointcut = "execution(* com.abc.xyz.service..*(..)) ",
throwing = "dataNotFoundException")
public void handleDataNotFoundException(DataNotFoundException dataNotFoundException) {
LOGGER.info("Info : " + dataNotFoundException.getMessage());
// code, desc need to create here and send it back to calling place.
// I need to change the return type here from void.
}
Can anyone please guide me in implementing exception handling here.
As I explained here, #AfterThrowing cannot modify return values or otherwise change the execution flow of your epplication. You cannot even catch the exception there. You need to use an #Around advice instead.
I suggest you read some documentation first and then ask more follow-up questions.

Global Error Handling in Service Fabric Stateless Web API

How should I handle global exception handling for my controller methods in stateless web API? My goal is to avoid verbosity of try/catch statements inside my controller.
I was able to achieve this with IIS hosted Web API using a custom ExceptionHandler which I register in my WebAPIConfig.cs. This won't work right-off-the-bat in OWIN hosted API (like in Service Fabric). So in SF stateless web API, I created an Owin middleware and registered that middleware in Startup.cs but it does not work. The catch block is ignored in the response pipeline in my middleware code.
...
public override async Task Invoke(IOwinContext context)
{
try
{
//It goes here
await Next.Invoke(context);
}
catch (Exception ex)
{
//This catch block does not get called????
HandleException(ex, context);
}
}
After a lot of digging for solutions, since there has been quite a lot of similar questons out there, I gained a better understanding about the Web API and OWIN pipeline. This question here in SO provided me a lot of info:Disable *all* exception handling in ASP.NET Web API 2 (to make room for my own)?
First-off, Web API exceptions are handled by default and that means the exception is handled so it does not propagate up the stacktrace. And that's the reason why, the catch block above (from my posted question) does not get called. In order for it to get called, I need to replace the IException handler of the Web API(in startup.cs) via this:
config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler());
All this custom handler does is forward the exception down the stack and let the OWIN global exception middleware do the work.
The PassthroughExceptionHandler is implemented like this:
public class PassthroughExceptionHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var info = ExceptionDispatchInfo.Capture(context.Exception);
info.Throw();
}
}
Note that this uses ExceptionDispatchInfo . There are other solutions that have a different implementation but so far this one provided me what I need which is to ulimately wrap the exception into my common error response model in my OwinGlobalExceptionHandler.

Spring integration http outbound gateway logging errors

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

Handling exception when using HibernateDaoSupport

I am using Spring Hibernate integration in my application and DAO classes are extending HibernateDaoSupport.
Suppose I save some object using the code
getHibernateTemplate().save(object);
As Spring Hibernate integration doesn't mandate to write try-catch block, but suppose if any exception is thwron while saving that object.
Then what is the best way to handle it? I means should I catch it in the service layer and wrap it in some user defined excpetions.
Do I need to write try-catch in DAO layer method itself in case I want to log which method in DAO throws exception?
I have never used HibernateDaoSupport or Hibernate Template before so ignorant about exception handling. Please provide me your valuable inputs
The idea behind Spring using RuntimeException is that generally there are different types of exception:
Exceptions that you want to recover from (such as a DuplicateKeyException if a record that you're trying to insert already exists or the more general DataIntegrityViolationException if there was a DB constraint that was violated as a result of user input)
Exceptions that you can't recover from (the database is down)
For the first case, you may well handle the exception (either through a custom business exception, so that the view layer can redirect to the input page and provide a meaningful message)
For the second case, it would be easier to let the exception bubble up and have it handled by a generic exception handler that then displays a generic error page to the user. For this scenario it doesn't make sense to wrap the exception in a custom exception as you won't be able to recover. A blown up DB tends to be fatal.
So what I would do:
try {
getHibernateTemplate().save(object);
} catch (DataIntegrityViolationException dive) {
throw new BusinessValidationException(dive, "You've got the data wrong");
}
Spring exception hierarchy is well documented.
Usually you can't do much if you have a data access exception, because in the working system this may be caused by the shortage of diskspace on the DB server, or network connection problems etc.
Such exceptions are usually need to be logged and investigated as soon as possible.
There some recoverable errors, they can be handled with spring exception hierarchy, but imho most of them should be avoided during the developing phase, so your web server should validate as many things as possible, before it goes to the db.
If you want to set the exception logging see the similar questions:
Exception handler in Spring MVC
Spring MVC Best Practice Handling Unrecoverable Exceptions In Controller

Resources