Spring Async method hides exceptions - java

I have a strange issue with Async methods.
If I run it in async way and its job throws some particular exception, it doesn't show it and simply stop the execution (no catch, no log).
I found it working with jasperreport.
This is the fault block code:
JasperPrint jp1=null;
try{
jp1 = JasperFillManager.fillReport(reportD1, params, new JRBeanCollectionDataSource(ingressi));
}catch(Exception e){
log.error(e);
e.printStackTrace();
throw e;
}
If this code is inside an Async annotated method it doesn't throw the exception and doesn't log (simply stops the execution).
If I remove the Async annotation, it throws this:
java.lang.ClassNotFoundException: org.apache.commons.collections.map.ReferenceMap
My trouble is not the exception itself, but why async method doesn't catch it?

Which method is #Async exactly? If you are running an asynchronous method you should always favour a Futureas result type. If you provide a void method, there's no way to transmit any sort of exception that would happen in the (asynchronous) thread.
There is catch for void method. Long story short: Spring Framework 4.1 allows you to register an exception handler for that kind of things, check SPR-8995. 4.1.RC1 will be available shortly if you want to try.

Related

Spring retry exception handling execution behavior

I am trying to get to the best way to wrap spring-retry #Retryable annotation around external service call. Here is my code:
#Retryable(exclude = HttpClientErrorException.BadRequest.class, value = RestClientException.class)
private ResponseEntity<Item> retrieveItemById(String id)
{
HttpHeaders headers = new HttpHeaders();
try {
return restTemplate.exchange(httpConnectionProperties.getBaseUrl() + "/items",
HttpMethod.GET, new HttpEntity<>(item, headers), Item.class, id);
}
catch (RestClientException e) {
log.error("Exception occurred while retrieving an item" , e);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
I have a few questions on what happens when a RestClientException occurs :
Is the catch block executed before retry kicks in or does the retry kicks in before the catch block execution? Do I need a recovery block?
Probably more of an exception handling question - Is there a way to differentiate between an actual retry worthy scenario (service momentarily down, network issues, I/O error etc.) vs exception occurring due to lack of presence of an item in the above case?
Since you are catching and "handling" the exception, retry is disabled; retry will only work if the method throws an exception.
To change the result (instead of throwing the exception to the caller when retries are exhausted, you need a #Recover method.
Not retryable exceptions will go straight there; you can have multiple #Recover methods for different exception types, or one generic one and you can check the exception type yourself.

Axon framework: Handling database exceptions in state-stored aggregates

I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates. The application relies on a database constraint (using H2 for now) to enforce uniqueness on a name attribute. I would like to catch this exception and rethrow it as a user-friendly domain exception.
Per the Axon documentation:
Exception Handling says "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class"
Message Intercepting documentation says "A function annotated with #ExceptionHandler will be regarded as a handler interceptor which will only be invoked for exceptional results. Using annotated functions to this end for example allow you to throw a more domain specific exception as a result of a thrown database/service exception."
But I cannot get this to work. I have tried adding exception handlers as follows:
#ExceptionHandler
public void handle(ConstraintViolationException ex) throws Exception {
if (ex.getMessage().contains("UNQ_COMPANY_ID") || ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new DomainException("Plan name and company id must be unique");
}
throw ex;
}
but this method is not called. I have tried putting the exception handler method on the aggregate and on a separate command handler class, tried adding resultType=ConstraintViolationException.class, and tried catching other types of exceptions including Exception, RuntimeException, AxonServerRemoteCommandHandlingException, etc. but this method is never called.
I can see the error in the log output:
org.axonframework.axonserver.connector.command.AxonServerRemoteCommandHandlingException: An exception was thrown by the remote message handling component: org.hibernate.exception.ConstraintViolationException: could not execute statement
Is it possible to catch database exceptions in state-stored aggregates? If it is, can someone point me towards what I am doing wrong?
The statement "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class" makes me wonder whether I need to create a custom repository class (rather than using the default GenericJpaRepository) but that seems like a lot more work than should be necessary.
Thank you!
Update: I was able to roughly accomplish what I want by adding a UnitOfWork parameter to the #CommandHandler method and using it to registering a rollback callback on it as follows:
uow.onRollback(unit -> {
DefaultUnitOfWork duow = (DefaultUnitOfWork) unit;
Throwable ex = duow.getExecutionResult().getExceptionResult();
while (ex != null) {
if (ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new RuntimeException("Plan name must be unique");
}
ex = ex.getCause();
}
});
But this seems kind of verbose, as well as limiting me to throwing unchecked exceptions only. This also doesn't feel like the right way to do this though because I assume the purpose of the #ExceptionHandler annotation is to eliminate need for code like the above.
This is doable of course.
Actually, the best pointer I could give you if the code-samples repo where you can see a sample about distributed exceptions.
In general, as you could see in your shared log, the 'original' exception is wrapped into an AxonServerRemoteCommandHandlingException meaning you will have to handle that. Doing that, you can pretty much add anything to the details field of this class, adding the indication you had a ConstraintViolationException for example (or an ERROR_CODE, like HTTP protocol does) and you are fine to unwrap it on the other side.
What might be the "gotcha" you require, is to know that an #ExceptionHandler annotated method should reside in the object handling the message. So if you want to react to a failing command handling operation (which would be the case in your sample), you will need to place the exception handler in the Aggregate, next to the Command Handler.
That fact you get an AxonServerRemoteCommandHandlingException to me suggests the exception is caught on the command dispatching end. So, prior to dispatching a command on the CommandGateway/CommandBus.
However, whether this is the problem at hand, isn't clear to me right now, since the sample only shows the exception handler and not where it resides. Please share whether my assumption on the placement of the exception handler is correct. If not, we'll dive into this deeper to get to the cause.

Spring Boot scheduler thread stops randomly

I have an Scheduler in spring boot that fulfils a specific business task every X minutes. It works fine until it suddenly stops and does not engage anymore. There is no exception in the logs or any other logs. I need to restart the program for the scheduler to work again.
Sometimes the task of the scheduler goes wrong, and I throw an exception. To be able to handle those exceptions specifically, I wrote a custom ErrorHandler in Spring for the scheduler that resolves a seperate task for logging purposes. It is linked correctly to the scheduler and processes the task.
This issue can come up when an unhandled exception gets thrown inside of an ErrorHandler. I am not sure about the specifics, however a Runtime Exception thrown by an ErrorHandler (or a method inside of it) that gets propagated outside of it basically kills the scheduled thread for that task. Furthermore NOTHING gets written to the logs (no Exception message, nada).
The "easiest" way to resolve this is by wrapping the entirety of the method in a try/catch block catching Exception - although depending on why you have that Error Handler that might be a bad idea. This does not solve the underlying issue at hand, but it keeps the thread alive and allows you to log the issue.
Example:
public class MyErrorHandler implements ErrorHandler {
#Override
public void handleError(Throwable t) {
try {
//handle intended exception (ex. write to database or logs)
} catch (Exception e) {
//handle exception that was thrown while trying to handle the intended exception.
}
}

Is bean method with ListenableFuture return value executed in separate thread?

Application declares interface for sending notifications with single method with ListenableFuture<> return type.
For mail service I don't see exceptions in case of misconfiguration (for example if SMTP server is down or host is not resolved) in my batch job.
Debugging shows that on:
MailNotificationService mailService = applicationContext.getBean(MailNotificationService.class);
I receive proxy that on method invocation:
mailService.send(mime);
resolved with stack:
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke(AsyncExecutionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
Documentation for invoke says:
* Intercept the given method invocation, submit the actual calling of the method to
* the correct task executor and return immediately to the caller.
After some steps I see new thread SimpleAsyncTaskExecutor-1 and service executed here.
It looks like service executed in separate thread and exception doesn't propagated to original thread (if it is meaningful at all).
Is it correct that for bean methods with ListenableFuture<> return type Spring execute them in separate thread?
NB My original issue in that I am blind in case of errors in notification service (traces are not logged). Mail service throws unchecked org.springframework.mail.MailException and the only way to find that out is to wrap .send() method by Exception with logging:
#Autowired
private JavaMailSender mailSender;
public void notify() {
try {
mailSender.send(mime);
} catch (Exception ex) {
log.warn("Can't deliver mail", ex);
}
}
As white predicted I have #Async annotation on service method and #EnableAsync on configuration class.
Exception handling described in section:
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#scheduling-annotation-support-exception
In case of Future return type (ListenableFuture is subtype of it) exception propagated to future object and can be retrieved from exception ExecutionException.getCause() which occur on Future.get() method call.
In my case I ignore return type (don't call .get()). So exception was not captured and logged. As I wrote originally excpetion logging should be done in task itself in this case.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutionException.html

Quartz scheduled job not firing - possible unhandled exception?

I have a web application with scheduled jobs using the Quartz library. Recently I encountered cases where a job didn't seem like it was being fired. I did some reading and apparently if the job throws an exception, the Quartz scheduler will attempt to execute the job again. Is this true?
In any case, I did some troubleshooting based on the assumption that the above statement is true. So let's say I have the following code snippet:
try {
method.invoke(object, params);
}
catch (ExceptionA ea) {
ea.printStackTrace();
}
catch (ExceptionB eb) {
eb.printStackTrace();
}
// and so on so forth, catching a bunch of specific Exceptions
The important point here to note is that Exception itself is not being caught.
So let's say the method being invoked throws an exception which is not handled.
public void methodBeingInvoked() throws UnhandledException {
What happens here?
Any Throwable thrown from a Job will be caught by Quartz and wrapped in a JobExecutionException, and not refired.
See the source code for JobRunShell#run
There is some documentation on the Quartz website which contradicts this, but after looking at Quartz 1.8.x/2.0.x/2.1.x source code, the documentation is wrong for all versions.
A Job's execute method should contain a try-catch block that handles
all possible exceptions.
If a job throws an exception, Quartz will typically immediately
re-execute it (and it will likely throw the same exception again).
It's better if the job catches all exception it may encounter, handle
them, and reschedule itself, or other jobs. to work around the issue.

Categories

Resources