Exceptions behandeln

White_Fox

Top Contributor
Guten Abend allerseits

Folgendes Problem: Ich habe eine Klasse in etwa der Form:
Java:
public abstract class Command{

    public ArrayList<ModelChange> execute();
    
    public boolean isExecutable();
}

Ein Objekt (einer davon abgeleiteten Klasse natürlich) wird in meinem Programm von der View an den Controller übergeben. Der Controller führt die Methode execute() aus.

Jetzt habe ich schon einige Commandklassen auf diese Weise realisiert, und das Konzept gefällt mir soweit auch gut. Nun habe ich allerdings das Problem, das ich in der execute()-Methode eine Exception geworfen bekommen kann.

Ich kann die Exception in dieser Methode nicht behandeln. Im konkreten Fall könnte z.B. ein Pfad ungültig sein, und würde dem Benutzer einfach eine entsprechende Fehlermeldung präsentieren. Aber wie gesagt - das geht nicht innerhalb dieser Methode.

Am liebsten wäre mir, eine Art Kanal zum Controller zu öffnen und dort die Exception zu übergeben. Jezt wollte ich mal fragen, ob es da ein Standardverfahren gibt. Fehler würde ich gerne sowieso irgendwie protokollieren und z.B. in eine Logdatei schreiben.
Hat jemand eine Idee? In C gibt es ja die In-, Out-, und die Errpipe und ich vermute fast, in Java gibt es sowas wie System.err. Wäre so etwas für diesen Zweck geeignet? Oder habt ihr andere Vorschläge?
 

LimDul

Top Contributor
Wenn der controller eh die execute Methode ausführt, dann kannst du doch um die execute Methode ein try/catch machen und a die Exception behandeln?
 
K

kneitzel

Gast
Also wenn es erst einmal um das Logging geht: da würde ich zu einem Logging Framework raten. Wir nutzen auf Arbeit log4j, aber es gibt hier eine größere Auswahl ... alles was du machst, ist dann zu Loggen und über eine Konfiguration kannst du jederzeit angeben, wo welches Level irgendwohin geschrieben wird ...

Aber bezüglich der Fehlerbehandlung hilft das erst einmal nicht wirklich weiter. Da kann ich Dir aber im Augenblick auch keinen Hinweis geben, da ich derzeit keinen Überblick habe, was Du derzeit genau machst ..
 

sascha-sphw

Top Contributor
Wieso behandelt der Controller die Ausnahme nicht? Der ruft den Command doch auch auf.

Ich würde aber einen Mix anstreben. Wenn es eine Ausnahme gibt, die der Command selbst behandeln kann sollte er das auch machen.

Man könnte aber auch folgendes machen. In diesem Fall behandelt dann zwar der Command die Ausnahme, Du kannst aber dennoch darauf reagieren.
Java:
public abstract class Command{

    // exit code. Analog wie bei Prozessen.
    public int execute();
    
    public boolean isExecutable();
    
    // im Falle eines success exit codes kann hier das Ergebnis abgerufen werden.
    public List<ModelChange> getResult();
}
 

White_Fox

Top Contributor
Wenn der controller eh die execute Methode ausführt, dann kannst du doch um die execute Methode ein try/catch machen und a die Exception behandeln?
Ja, das wäre zwar naheliegend, gefällt mir aber aus mehreren Gründen nicht:
  1. Ich müßte schon in der execute()-Methode deklarieren, daß sie eine Exception werfen könnte. Das ist aber bei eher wenigen Klassen der Fall.
  2. Der Code im Controller, der die execute()-Methode aufruft, wird womöglich sehr groß werden wenn es (wenn auch wider Erwarten) viele Klassen mit Exceptions werden. Und dann wächst mir der Code wieder potentiell über alle Grenzen hinaus.
  3. Es erscheint mir auch aus strukturellen Gründen sinnvoll, Fehler gesondert abzufangen...zugegeben: Bauchgefühl.

