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.
}
}
Related
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.
I have a question about how to handle EJBExceptions in some special cases.
General situation
In our application an EJB (3.0) DataAccessObjects(DAO) are responsible for all database access, these are used in other parts of the application.
Exceptions in the database layer are expected, for instance because of Optimistic Locking or Database constraint violations. The exceptions often thrown outside of the DOA class, because they occur on commit of the automatic JTA transaction. The calling class then receives this exception wrapped in an EJBException.
In most cases ignoring or logging and rethrowing the EJBException is best, as our JMS will trigger automatic retries for MessageDrivenBeans. In two cases, we don't want the exception to be propaged, as they have unwanted side effects.
Handling in JSF
In our JSF website we use the following pattern to display user friendly messages:
#ManagedBean
#ViewScoped
public class MyDataController {
#EJB
private MyDataDao myDataDao ;
public void addData(){
FacesMessage msg;
try {
Data data = new Data();
// Data gets filled
myDataDao.addData(data);
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Succes",
data.getName());
}
catch (EJBException e) {
LOGGER.warn("Failed to add data"newCompanyName, e);
if (ExceptionUtils.getRootCause(e) instanceof SQLIntegrityConstraintViolationException) {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Failed",
data.getName());
}
else {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL,
"Failed to add data for unknown reason", data.getName());
}
}
}
}
Handling in Schedules tasks
In a related case, we call the database from a timed task (created using #Schedule). However this task is destroyed when (two consecutive?) exceptions occur while running it (at least in Weblogic). For us it is very important that this task keeps running even if exceptions during handling occur.
We have achieved this by catching and logging all EJBExceptions, as explained in this answer and in this answer. (Actually in our case we decided to catch all exceptions).
Problem
The above solutions mostly work as intended. However, we recently found that Errors are wrapped in an EJBException as well. For instance an OutOfMemoryError. In this case it caused the error to be swallowed, disabling the normal mechanism in Weblogic that would restart the application in case of an OutOfMemoryError.
Effectively this has downgraded Errors to Exceptions.
Question
The only solution I have is to check the recursively check the exception and its causes for instances of type Error, and if that is the case, rethrow the EJBException.
What is the correct way to handle the EJB exceptions in these situations?
I have a rest API on my spring-boot 1.3.5.RELEASE application, from which a process is started asynchronously using a ThreadPoolExecutor.
My problem is that the async process happens to throw runtime exceptions for scenarios that were not handled but the stacktrace does not go in my logs. I am using log4j.
This is a big issue, because it takes a lot of time to debug and see what the actual problem is.
I am aware of the #ControllerAdvice, but I think it's context ends when the new thread is started and spring no longer intercepts the Exceptions.
How can I configure the ThreadPoolExecutor to redirect the uncought exceptions to the spring context or how should I approach this issue?
I am looking for a general solution to catch these types of exceptions and add their stacktrace to the appender, as I don't know where a developer will start a new thread which will crash with an uncaught exception
Let's say that the rest looks like this:
#RequestMapping("/api/test")
public void doSomething() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 10 , TimeUnit.SECONDS, new ArrayBlockingQueue<>(10, true));
threadPoolExecutor.execute(() -> {
throw new RuntimeException("some exception");
});
}
Have you tried creating a #ControllerAdvice, injecting Throwable into it and call logging?
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.
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.