Ich hoffe, Sie sind gut in das Jahr 2012 gestartet und haben weiterhin Lust auf Swing. Wie an anderer Stelle bereits gesagt wird es natürlich auch weiterhin andere Themen, zum Beispiel rund um Android und Mobile Computing geben. Das Speichern von (neu eingegebenen) Kategorien ist bisher recht schlampig implementiert:

// FIXME: refactor code to SwingWorker
Category cat = DTOFactory.createCategory(text);
if (categoriesModel.addCategory(cat)) {
  if (categoryDelegate.save(cat)) {
    break;
  }
}
Application.showErrorMessage(MessageFormat.format(
    Application.getString("string.error_new_category"),
    text));

Analog zum Löschen von Kategorien lässt sich dies sehr schön in einen Worker auslagern.

Category c = DTOFactory.createCategory(text);
_new _SaveCategoryWorker(c, categoriesModel,
    categoryDelegate).execute();

Ich finde, das sieht wesentlich aufgeräumter aus. Hier die Implementierung des Workers:

public class SaveCategoryWorker extends SwingWorker < Boolean, Void > {
    private final Category c;
    private final CategoriesModel m;
    private final CategoryDelegate d;

    public SaveCategoryWorker(Category c, CategoriesModel m, CategoryDelegate d) {
        this.c = c;
        this.m = m;
        this.d = d;
    }

    @Override
    protected Boolean doInBackground() throws Exception {
        boolean result = d.save(c);
        return new Boolean(result);
    }

    @Override
    protected void done() {
        Boolean result = Boolean.FALSE;
        try {
            result = get();
        } catch (InterruptedException e) {
            handleException(e);
        } catch (ExecutionException e) {
            handleException(e.getCause());
        } finally {
            if (Boolean.TRUE.equals(result)) {
                m.addCategory(c);
            }
        }
    }

    private void handleException(Throwable t) {
        Application.showErrorMessage(t.getLocalizedMessage());
        t.printStackTrace();
    }
}

Wenn Sie dies mit dem Worker aus dem vorangehenden Post vergleichen, stellen Sie viele Gemeinsamkeiten fest. Der Konstruktor und die Methode handleException() sind identisch. Es liegt nahe, beides in eine abstrakte Elternklasse auszulagern.

public abstract class AbstractCategoryWorker extends SwingWorker <Boolean, Void> {
    protected final Category c;
    protected final CategoriesModel m;
    protected final CategoryDelegate d;

    public AbstractCategoryWorker(Category c, CategoriesModel m,
        CategoryDelegate d) {
        this.c = c;
        this.m = m;
        this.d = d;
    }

    public abstract void doneIfTrue();

    public abstract String getStringForErrorLine1();

    @Override
    protected void done() {
        Boolean result = Boolean.FALSE;
        try {
            result = get();
        } catch (InterruptedException e) {
            handleException(e);
        } catch (ExecutionException e) {
            handleException(e.getCause());
        } finally {
            if (Boolean.TRUE.equals(result)) {
                doneIfTrue();
            }
        }
    }

    private void handleException(Throwable t) {
        String msg = t.getLocalizedMessage();
        if ((msg == null) || (msg.length() < 1)) {
            msg = t.getClass().getName();
        }
        Application.showErrorMessage(MessageFormat.format("{0}\n{1}",
            getStringForErrorLine1(), msg));
        t.printStackTrace();
    }
}

Die Methode handleException() gibt den Klassennamen der Ausnahme aus, wenn getLocalizedMessage() einen Leerstring oder null liefert. Dies war in früheren Versionen meiner Methode noch nicht so (robust) implementiert. Außerdem ist die Fehlermeldung nun zweizeilig. Die erste Zeile wird durch Aufruf der Methode getStringForErrorLine1() ermittelt. Zum Abschluss die deutlich abgespeckte Fassung der Klasse SaveCategoryWorker:

public class SaveCategoryWorker extends AbstractCategoryWorker {
  public SaveCategoryWorker(Category c, CategoriesModel m, CategoryDelegate d) {
    super(c, m, d);
  }

  @Override
  protected Boolean doInBackground() throws Exception {
    boolean result = d.save(c);
    return new Boolean(result);
  }

  @Override
  public void doneIfTrue() {
    m.addCategory(c);
  }

  @Override
  public String getStringForErrorLine1() {
    return MessageFormat.format(
        Application.getString("string.errornewcategory"),
        c.getDescr());
  }
}

This is a (slightly updated) repost of a piece I published on my blog Tommi’s Blog. I deleted the blog in the wake of the GDPR, so the original version is no longer available, or only through the WayBack Machine of the Internet Archive. Please note: code usually has not been updated, so language feature reflect the time the original post was written.