Wieso behandelt der Controller die Ausnahme nicht? Der ruft den Command doch auch auf.
Nun: Eigentlich gehören die Commandobjekte durchaus zum Controller. Das, was der Controller eigentlich tun soll, habe ich in diese Klassen ausgelagert. Urpsrünglich aus zwei Gründen:
  1. Ich wollte die Aktionen gerne gekapselt haben. Um einerseits mit nichts durcheinander zu kommen, und um den Code übersichtlich zu halten.
  2. Um Aktionen zu trennen. Von der Klasse Command leite ich noch noch die (ebenfalls abstrakten Klassen ExecuteOnlyCommand - für Aktionen die nur ausgeführt werden wie z.B. Speichern und Laden von Dateien - und ReversableCommand. Letztere verfügen über eine Rückwärtsmethode, um genau ihre Aktion wieder rückgängig zu machen. Die Commandobjekte müssen dann nur noch in eine Queue gestopft werden und ich kann sehr einfach Benutzeraktionen wieder rückgängig machen oder wiederholen.
  3. Ein anderer Plan war auch, evt. die Commandobjekte zum Debugging zu benutzen. Und zwar, wenn Benutzer Probleme haben, Support anfragen, und ich die Probleme nicht nachstellen kann. Dann könnte ein Benutzer z.B. eine Log-Datei schicken, die - keine Ahnung, die letzten 20 Command-Objekte sowie die Modeldaten vor dem ersten Command-Objekt oder so - und ich kann den Fehler in aller Ruhe nachstellen.
Die Idee mit dem Successcode ist auch nicht schlecht, geht aber bei mir nicht mehr, da ich schon einen Rückgabewert habe.


Was hindert Dich daran?!?
Einfach der Umstand, daß ich noch keine rechte Idee habe wie ich das am Besten umsetzen soll. Und ich denke, hier müßte doch eigentlich schon fast jeder - zumindest die meisten - auf jeden Fall gerade du - dieses Problem doch schonmal gelöst haben.
Ich meine - jeder hier kann Programmieren. Außer ich. (Anfänger zählen nicht.) ;)
 

LimDul

Top Contributor
Ja, das wäre zwar naheliegend, gefällt mir aber aus mehreren Gründen nicht:
  1. Ich müßte schon in der execute()-Methode deklarieren, daß sie eine Exception werfen könnte. Das ist aber bei eher wenigen Klassen der Fall.
Nein, wenn du eine eigen, von RuntimeException abgeleitet Exception erstellst, muss du die nicht deklarieren
  1. Der Code im Controller, der die execute()-Methode aufruft, wird womöglich sehr groß werden wenn es (wenn auch wider Erwarten) viele Klassen mit Exceptions werden. Und dann wächst mir der Code wieder potentiell über alle Grenzen hinaus.
Irgendwo muss der Code ja hin und du kannst im Catch-Block an eine andere Methode delegieren.
  1. Es erscheint mir auch aus strukturellen Gründen sinnvoll, Fehler gesondert abzufangen...zugegeben: Bauchgefühl.
Ist es doch mit dem Catch-Block?

Um etwas konkreter zu werden - egal wie die Logik hinterher aussieht. Wie willst du die Fehler behandeln? Wie soll der Code aussehen und was soll er als Informationen bekommen?

Du kannst natürlich auch der Execute Methode des Commands einen Callback Consumer<Exception> mitgeben, die dann das Command aufruft, wenn eine Exception auftritt. Aber das ist fast nichts anderes, als ein try/catch um den execute Befehl und Aufruf der gleichen Methode (Gewichtiger Unterschied: Im ersten Fall muss die Methode noch eine sinnvolle Rückgabe machen, im zweiten nicht).
 

White_Fox

Top Contributor
Um etwas konkreter zu werden - egal wie die Logik hinterher aussieht. Wie willst du die Fehler behandeln? Wie soll der Code aussehen und was soll er als Informationen bekommen?
Nun, mein persönliches Wunschkonzert würde etwa so aussehen:

Java:
public class SomeVolatileCommand{
    @Override
    public ArrayList<ModelChange> execute() {
        try{
            //...
        }
        catch{
            Controller.err.sachDemNutzerDasGehtSoNicht();
        }
    }
}

Ok, danke...ich glaub ich weiß was ich ungefähr machen will.
 

LimDul

Top Contributor
Singelton riecht immer nach schlechten Design. Das riecht an der Stelle nach Zyklus (Controller kennt Commands, Commands kennen Controller), das will man nach möglichkeit vermeiden. Dann lieber per Callback-Interface.
 

mrBrown

Super-Moderator
Mitarbeiter
Zwei andere Möglichkeiten:

Nutz innerhalb der Commands Delegation.
Es gibt dann zB ein LoggingCommand, das loggt einfach nur was es bekommt oder zurück gibt, und ruft intern das wirkliche Command auf. Die Logik ist damit sowohl aus Controller als auch aus dem eigenen Command entfernt und vernünftig gekapselt.
Könnte man mit der anderen Möglichkeit kombinieren, das eigentlich Command ist dann "dumm" und wirft im Fehlerfall einfach nur Exceptions, der spezifische Wrapper "weiß", was er im Fehlerfall machen muss.


