PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RequestDispatcher - nach forward() Abbruch?


eViL_oNe
09.07.2005, 01:45
Hallo (schon das zweite Prob am gleichen Tag, son scheiss ;) )

in meiner Webapp habe ich eine Helper Klasse für Servlets definiert, die unter anderem eine schlichte doError-Methode anbietet, die mit Hilfe von forward() vom RequestDispatcher auf eine Standard-JSP-Fehlerseite umleitet.

Jetzt ist mir aufgefallen (ich hätte wohl GENAUER die servlet-api studieren sollen ;) ), dass forward() keineswegs nach dem Dispatch-Vorgang die Abarbeitung im Servlet abbricht, wie ich das von Location: <newLocation> im HTTP Header gewohnt bin, sondern munter im Code weitermacht

schauen wir uns mal einen kleinen Codeabschnitt aus einem Servlet an, der so nicht korrekt ist:


//...
if ( something )
{
helper.doError( "Fehler1" ); // forward auf Fehlerseite
}
// weiterer Code
if ( something2 )
{
helper.doError( "Fehler2" ); // forward auf Fehlerseite
}


falls beide if-Statements zutreffen, gibt es beim zweiten doError eine IllegalStateException, da durch das erste Forward bereits Ausgabe betrieben wurde.

Natürlich könnte man hingehen und die beiden if-Abfragen verschachteln, so dass garantiert ist, dass nur ein einziges Mal doError aufgerufen wird - ob dies zu einer besseren Übersichtlichkeit führt, sei mal hier dahingestellt.

Bevor ich jetzt aber alle 38 Referenzen auf die Methode in meinem Projekt überprüfe, würde ich gerne wissen, ob es nicht eine Möglichkeit gibt, den Programmlauf (d.h. das Servlet) nach dem ersten forward zu beenden, ähnlich wie System.exit(exitCode) in normalen Java Apps.

Die JSP Seiten, auf die ich mit Hilfe von forward dispatche, bilden die Präsentationsschicht und den absoluten Endpunkt - danach braucht nix mehr gemacht zu werden - abgesehen vielleicht von einem finalize(), um die Datenbankverbindung zu trennen ;)

Any info?


MrEasy
09.07.2005, 01:59
wieso fügst du hinter
"helper.doError( "Fehler1" ); // forward auf Fehlerseite"
nicht einfach ein "return" ein?

eViL_oNe
09.07.2005, 02:02
nützt nix - damit beende ich die aktuelle Methode, allerdings nicht das komplette Servlet, in dem die Methode aufgerufen wird (die evtl. weitere Methoden aufruft)

DarkTom
09.07.2005, 18:40
Hmm, wie wäre es mit einer eigenen Exception-Klasse?

Statt dem
helper.doError("Fehler1")
ein
throw new ForwardException("Fehler1")

Auf der höchsten Ebene dann einen passenden catch-Block, der dann weiterleitet. Nur so ne Idee.

mhaller
09.07.2005, 20:51
Man soll doch Exceptions nicht für positive Logik einsetzen?


class Servlet {

public boolean doSomething1() {
if (error) {
doError();
return false;
}
//...
return true;
}


public ... execute() {

if (!doSomething!()) {
return errorforward;
}

return successforward;
}

}

DarkTom
10.07.2005, 18:43
Wieso positive Logik? Da tritt doch ein Fehler auf und die Berechnung soll mit sofortiger Wirkung abgebrochen werden. Die Fehlerbehandlung sieht so aus, dass der Fehler dem Benutzer mitgeteilt wird. Genau dafür sind die Dinger doch da.

mhaller
11.07.2005, 02:32
Exceptions sind für "Fehlerbehandlung" da, nicht, um die Ablauflogik der Anwendung zu steuern.

Stell dir vor, jemand würde eine "switch() case" Logik mit Exceptions realisieren. Das ist falsch und sollte nicht gemacht werden.

Sowas meinte ich:
try {
switch(blubb) {
case 1: throw new AblaufException(1);
default: throw new AblaufException(other);
}
} catch (AblaufException ae) {
if (ae.getValue()==1) {
doSometing();
} else {
doSomethingOther();
}
}

Und im Endeffekt ist es das, was ihr da vorschlagt: eine Exception für die Ablauflogik der Funktion einsetzen.

Wenn es wirklich um einen außerordentlichen Fehler handelt, ist natürlich nichts dagegen einzusetzen. Allerdings hört sich "ForwardException" eher nach Ablauflogik als nach ExceptionHandling an.

Da sollte man doch lieber ein throw new ThereWasSomeErrorException() einsetzen, und das dann in der Hauptmethode des Servlets abfangen, und *danach* dann die entsprechenden Schlüsse ziehen.

DarkTom
11.07.2005, 11:30
Na ok, die Namensgebung war vielleicht unglücklich. Mir fiel nur nichts besseres ein. Und ErrorException (was mir als erstes in den Sinn kam) wäre noch grausiger, da ein Error ja eigentlich nicht gefangen werden sollte.

Trotz des Namens hatte ich das auch wirklich nur für Fehlersituationen gedacht, nicht für ein positives forward.

Grundsätzlich sind wir uns also einig. :)

eViL_oNe
11.07.2005, 18:05
hmmm, genau der richtige Hinweis, DarkTom!

habe auch schon in die Richtung gedacht und lässt sich auch prima mit meiner Idee zur Servlet Hierarchie mit abstraktem Basisservlet koppeln!

sieht dann ungefähr so aus:


// Helper instantiieren
helper = new Helper( request, response );

if ( !authorized )
{
doShowHome();
}

try
{
...

// starten der eigentlichen Verarbeitung
doStartProcessing();
} catch ( ControlFlowException e )
{
helper.doError( e );
}


Falls jemand nen besseren Namen für meinen Exceptionwrapper hat, bin ich ganz Ohr - funktionieren tut es auf jedenfall ;)

@mhaller: meine Anwendung fängt nur wirklich ausserordentliche Fehler mit Hilfe von doError ab (z.B. gewünschte Resource existiert gar nicht, oder Zyklus beim Durchschreiten meiner Regionhierarchie entdeckt). Im Prinzip hast du aber vollkommen recht: Exception wird für Manipulation des Steuerflusses eingesetzt, allerdings eben nur in Ausnahmefällen ;)

"Normale" Fehler (z.B. Resourcenname existiert bereits) werden in einer HashMap<String, String> problems gesammelt und am Ende an der richtigen Stelle angezeigt.