Ich habe folgende Controller-Struktur:
abstrakte Klasse AbstractController {
// ...
}
abstrakte Klasse AbstractDiagramController erweitert AbstractController {
// ...
}
Klasse PopulationController erweitert AbstractDiagramController {
// ...
}
Die meisten Controller-Aktionen rufen verschiedene Methoden der abstrakten Basisklassen auf. Wenn nun eine dieser Basismethoden einen Redirect (oder Forward) an den Client senden muss, verhindert Grails nicht, dass die Anwendung den restlichen Aktionscode der Controller-Aktion trotzdem verarbeitet.
Von meinem Standpunkt aus ist dies ein unerwünschtes Verhalten, da die Basismethoden eine Art Validierung durchführen (wie die Validierung von Parametern, Benutzern, Sitzungen usw.) und der Controller davon ausgeht, dass die Validierung erfolgreich war (und daher nachfolgende Fehler produziert).
Wie kann ich dieses unzureichende Verhalten verhindern?
Mit freundlichen Grüßen, Christopher
PS: Ich habe bereits diese Frage gefunden, aber die Antworten haben mich nicht zufriedengestellt, da sich keine davon mit einem Basiskontroller befassen:
PPS: Ich benutze Grails in der Version 1.3.7
EDIT
Dies ist eine Reaktion auf die Kommentare von Victor Sergienko. Hier gebe ich ein detaillierteres Codebeispiel meines Problems.
// Der Basiskontroller
abstrakte Klasse AbstractController {
// Der Interceptor wird aufgerufen, bevor eine Aktion der Ableiter verarbeitet wird
def beforeInterceptor = [action:this.&initialize]
// Methode validiert verschiedene Dinge
protected initialize() {
if( someThingIsWrong() ) {
// Dieser Redirect sollte jeden anderen Code der Ableiter stoppen
redirect( controller: "foo", action: "bar" )
return false
}
}
}
// Der zweite Basiskontroller
abstrakte Klasse AbstractDiagramController erweitert AbstractController {
// Dieses Objekt muss initialisiert werden. Wenn nicht (z. B. bei Fehlern oder Ausnahmen)
// dürfen alle Aktionen der Ableiter nichts tun
MyObject myGreatObject = null
// Überschrieben wegen zusätzlicher individueller Diagrammvalidierung
@Override
protected initialize() {
// Zuerst Elternstuff machen
super.auth()
// Wenn Eltern fehlgeschlagen sind, sollte dieser Code nicht mehr ausgeführt werden.
// Ja, hier könnte ich überprüfen, ob Eltern false zurückgegeben haben und ebenfalls false zurückgeben, bevor
// ich die nächste Validierung fortsetze. So oder so muss ich das tun, weil Grails verständlicherweise
// eine Ausnahme wirft, wenn zwei Redirects hintereinander ausgeführt werden.
// (Damit möchte ich nur das Verhalten verdeutlichen, das ich erwarten würde)
if( someThingElseIsWrong() ) {
redirect( controller: "hello", action: "world")
return false
}
// Nach der Validierung kann ich das Objekt initialisieren
myGreatObject = new MyObject()
}
}
// Eine Controllerimplementierung
Klasse MyDiagramController erweitert AbstractDiagramController {
// Überschrieben wegen individueller Validierung
@Override
protected initialize() {
// Zuerst Elternstuff machen
boolean succeeded = super.auth()
// Wieder ärgerliche Doppelüberprüfung
if( !succeeded ) {
return false
}
}
def myAction = {
myGreatObject.SpinAroundAndBeHappy()
}
}
Sieht so aus, als ob es eine gute Idee war, den Anwendungsfall auf das Minimum an Codezeilen zu reduzieren. Jetzt scheint es, als könnten die Vorschläge von Victor (entweder canContinue
oder hasErrors
) dieses unangenehme Umstände irgendwie lösen, auch wenn es eine Art Workaround ist.
Aber irgendwie mag ich diese doppelten Überprüfungen nicht. Ich kämpfe immer noch gegen die Tatsache, dass alle Schichten über dem abstrakten Basiskontroller auf ungültige Validierungen reagieren müssen, die bereits zuvor aufgetreten sind (und auch von den Basiskontrollern selbst verwaltet werden sollten). Aus meiner Sicht sollten diese Überprüfungen nicht in den Implementierungen des Controllers liegen.
PS: Ich hoffe, es sind keine schwerwiegenden Fehler im Code aufgetreten.