Oder explizite ExceptionHandler, ähnlich wie das zB Spring macht.
Das Command ist wieder "dumm" und wirft einfach die Exception, und im Controller gibt es einen catch-Block, der die Exception an die ExceptionHandler weiterreicht.
ExceptionHandler "registrieren" sich für eine Exception (oder auch eine Kombination aus Exception und Command), und wissen wie sie damit umgehen müssen.
 

White_Fox

Top Contributor
Ja, ein Interface hätte ich dafür schon vorgesehen.

Edit:
@mrBrown Gute Idee...das lasse ich mir auch nochmal durch den Kopf gehen.

Was ich mich jetzt gerade frage: Welche der vielen Antworten markiere ich jetzt als DIE Lösung? Was mache ich, wenn ich eine Antwort ausgewählt habe, und danach kommt postet jemand eine Lösung die mir vollkommen perfekt erscheint und die ich einfach nur noch kopieren und einfügen muß? Ich bin gerade unschlüssig.

Nichtsdestrotrotz: Vielen Dank an alle fürs mitdenken und posten und anregen. :)
 

sascha-sphw

Top Contributor
Vielleicht sowas?
Java:
public abstract class Command{

    protected Consumer<Exception> errorCallback;

    public Command() {
        this(null);
    }

    public Command(Consumer<Exception> errorCallback) {
        this.errorCallback = errorCallback;
    }

    public final List<ModelChange> execute() {
        List<ModelChange> result = new ArrayList<>();
        try {
            result = internalExecute();
        }
        catch (Exception e) {
            if(errorCallback != null) {
                errorCallback.accept(e);
            }
        }
        return result;
    }

    protected abstract List<ModelChange> internalExecute();

    public abstract boolean isExecutable();
}
 

mrBrown

Super-Moderator
Mitarbeiter
Was ich mich jetzt gerade frage: Welche der vielen Antworten markiere ich jetzt als DIE Lösung? Was mache ich, wenn ich eine Antwort ausgewählt habe, und danach kommt postet jemand eine Lösung die mir vollkommen perfekt erscheint und die ich einfach nur noch kopieren und einfügen muß? Ich bin gerade unschlüssig.
Meine natürlich :p


Das ist mMn potentiell die Art Frage, bei der es keine "richtige Lösung" gibt, wenn überhaupt müsste man jetzt warten, bis einer alle Möglichkeiten in einer Antwort inklusive Vor- und Nachteilen erläutert, was halt eher selten passiert.
Wenn es ne Frage bleiben soll, kann man alles hilfreich entsprechend markieren, das wäre sonst aber einer der Fälle, wo ich einfach von "Frage" auf "Diskussion" umschalten würde.


(Achso, wenn nachträglich eine bessere kommt, kann man das immer noch ändern, ist also nicht für die Ewigkeit)
 

White_Fox

Top Contributor
Also, ich denke ich mache das so:

Was ich vergessen habe euch mitzuteilen (sehts mir nach, ich habe diese Codeteile schon seit Januar nicht mehr angesehen weil ich mit dem Serialisierungskram beschäftigt war und vieles wieder vergessen habe): die Command-Objekte werden von einer Factory erzeugt.
Das habe ich gemacht weil die View die Commandobjekte ja irgendwie anfragen und präparieren muß (also im konkreten Fall hier den Speicherpfad übergeben und das Commandobjekt überhaupt erstellen), die Commandobjekte als Teil des Controllers natürlich das Model kennen, die View aber nichts vom Model wissen soll. Zumindest nicht von dem Teil des Models, der Änderungen erlaubt, um sich neue Daten zu holen gibt stellt das Model eigend ein View-Interface bereit das aber nur Lesezugriffe erlaubt.

