Catch EDT exceptions in a NetBeans environment - java

I want to catch all uncaught exceptions and bring up a dialog. First I removed the default exception handler from NetBeans and added my handler as default handler:
java.util.logging.Logger global = java.util.logging.Logger.getLogger("");
for (Handler handler : global.getHandlers()) {
if (handler.getClass().getName().equals("org.netbeans.core.startup.TopLogging$LookupDel"))
{
global.removeHandler(handler);
break;
}
}
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
The handler looks like this:
public static final class ExceptionHandler implements UncaughtExceptionHandler
{
#Override
public void uncaughtException(Thread thread, Throwable throwable)
{
logger.error(throwable.getMessage(), throwable);
ExceptionViewPanel.showException(throwable);
}
}
With that construct, I can only catch exceptions which are thrown outside the EDT. I've read about ThreadGroups, but I can't use that solution due we use NetBeans with Maven and so I can't wrap the start thread with a ThreadGroup. The hack from pre-1.7 is also no longer possible and overwriting the EventQueue has no effect.
I've tried many solutions, none of them worked. Does anyone has another solution for me that might work?
Thanks in advance
Teazl

In my own project I've superseded NetBeans error handler to my own. My example:
#ServiceProvider(service = Handler.class, supersedes = "org.netbeans.core.NbErrorManager")
public class MyHandler extends Handler {
#Override
public void publish(LogRecord record) {
if (record.getThrown() != null) {
record.getThrown(); // do with it something
}
}
#Override
public void flush() {
}
#Override
public void close() throws SecurityException {
}
}
See also org.netbeans.core.NbErrorManager and org.netbeans.core.NotifyExcPanel to know how NetBeans uses default handler.
You only need to add this class in your project.

Related

Java - listen when an exception is caught in an external class

Is there a way to create a listener in a separate class that runs a certain piece of code whenever an exception is caught within your project?
My code has a lot of try-catches in it, and if an exception is caught I would like to see the logs using log4j. I can do the following for every try-catch I have fairly easily (just with some time effort):
private static final Logger logger = LogManager.getLogger(Example.class);
public void testMethod() {
try {
// some code here that could throw an exception
} catch(Exception e) {
logger.error("Unexpected error has occurred: ", e);
}
}
This will log the exception using log4j. However, I would need to do that over 50 times, and it's so redundant that I would rather be able to use 1 method to do that. So, is there a way to instead do something like this?
public class ListenerClass {
private static final Logger logger = LogManager.getLogger(ListenerClass.class);
// This method will be listening for exceptions to be caught within the project
/**
* #param e - The exception that was just caught
*/
public void listenerMethod(ExceptionCaught e) {
logger.error("An exception has been thrown: ", e);
}
}
Is this possible?
Thanks
Standard java way:
Thread.setDefaultUncaughtExceptionHandler( (thread, throwable) -> {
log(throwable.getMessage(), thread.getId());
});
which will handle uncaught RuntimeExceptions, and unless otherwise specified it will act for all your application threads.
Just remember the Exceptions are thrown for a reason, and shouldn't be ignored, especially RuntimeExceptions.
If you are using an older version of java (before 8), you must explicitly instantiate an anonymous class:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(final Thread t, final Throwable e) {
}
});
Look at Thread.setDefaultUncaughtExceptionHandler()

How to catch ExceptionInInitializerError?

I want to install some kind of global handler to catch any ExceptionInInitializerError which could be thrown from any static block when some class is loading. Currently it dumps a stack trace to the stderr and exits the application. I want to log a stack trace using my logging framework, then exit the application. Is it possible?
It looks like Thread.UncaughtExceptionHandler is what you are looking.
This answer will provide you with more information.
In essence you need to install default exception handler as soon as possible:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof ExceptionInInitializerError) {
// do something with you're exception
// and than close application
System.exit(-1); // passing
}
}
});
Maybe you can make a global exception handler and just filter your exception out of it.
Example
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof ExceptionInInitializerError) {
//Your handler code
}
}
});

Global Exception Handling in an Eclipse RCP app

I want to override the global Exception Handling in my RCP app. Whenever an uncaught Exception happens I want to log it (using java logging) and then exit the app. I have already overwritten the eventLoopException(Throwable exception) method in the ApplicationWorkbenchAdvisor class. But this catches only the event loop exceptions. As of now I have also overwritten the postStartup() method like this:
public void postStartup()
{
Policy.setStatusHandler(new StatusHandler()
{
#Override
public void show(IStatus status, String title)
{
LOGGER.log(Level.SEVERE, "Uncaught Exception", status.getException());
UnexpectedErrorDialog();
PlatformUI.getWorkbench().close();
}
});
}
It logs the exception in my log file and exits the app. But it's obviously not right and the exception is shown twice in the console, cause all I do is intercepting the showing of the exception in a gui dialog to the user. So how can I properly overwrite/change the global exception handling, so that my code (log) is used instead of the default one?
I would suggest you to use org.eclipse.ui.statusHandlers extension point
Thanks to sambi reddy's tip i have now overwritten AbstractStatusHandler in the ApplicationWorkbenchAdvisor class
#Override
public synchronized AbstractStatusHandler getWorkbenchErrorHandler() {
if (myStatusHandler == null) {
myStatusHandler = new MyStatusHandler();
}
return myStatusHandler;
}
MyStatusHandler extends AbstractStatusHandler and i have overwritten the handle method like this:
#Override
public void handle(StatusAdapter statusAdapter, int style)
{
if(statusAdapter.getStatus().matches(IStatus.ERROR) && ((style != StatusManager.NONE)))
{
LOGGER.log(Level.SEVERE, "Uncaught Exception", statusAdapter.getStatus().getException());
UnexpectedErrorDialog();
PlatformUI.getWorkbench().close();
}
}
seems to work right, only downside is that i still get 2 console outputs.

