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?
Related
I am not able to find how to do custom error handling in for a spring kafka consumer.
My requirement is:
For any deserialization errors, just write the error and message to database.
For any errors in execution under #KafkaListener method, retry 3 times and then write the error and message to database.
From the spring docs, I found that,
For 1, I will have to use ErrorHandlingDeserializer and it will then call the #KafkaListener error handler.
For 2, framework provides SeekToCurrentErrorHandler which handles message retries.
I am not understanding where can I add the code to write the exception/message to database in addition to enable configured retries.
Add a recoverer to the SeekToCurrentErrorHandler
new SeekToCurrentErrorHandler((rec, ex) -> {
Throwable cause = ex.getCause();
if (cause instanceof DeserializationException) {
...
}
else {
...
}, new FixedBackOff(2000L, 2L));
By default, deserialization exceptions are not retried; most others are retried before calling the recoverer.
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.
}
}
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.
First, I am throwing run time exceptions for all unrecoverable exceptions, this causes these exceptions to travel up to the container, where I currently use an error page (defined in web.xml). In this error page is a scriptlet that invokes the logger.
The issue I am having with this is that the exception is no longer on the stack at this invocation. I have access to it from a request scope variable ("javax.servlet.error.message"). This string is the stack trace. I need this stack trace for logging purposes obviously, and on different app servers "javax.error_message" can be turned off for security reasons.......
So my question is, how can best log runtime exceptions from within Java EE apps without wrapping everything in this:
try {} catch (Exception e) {logger.log(...)}
?
I want some way to invoke the logger from the container maybe... right before the container catches the exception for example.
I found a solution. By adding a response filter and wrapping chain.doFilter(req, resp) like so:
try {
chain.doFilter(req,resp);
} catch (Exception e) {
logger.error("", e);
throw new RuntimeException(e);
}
This works fine so far and isn't dependent on a particular framework or app server.
There is nothing I know of in Servlet API to accomplish this.
However, you can do this in Tomcat with an instance listener. You can install a listener in context.xml like this,
<InstanceListener>myapp.MyListener</InstanceListener>
Tomcat fires InstanceEvent.AFTER_SERVICE_EVENT event right after the container catches the exception and before it throws the exception again. You can invoke the logger right there.
Correct me if I'm wrong, but the 'exception' object is present as a variable.. called 'exception' in your 'error' jsp. You could always use this object to log retrieve the exception information and log in in the error jsp itself.
AOP (Aspect Oriented Programming) would be my first choice.
You define:
join point (a runtime exception is thrown).
advice (your code to log the exception).
point cuts (which parts of your applications are "listening" this aspect).
Take a look at http://www.aspectj.org/