2

I wish to handle Exceptions in a meaningful way in a Swing application.

The following is inside an actionPerformed method. The UiUtils#showError displays a JOptionPane with a button that shows/hides the stack trace. ApplicationException is a custom class to translate low level Exceptions to something a user would understand.

One issue is that I'm not sure how to handle a NullPointerException that propagates up if a user doesn't select a file in the JFileChooser before this code. The exportData method purposefully checks for null on entry so no file handling is done.

Also, it seems that it would be a good approach to wrap a low level Exception (from the data layer for example). I'd like to modify ApplicationException to keep an instance instead of doing this in the showError method.

Finally, there's one thing that's bothering me and that's the possibility that a few Exceptions could happen simultaneously. I have no idea how to handle this so I'm open to any suggestions.

try {
    dataService.exportData(list, selectedFile);
} catch (IOException e) {
    UiUtils.showError(new ApplicationException("Input/Ouput error"), e );
} finally {

    if( list == null){
        UiUtils.showError(new ApplicationException("No data to export"), null );
    }

    if( selectedFile == null ){
        UiUtils.showError(new ApplicationException("No file selected"), null );
    }       
}
James P.
  • 19,313
  • 27
  • 97
  • 155

3 Answers3

2

To catch NullPointerException (or any RuntimeException for that matter) as well as your IOExceptionjust catch the most general exception type:

try {
   dataService.exportData(list, selectedFile);
} catch (Exception e) {
   UiUtils.showError(new ApplicationException(e), e );
} finally {
  ...
}

You can wrap the original exception into your ApplicationException by adding it as a "cause" parameter to the constructor, e.g.:

public class ApplicationException extends RuntimeException {

   public ApplicationException(Exception cause) {
       super(cause);
   }

   ...
}

Then the original exception would be always available via the getCause() method.

If you program is not multithreaded, I wouldn't worry about simultaneous exceptions.

Sasha O
  • 3,710
  • 2
  • 35
  • 45
1

For reference, nothing happens "simultaneously" on the event dispatch thread; the EventQueue enforces this. Moreover, Swing restarts the EDT on uncaught exceptions, but you can substitute your own handler, as shown here.

Addendum: @Sasha O has helpfully addressed the question directly. Alternatively, if you can arrange never to call the method with a null file handle, you can assert that fact as a precondition. See Programming With Assertions for details.

This leaves me wondering in what cases inputs should be checked before a method call or inside a method.

A lot depends on the design. Instead of dealing with "No file selected," disable affected controls until a valid file has been selected. Instead of dealing with "No data to export," filter files by type, size or content in the chooser dialog. You still have to deal with I/O faults, but that's inevitable, as they are external to your program.

Addendum: This raises the problem of helping the user understand why a control is disabled. Some applications use a status bar to show such information. A tooltip can help, as shown here, even on a disabled control.

You should not use assertions to check the parameters of a public method.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Sorry about the old link, but that's when assertions were introduced. Any newer suggestions? – trashgod Apr 25 '11 at 02:20
  • Interesting bit of info there about the EDT. I've already added an `UncaughtExceptionHandler`. Assertions do seem to be a good idea in that it's needless to pass null arguments to a method. This leaves me wondering in what cases inputs should be checked before a method call or inside a method. – James P. Apr 25 '11 at 03:17
  • nothing changed in the realm of java asserts, afaik. Then and now, checking preconditions is exactly what they are _not_ for ;-) – kleopatra Apr 25 '11 at 10:51
  • @kleopatra: Thanks for commenting on this. As noted in the article, one should _not_ use assertions to check the parameters of a public method. The goal should be to not throw an exception at all. – trashgod Apr 25 '11 at 12:24
1

Users don't understand exceptions however nicely you coat or layer them ;-) Design every end-user targeted application in a way that there are none. And keep in mind that exceptions are for .. well .. exceptional state, nothing else.

F.i, empty selection is a perfectly valid state of a ui which allows to select something (and act on the selected item). If acting on empty-selection bubbles up as a NPE, the acting logic is incorrect - it must cope with any valid state. One option to cope might be to be disabled (as trashgod already suggested), another might be to show a warning label as long as there's nothing selected.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • 1
    Good point: some applications use a status bar or tooltip to guide the user on why a control is disabled. – trashgod Apr 25 '11 at 12:27