7

I'm not sure about how manage exceptions in GUI; my goal is to let the user know if something goes wrong showing an intelligible message.

I'm thinking to do something like this:

// I'm inside an actionPerformed() method
try {
    // do whatever I have to do here
} catch (KnownBusinessException1 e) {
    // inform the user and do something;
    // most times simply inform the user that it wasn't possible to complete the
    // operation and remain in the same window instead of moving forward.
} catch (KnownBusinessException2 e) {
    // just as above
} catch (KnownDataAccessException1 e) {
    // just as above
} catch (KnownDataAccessException2 e) {
    // just as above
} catch (RuntimeException e) { // I want to catch any other unexpected exception,
// maybe NPE or unchecked IllegalArgumentExceptions and so on
    // something went wrong, I don't know where nor how but I will surely inform the user
}

Now: If in the try block there are checked exceptions to catch, would it be better to nest a try/catch or to catch these checked exceptions after catching RuntimeException? (it probably depends, I don't even know if this is going to happen btw)

Another thing: what about Errors? I wouldn't like to experience an unexpected shutdown if I were a user, I'd much rather that the application tells me that something went incredibly wrong and no one can do anything about it, "the end of the world is coming so I will exit right now". At least I would know that wasn't my fault lol.

Btw don't know if it's a good practice to catch errors... :\

There is a better way to do this in a Swing application?

kelo
  • 479
  • 11
  • 19
  • Look at this for the errors http://stackoverflow.com/questions/352780/when-to-catch-java-lang-error – Bhesh Gurung Sep 09 '12 at 18:10
  • Possible duplicate of [How can I catch Event Dispatch Thread (EDT) exceptions?](http://stackoverflow.com/questions/4448523/how-can-i-catch-event-dispatch-thread-edt-exceptions) – trashgod Sep 09 '12 at 18:14
  • @BheshGurung I had already read it. Well, if there's nothing wrong with it, I think I will add another catch block after the RuntimeException catch block in order to catch Errors and try to inform the user before exiting. @ trashgod: that doesn't seem to be a duplicate for me :) – kelo Sep 09 '12 at 18:28

3 Answers3

11

I think the best is to explicitly catch all checked exceptions, and install an uncaught exception handler for the rest. See this: How can I detect when an Exception's been thrown globally in Java?

This is how I use Thread.setDefaultUncaughtExceptionHandler:

public static void setupGlobalExceptionHandling() {
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            handleException(e);
        }
    });
}

Note that the "sun.awt.exception.handler" trick for the EDT thread, mentioned in many SO posts, is not necessary and does not work in Java 7. For Java 7 just use the standard Thread.setDefaultUncaughtExceptionHandler as described above. Of course, if you use both mechanisms to register the exception handler, the code will work in all versions.

BTW, the EDT thread is automatically restarted if an uncaught exception is thrown (but your app might remain in an inconsistent state), see this: EDT and runtime exception

Community
  • 1
  • 1
lbalazscs
  • 16,476
  • 7
  • 39
  • 48
  • 1
    +1 for mentioning `UncaughtExceptionHandler`. It is indeed a good thing to have in your code :) – javatarz Sep 09 '12 at 18:32
  • @lbalazscs: Thanks, but I didn't understand what handleException(e) is supposed to do. Is this a common way to handle runtime exceptions (e.g. logging)? What if I want to take different actions for different subclasses of RuntimeException, depending on which exception has been thrown and on the action of the user that caused it? – kelo Sep 10 '12 at 09:54
  • Runtime exceptions in my view are not caused by user actions but by programmer errors :) In a GUI I would show the exception message, possibly with a stack trace, and I would ask the user to contact the developer with this info. The JXErrorPane class in the SwingX does this. But you can do whatever you would like, including examining the exact class of the exception. – lbalazscs Sep 10 '12 at 10:30
  • Yes that is my view too, I expressed myself badly: I meant that the user clicks `Button1`, this action causes a runtime exception (*due to a programming error (e.g. NPE) or whatever (e.g. DataAccessException)*). Obviously the user is **not** responsible of that exception, but I want to act differently depending on whether he has pressed `Button1` in `ViewX` or `Button2` in `ViewY` :) Is that possible within the `handleException(e)` method? It seems to me it's not :( – kelo Sep 10 '12 at 11:10
  • I'm thinking that maybe I could use the `UncaughtExceptionHandler` just for generic `RuntimeException`s, which should be handled in a quite standard way (I can't think of any custom approach, and besides it would be an overkill)... or any other exception that will be handled in the same way, probably just parameterizing the error message (e.g. `DataAccessException`, I think). – kelo Sep 10 '12 at 11:16
  • I don't think that it is generally a good idea to act differently (I think the developers should be contacted for all program errors), but if you really want to this, I it is better to catch locally (you could parse the stack trace even in a generic handler, but that would not be elegant...). – lbalazscs Sep 10 '12 at 13:33
  • Thanks. I agree with you... but what if a `DataAccessException` is thrown due to a `IOException` or a `SQLException` (e.g. couldn't connect to DB due to external factors)? This wouldn't depend on either the user or the programmer. In this case I'd like to tell the user something like "There is a problem accessing the DB right now, please try later; if problem persists contact support.", I don't think I can do this using `UncaughtExceptionHandler`, can I? – kelo Sep 10 '12 at 14:03
  • Why not? if(e instanceof DataAccessException) { // handle it here, it doesn't matter which button caused it } – lbalazscs Sep 10 '12 at 14:26
0

If in the try block there are checked exceptions to catch, would it be better to nest a try/catch or to catch these checked exceptions after catching RuntimeException? (it probably depends, I don't even know if this is going to happen btw)

Just like you said it depends on whether it makes sense to execute the rest the code in the try block after the exception has been caught. If not then there is no point in nesting the try/catch blocks.

Bhesh Gurung
  • 48,464
  • 20
  • 87
  • 139
0

A good way to show the user something has gone wrong is to use JOptionPanes. Add to that good usage of the icons (information/error) and you're good to go. Here's some sample code for your reference:

http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html

You can consider some customization/abstraction classes over JOptionPane if you want to :)

As for handling multiple exceptions in the same way, if the message is going to be the same in all 3 KnownBusinessExceptions and KnownDataAccessExceptions then you could make sure that both classes have the same parentage and catch that one class. If the same handling is required for KnownBusinessExceptions and not KnownDataAccessExceptions, have all KnownBusinessExceptions with the same parent and all KnownDataAccessExceptions with the same parent.. Hope you get where I'm going with this.

javatarz
  • 1,144
  • 15
  • 30
  • Nothing new here, I know how to use JOptionPane and if I want to handle multiple exceptions in the same way, I surely won't do copy/paste. – kelo Sep 09 '12 at 18:35
  • 1
    Sorry, I misunderstood your question. @Ibalazscs' answer involving `UncaughtExceptionHandler` does what you require. At an application level, you can handle anything that goes uncaught. Say you want to do that at a screen level (where you're potentially expecting runtime exceptions to occur, you should add catches for those. Hope this helps :) – javatarz Sep 09 '12 at 18:40