2011-01-04 8 views
8

Ich habe einen benutzerdefinierten Bean-Validator, der überprüft, ob ein bestimmtes Feld in einer Entität für einige Bedingungen eindeutig ist. Wenn die Validierung fehlschlägt, sollte die Nachricht ein Feld (z. B. die ID) der bereits existierenden Entität enthalten. So sollte zum Beispiel die Nachricht sein:Validierungsspezifische Parameter in Bean-Validierungsnachricht interpolieren

"Product 42 already has such a value defined, choose a unique value." 

Ist dies mit Bean Validierung möglich?

AFAICS kann die Nachrichtenformat-Parameter enthält, wie zum Beispiel:

"Length must be between {min} and {max}." 

Aber das "statische" Attribut der Validierung Annotation nur verweisen kann, in diesem Fall:

@Size(min=1, max=16) 
private String name; 

In Mein Fall, der Wert ist nur innerhalb isValid meines benutzerdefinierten Validators bekannt.

Antwort

2

Sie haben Recht! Und für was Sie wollen !, können Sie Constraint-Verletzung Nachricht innerhalb der IsValid() -Methode erstellen. Zu diesem Zweck sollte die Annotation der Abhängigkeiten für bestimmte Klassen spezifisch sein, auf die sie angewendet wurde, und es sollte sich um Validierungseinschränkungen auf Klassenebene handeln. Innerhalb von isValid können Sie vor dem Zurückgeben von false bei fehlgeschlagener Validierung eine Nachricht erstellen, die den Wert der Klasseninstanz enthält. Zum Beispiel:

@check class Test{ int id; @validations...on fields}. 

public boolean isValid(Test value, ConstraintValidatorContext context) 
{ 
// your check logic 
context.disableDefaultConstraintViolation(); 
context.buildConstraintViolationWithTemplate("It should be different for(custom message) .."+ value.id).addConstraintViolation(); 
return false; // based on constraint filure. 

} 

Aber ich denke, dass Sie dies mit Anmerkungen auf Feldebene tun möchten! Ich habe keine Ahnung, dass ich mich auf deine Ergebnisse freue.

+0

Das Problem ist, dass ich nicht die endgültige Nachricht im Validator, nur ein Format (für Übersetzungen) und Parameter erstellen will. Aber ich vermute, dass ich die Nachricht im Validator lokalisieren soll. – robinst

+0

Ich habe die Lösung, die wir gefunden haben, als eine andere Antwort veröffentlicht. Aber ich denke, Ihre Antwort ermöglicht spezifischere Fehlermeldungen, selbst wenn die Lokalisierung innerhalb des Validators vorgenommen werden muss, akzeptierte ich sie. – robinst

0

Es ist nicht wirklich die schönste Lösung, aber was landeten wir tun so etwas wie die folgenden zu unseren Top-Level-Exception-Handling-Code wurde hinzugefügt:

String getConstraintViolationMessages(ConstraintViolationException e) { 
    StringBuilder sb = new StringBuilder(); 
    for (ConstraintViolation<?> violation : e.getConstraintViolations()) { 
     sb.append(getMessage(violation)); 
     sb.append("\n"); 
    } 
    sb.setLength(sb.length() - 1); 
    return sb.toString(); 
} 

String getMessage(ConstraintViolation<?> violation) { 
    String key = violation.getMessageTemplate(); 
    String messageFormat = localize(key); 

    Object entity = violation.getRootBean(); 
    String identifier; 
    if (entity instanceof PrimaryKeyed) { 
     identifier = String.valueOf(((PrimaryKeyed) entity).getId()); 
    } else { 
     identifier = entity.toString(); 
    } 

    return MessageFormat.format(messageFormat, identifier); 
} 

Beachten Sie, dass PrimaryKeyed eine benutzerdefinierte Schnittstelle, die auf verwendet wird unsere Entitäten. Wir haben auch einige andere Schnittstellen und benutzerdefinierte Handhabung oben nicht gezeigt.

+0

In welcher Klasse sitzen diese beiden Methoden? Meine benutzerdefinierte Einschränkung mit einem 'context.buildConstraintViolationWithTemplate (" {no.mobitroll.rest.resources.enities.validators.QuizType.enum} "). AddConstraintViolation();' interpoliert den Wert noch nicht. – Stephane

+0

@Stephane Wir haben sie in einer Top-Level-Exception-Handler-Klasse, was wahrscheinlich auch eine gute Sache ist. Wo du das hinzufügst, hängt wirklich von deiner Architektur und von den Rahmen ab, die du verwendest, also kann ich leider nicht wirklich eine spezifischere Antwort geben. – robinst