2014-05-16 11 views
6

Ich habe eine Validierung Annotation von einem benutzerdefinierten ConstraintValidator implementiert geschrieben. Ich möchte auch sehr spezifische ConstraintViolation Objekte erzeugen, die Werte verwenden, die während des Validierungsprozesses während der Nachrichteninterpolation berechnet wurden.Erstellen von dynamischen ConstraintViolation Fehlermeldungen

public class CustomValidator 
    implements ConstraintValidator<CustomAnnotation, ValidatedType> { 

... 
    @Override 
    public boolean isValid(ValidatedType value, ConstraintValidatorContext context) { 
    // Figure out that the value is not valid. 
    // Now, I want to add a violation whose error message requires arguments. 
    } 
} 

Eine hypothetische Fehlermeldung in meiner Nachrichtenquelle:

CustomAnnotation.notValid = The supplied value {value} was not valid because {reason}. 

Der Kontext in das Verfahren isValid geleitet, um eine Einschränkungsverletzung, eine Schnittstelle sorgt für den Aufbau und die es schließlich auf den Kontext hinzugefügt wird. Allerdings kann ich nicht herausfinden, wie man es benutzt. Gemäß dieser documention für die Version, die ich verwende, kann ich Bean und Eigenschaftsknoten der Verletzung hinzufügen. Dies sind die einzigen zusätzlichen Details, die ich für die Verletzungsdefinition angeben kann, aber ich verstehe nicht, wie sie den Parametern in der Fehlermeldung zugeordnet werden können.

Millionen-Dollar-Frage: Wie kann ich dynamische Parameter mit einem benutzerdefinierten Validator an meine Validierungsfehlermeldungen übergeben? Ich möchte die {value} und {reason} Felder ausfüllen, die die ConstraintValidatorContext 's Schnittstelle für Gebäudeverletzungen verwenden.

Das Erhalten einer Instanz der Nachrichtenquelle und das Interpolieren der Nachricht innerhalb des benutzerdefinierten Validators ist keine Option - die aus der Validierung kommenden Nachrichten werden unabhängig von der Interpolation interpoliert und eine interne Interpolation führt dazu, dass einige Nachrichten zweimal interpoliert werden und möglicherweise vernichten Sonderzeichen oder andere Zeichen mit besonderen Bedeutungen in meiner Nachrichtendefinitionsdatei.

Antwort

10

Das ist mit der standardisierten Bean Valiation-API nicht möglich, aber es gibt einen Weg in Hibernate Validator, der BV-Referenzimplementierung.

Sie müssen die ConstraintValidatorContext in eine HibernateConstraintValidatorContext auszupacken, die Ihnen den Zugriff auf die addExpressionVariable() Methode gibt:

public class MyFutureValidator implements ConstraintValidator<Future, Date> { 

    public void initialize(Future constraintAnnotation) {} 

    public boolean isValid(Date value, ConstraintValidatorContext context) { 
     Date now = GregorianCalendar.getInstance().getTime(); 

     if (value.before(now)) { 
      HibernateConstraintValidatorContext hibernateContext = 
       context.unwrap(HibernateConstraintValidatorContext.class); 

      hibernateContext.disableDefaultConstraintViolation(); 
      hibernateContext.addExpressionVariable("now", now) 
       .buildConstraintViolationWithTemplate("Must be after ${now}") 
       .addConstraintViolation(); 

      return false; 
     } 

     return true; 
    } 
} 

Der Referenzanleitung für einige more details hat.

+1

Für die Aufzeichnung habe ich diese Antwort akzeptiert, weil Sie angegeben haben, dass dies nicht möglich ist. Das Beispiel aus der Dokumentation funktionierte für mich nicht, da meine Constraint-Verstoßvorlagen selbst Nachrichtencodes sind und ich nicht auf die benutzerdefinierten "Ausdrucksvariablen" in der letzten Nachricht zugreifen konnte. (Die Fehlermeldung war immer, dass der Code nicht aufgelöst werden konnte.) – Misha

Verwandte Themen