title: Catch Exception thrown by a SwingWorker located in a different class
body: <p>I have a main class <code>Gui</code> that handles my GUI and calls a few SwingWorkers (calls to DB and other data sources) that have been put in their own class <code>TablesDataManager</code>. My issue is that when one of those swingworkers throws an exception within its done90 method (i.e. on the EDT), I want to be able to catch it somehow in the main class and act accordingly (call <code>showErrorAndExit</code> in my SSCCE below).</p>
  
  <p>Any ideas would be welcome.</p>
  
  <p>Gui.java</p>
  
  <pre><code>import java.awt.event.WindowEvent;
  import javax.swing.*;
  
  public class Gui extends JFrame {
  
      private final JLabel waitLabel = new JLabel();
      private final JPanel panel = new JPanel();
      private final TablesDataManager tblData = new TablesDataManager();
  
      /**
      * @param args the command line arguments
      */
      public static void main(String args[]) {
          java.awt.EventQueue.invokeLater(new Runnable() {
  
              public void run() {
                  createAndShowGui();
              }
          });
      }
  
      private static void createAndShowGui() {
          Gui frame = new Gui("My Great GUI");
          frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
          frame.pack();
          frame.setVisible(true);
      }
  
      public Gui(String title) {
          super(title);
          panel.add(waitLabel);
          setContentPane(panel);
          try {
              initData();
          } catch (Exception e) {
              showErrorAndExit(e);
          }
      }
  
      //I WANT TO CALL THIS METHOD IF done() THROWS AN EXCEPTION
      private void showErrorAndExit(Exception e) {
          JOptionPane.showMessageDialog(this,
                  "An unexpected error occured while initialising the tables. The application will close.\n"
                  + (e.getMessage() == null ? "" : e.getMessage()),
                  "Unrecoverable error",
                  JOptionPane.ERROR_MESSAGE);
          this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
      }
  
      private void initData() {
          waitLabel.setText("Loading Data");
          tblData.initData(new Runnable() {
  
              public void run() {
                  initTables();
              }
          });
      }
  
      private void initTables() {
          waitLabel.setText("Loading Tables");
          tblData.initTables(new Runnable() {
  
              public void run() {
                  finishComponentsSetup();
              }
          });
      }
  
      private void finishComponentsSetup() {
          waitLabel.setText("We are done");
      }
  }
  </code></pre>
  
  <p>TablesDataManager.java</p>
  
  <pre><code>import java.beans.PropertyChangeEvent;
  import java.beans.PropertyChangeListener;
  import java.io.IOException;
  import java.util.concurrent.ExecutionException;
  import javax.swing.SwingWorker;
  
  class TablesDataManager {
  
      private final InitData initData = new InitData();
      private final InitTables initTables = new InitTables();
  
      void initData(final Runnable runAfterInit) {
          launchWorker(initData, runAfterInit);
      }
  
      void initTables(final Runnable runAfterInit) {
          launchWorker(initTables, runAfterInit);
      }
  
      private void launchWorker(final SimpleSwingWorker worker, final Runnable runAfterWorkerDone) {
          worker.addPropertyChangeListener(new PropertyChangeListener() {
  
              @Override
              public void propertyChange(PropertyChangeEvent evt) {
                  if (evt.getPropertyName().equals("progress")) {
                      if (worker.getProgress() == 100) { //update finished
                          runAfterWorkerDone.run();
                      }
                  }
              }
          });
          worker.execute();
      }
  
      private class InitData extends SimpleSwingWorker {
  
          @Override
          protected Void doInBackground() throws Exception {
              //do something in the background
              //unfortunately there is a connection problem
              throw new IOException("Can't connect to database...");
          }
      }
  
      private class InitTables extends SimpleSwingWorker {
  
          @Override
          protected Void doInBackground() throws Exception {
              //do something else in the background
              return null;
          }
      }
  
  
      private abstract class SimpleSwingWorker extends SwingWorker&lt;Void, Void&gt;  {
  
          @Override
          protected abstract Void doInBackground() throws Exception;
  
          @Override
          public void done() {
              try {
                  get();
                  setProgress(100);
              } catch (ExecutionException | InterruptedException e) {
                  System.out.println("Got that?");
                  //WHAT DO I DO WITH IT???
                  throw new RuntimeException(e);
              }
          }
      }
  }
  </code></pre>