I have a main class Gui that handles my GUI and calls a few SwingWorkers (calls to DB and other data sources) that have been put in their own class TablesDataManager. 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 showErrorAndExit in my SSCCE below).
Any ideas would be welcome.
Gui.java
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");
    }
}
TablesDataManager.java
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<Void, Void>  {
        @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);
            }
        }
    }
}
 
     
    