Mein Plan sieht jetzt wie folgt aus:
Ich fahre einfach das gleiche Konzept weiter, wie ich es mit dem Model schon gehalten habe. Ich spendiere dem Controller ein ErrorHandler-Interface und gebe den Commandobjekten über die CommandFactory einfach neben dem Model auch noch den Controller (bzw. dessen ErrorHandler-Interface) mit.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Jose05 Umgang mit Exceptions in einen Programm Allgemeine Java-Themen 2
M Exceptions - wann / wie verwenden? Allgemeine Java-Themen 4
Kirby.exe Exceptions erklärt Allgemeine Java-Themen 5
L Operatoren Java Reflections: Alle Methoden einer Klasse aufrufen ohne Exceptions Allgemeine Java-Themen 5
E Java Editor Problem mit 2er Exceptions Allgemeine Java-Themen 12
B Maven Keycloak library wirft exceptions nach maven package Allgemeine Java-Themen 1
J Exceptions Allgemeine Java-Themen 1
Z Java Exceptions - Auf leeres Feld prüfen Allgemeine Java-Themen 10
E Exceptions abfangen und dann Programm stoppen - aber wie? Allgemeine Java-Themen 2
L Nullpointer Exceptions werden nicht angezeigt Allgemeine Java-Themen 5
V Exceptions Allgemeine Java-Themen 2
G Exceptions mit jre 7u40 Allgemeine Java-Themen 2
S Best Practice verschiedene Exceptions fangen und neue Exception erzeugen Allgemeine Java-Themen 11
E LookAndFeel Exceptions bei UIManager.setLookAndFeel Allgemeine Java-Themen 4
W JavaDoc Runtime-Exceptions: Wie sinnvoll anzeigen? Allgemeine Java-Themen 14
C Threads und Exceptions Allgemeine Java-Themen 7
B Webstart Exceptions Allgemeine Java-Themen 7
R Threads Exceptions von Threads abfangen im ThreadPool Allgemeine Java-Themen 5
S Runtime Exceptions in eine Datei schreiben Allgemeine Java-Themen 7
G Internationalisierung von Exceptions Allgemeine Java-Themen 5
J JUnit - werfen von Exceptions testen Allgemeine Java-Themen 17
F Alle Exceptions abfangen Allgemeine Java-Themen 4
B Alle Exceptions auf einmal abfangen Allgemeine Java-Themen 4
G log4j - Behandlung nicht explizit abgefangener Exceptions Allgemeine Java-Themen 5
B Logging von Exceptions Allgemeine Java-Themen 7
G Designfrage: Exceptions in Konstruktoren Allgemeine Java-Themen 7
I Exceptions - weder catch- noch finally-Klausel funktioniert Allgemeine Java-Themen 12
M Verwendung von unchecked exceptions & bereits vorhandenen exceptions was priorisieren Allgemeine Java-Themen 3
hdi Verhalten bei nicht behandelten Exceptions Allgemeine Java-Themen 2
H Exceptions und IO Allgemeine Java-Themen 17
B Exceptions? Allgemeine Java-Themen 4
D Throws Exceptions Allgemeine Java-Themen 14
M Verständnisfrage Exceptions Allgemeine Java-Themen 2
V Exceptions als Fehlerbehandlung "missbrauchen"? Allgemeine Java-Themen 10
DEvent Wie behandelt man Exceptions in Iterator? Allgemeine Java-Themen 2
J Verständnisfrage zu exceptions Allgemeine Java-Themen 3
A Junit Exceptions testen Allgemeine Java-Themen 3
R Loading-Thread und Exceptions abfangen. Allgemeine Java-Themen 4
P Exceptions dokumentieren. Allgemeine Java-Themen 6
G Exceptions weiterwerfen Allgemeine Java-Themen 2
T Generics und Exceptions Allgemeine Java-Themen 6
P Exceptions throw Allgemeine Java-Themen 6
F Wann und wie Exceptions einsetzen? Allgemeine Java-Themen 13
J Method.invoke -> Exceptions der Funktion abfangen Allgemeine Java-Themen 5
T Frage zu Exceptions Allgemeine Java-Themen 3
G Java-Exceptions werden nicht ganz angezeigt. Wo ändern? Allgemeine Java-Themen 3
J Probleme mit Exceptions Allgemeine Java-Themen 11
R Exceptions mit aktuellen Programminformationen ausgeben? Allgemeine Java-Themen 2
märliprinz com.sap.dbtech.jdbc.exceptions.JDBCDriverException Allgemeine Java-Themen 2
G Alle Exceptions loggen Allgemeine Java-Themen 4
G Frage zu Exceptions Allgemeine Java-Themen 6
M err oder alle Exceptions eines Programms abfangen Allgemeine Java-Themen 4
G Exceptions ohne Zeilennummer (Unknown Source) Allgemeine Java-Themen 8
T Exceptions im statischem Klassencode Allgemeine Java-Themen 5
J socket closed - wie behandeln. Allgemeine Java-Themen 2
B InterruptedException: Wie behandeln? Allgemeine Java-Themen 11
M Scanner-Methode: Mehrere Eingaben mit Exception behandeln Allgemeine Java-Themen 10

Ähnliche Java Themen

Neue Themen


Oben