Vaadin: centralizing custom exception handling

I use Vaadin framework to create my web application GUI.
I have a Vaadin button and its click listener code may throw an application custom exception. In other points of application code, this exception is thrown all the way back to my custom window class, where it's centrally handled. I'd like to do something similar here: throw this exception in the clickListener code, so I could catch it in my custom terminal error handler in the window class. As the click listener class does not throw any exception, I'm unable to throw the exception there and I think I'll be obliged to handle the exception locally. As I don't want to handle the exception at the button click listener level, I think I'll forward it to my custom window class. Something like this:
Button btnNew = new Button("New", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
try {
doThingThatThrowsException();
} catch (Exception exc) {
window.handleCustomException()
}
}
});
Is this the usual way of centralizing handling of a custom exception using Vaadin?
I can't answer as to whether it's the usual way of handling the exception, but we do something very similar.
Depending on how many listeners or how often you have to do this, you could also create abstract listeners that do that delegation for you.
e.g.
abstract class BasicListener {
protected void handleThrowable(Component.Event event, Throwable throwable) {
Window window = event.getComponent().getWindow();
if (window instanceof ExceptionHandlingWindow) {
((ExceptionHandlingWindow) window).handleException(throwable);
} else {
// Log it ? DO something, anyway.
}
}
}
abstract class ExceptionHandlingButtonClickHandler extends BasicListener implements Button.ClickListener {
#Override
public void buttonClick(Button.ClickEvent event) {
try {
handleClick(event);
} catch (Throwable e) {
handleThrowable(event, e);
}
}
protected abstract void handleClick(Button.ClickEvent event);
}
Button btnNew = new Button("New", new ExceptionHandlingButtonClickHandler() {
#Override
protected void handleClick(Button.ClickEvent event) {
doThingThatThrowsException();
}
});

Java thread trobleshooting for SwingWorker like tasks

Thread dump contains wealth of information. For example, if I suspect some action fired more than once, then all I need to do is dumping stack trace each time the action is fired, then investigate the stacks for erroneous action firing.
In certain situations developers are encouraged to abandon conceptual simplicity of sequential execution. For example, Swing offers SwingWorker helper to work around limitations of single threaded EDT. Now, if I dump stack trace, it is useless, because the action is fired by SwingWorker, and there is no information on who initiated SwingWorker task.
So, how do I troubleshoot? Is there a clever trick of "redirecting" thread dump to follow the genuine cause?
You can extend SwingWorker to record the stack when it is created (or when execute but then you need to create another execute method since it is final). Creating the cause is relative expensive though so you might want to do it only when debug (check log level or some such)
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
public abstract class TracedSwingWorker<T, V> extends SwingWorker<T, V> {
private final Exception cause;
public TracedSwingWorker() {
super();
this.cause = new Exception("TracedSwingWorker created at:");
}
#Override
protected final T doInBackground() throws Exception {
try {
return doWorkInBackground();
}
catch(Exception e) {
if(this.cause != null) {
Throwable cause = e;
while(cause.getCause() != null) {
cause = cause.getCause();
}
cause.initCause(this.cause);
}
throw e;
}
}
protected abstract T doWorkInBackground();
// just for testing
public static void main(String[] args) {
new TracedSwingWorker<Void, Void>() {
#Override
protected Void doWorkInBackground() {
throw new IllegalArgumentException("Exception in TracedSwingWorker!");
}
#Override
protected void done() {
try {
get();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
}
}.execute();
}
}
prints:
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Exception in SwingWorker!
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
<snip>
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.Exception: SwingWorker created at:
at TracedSwingWorker.<init>(TracedSwingWorker.java:15)
at TracedSwingWorker$2.<init>(TracedSwingWorker.java:60)
at TracedSwingWorker.main(TracedSwingWorker.java:60)
I might be telling you something you already know but I suggest ThreadDump
http://www.oracle.com/technetwork/java/javase/tooldescr-136044.html#gbmpn
If you use IDE, then this is good:
NetBeans
http://netbeans.org/kb/docs/java/debug-multithreaded.html
I used Eclipse for this a lot. Debugger view has means of visualizing and tracking multiple threads, printing stack and pausing them.

Categories