Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden
0800 1 255 255

Grails: Validierung nach Maß

Die Validierung von Attributen direkt in Domain-Klassen durch­zu­füh­ren ist nicht nur prak­tisch, son­dern spart auch an man­cher Stelle auf­wän­di­ges Exception-Handling. Mit ein­fa­chen Mitteln ist man in der Lage die Korrektheit der über­ge­be­nen Variablen zu über­prü­fen, bei Bedarf auch gleich mit einer loka­li­sier­ten Fehlermeldung.

Die klassische Variante

Zur Einführung wird zunächst eine simple Klasse mit ent­spre­chen­den Constraints erzeugt:

class User {
  String login
  String surname
  String lastname
  static constraints = {
    login(size:5..8,blank:false)
    surname(minSize:3, blank:false)
    lastname(minsize:3, blank:false)
  }
}

Beim Aufruf der Methoden save() bzw. validate() wer­den die gesetz­ten Werte über die Constraints über­prüft und ein even­tu­el­ler Fehler samt dem zuge­hö­ri­gen Klassen-Attribut im Objekt selbst hin­ter­legt. Beim stan­dard­mä­ßi­gen Aufruf einer .gsp kön­nen diese Fehler dann aus­ge­ge­ben wer­den. Im fol­gen­den Listing ist diese Funktion am Beispiel einer Service-Klasse dar­ge­stellt:

class UserService {
  ...
    User user = new User(login:"myLogin", surname:"hans", lastname:"m")
    if(!user.validate()) {
      user.errors.hasErrors.each {
        println "-> Error: " + it.getField()
      }
    }
    user.save()
  ...
}

Das Speichern des User-Objektes würde im obe­ren Fall fehl­schla­gen und auf der Konsole der Name des inva­li­den Feldes auf­tau­chen. Da Domain-Klassen in der Regel aber etwas kom­ple­xer sind, zeigt das nächste Listing die Auslagerung des Nutzernamens in einer sepa­ra­ten Klasse:

class UserName {
  String surname
  String lastname
  static constraints = {
    surname(minSize:3, blank:false)
    lastname(minsize:3, blank:false)
  }
}
class User {
  String login
  UserName name
  static constraints = {
    login(size:5..8,blank:false)
    name(nullable:false)
  }
}

Die Klasse User kann nun mit den Standard-Mechanismen den über­ge­ben 'UserName' auf "null" prü­fen. Leider ist es aber nicht ohne wei­te­res mög­lich bei einem über­ge­be­nen Objekt die dort vor­han­de­nen Fehler in die eigene Fehlerliste zu über­neh­men.

class UserService {
  ...
    UserName userName = new UserName(surname:"hans", lastname:"m")
    userName.save()
    User user = new User()
    user.login = "myLogin"
    user.name = userName
    if(!user.validate()) {
      user.errors.hasErrors.each {
        println "-> Error: " + it.getField()
      }
    }
    user.save()
  ...
}

Kaskadierende Validierung

Im obe­ren Beispiel wird der ungül­tige Nachname nicht als feh­ler­haf­tes Feld aus­ge­ge­ben. Abhilfe schafft hier ein eige­ner Validator:

class User {
  String login
  UserName name
  static constraints = {
    login(size:5..8,blank:false)
    name(nullable:false, validator :{ val, obj ->
      if(obj && val) {
        if(!val.surname) {
          return ["invalid.surname"]
        }
        if(!val.lastname) {
          return ["invalid.lastname"]
        }
      }
    })
  }
}

Den ent­spre­chen­den Fehlertext kann man nun unter dem Schlüssel user.name.invalid.surname bzw. user.name.invalid.lastname in der messages.properties hin­ter­le­gen und bekommt diese Meldung dann auch nach einer Validierung ange­zeigt. Auf der zuge­hö­ri­gen GroovyServerPage sollte nun neben der Fehlermeldung auch das ent­spre­chende Feld (in die­sem Fall "name") auto­ma­tisch farb­lich her­vor­ge­ho­ben sein.

Related Posts

Pin It on Pinterest