2010-03-18 9 views
13

Ich muss eine benutzerdefinierte Constraint-Annotation erstellen, die auf den Wert eines anderen Feldes meiner Bean zugreifen kann. Ich verwende diese Annotation, um das Feld zu validieren, da es vom Wert des anderen abhängt, aber die Art, wie ich es definiere, sagt der Compiler "Der Wert für das Annotationsattribut" meines Feldes "muss ein konstanter Ausdruck sein".Variables Feld in einer Constraint-Annotation

Ich habe es auf diese Weise definiert:

@Target(ElementType.FIELD) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy=EqualsFieldValidator.class) 
@Documented 
public @interface EqualsField { 
    public String field(); 

    String message() default "{com.myCom.annotations.EqualsField.message}"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 
} 

public class EqualsFieldValidator implements ConstraintValidator<EqualsField, String>{ 

    private EqualsField equalsField; 

    @Override 
    public void initialize(EqualsField equalsField) { 
     this.equalsField = equalsField;  
    } 

    @Override 
    public boolean isValid(String thisField, ConstraintValidatorContext arg1) { 
     //my validation 
    } 

} 

und in meiner Bohne möchte ich etwas wie folgt aus:

public class MyBean{ 

    private String field1; 

    @EqualsField(field=field1) 
    private String field2; 
} 

Gibt es eine Möglichkeit die Anmerkung zu definieren, so dass der Wert Feld eine Variable sein?

Dank

+0

Hallo, kann u den Arbeitscode teilen? Es wird sehr hilfreich sein. Selbst ich habe das gleiche Problem. –

Antwort

13

Am einfachsten gehen Sie einen Schritt zurück: Der Constraint/Validator, den Sie geschrieben haben, funktioniert auf Feldebene, aber was Sie erzwingen wollen, ist eine Cross-Field-Abhängigkeit, also eine Einschränkung auf Klassenebene.

Schreiben Sie Ihre Einschränkung und den Validator neu, um auf Klassenebene zu arbeiten (d. H. Die Annotation wird in der Klasse und nicht auf dem Feld ausgeführt). Auf diese Weise erhalten Sie Zugriff auf die gesamte Klasse. Führen Sie in Ihrer isValid (..) -Methode einfach die beiden Felder aus, vergleichen Sie sie und geben Sie sie entsprechend zurück.

+0

Es funktioniert auf diese Weise, obwohl ich den Validierungsfehler mit einem der Felder verknüpfen muss und wenn ich das ganze Objekt validiere, bekomme ich einen Fehler für das ganze Objekt anstelle eines Fehlers für das Feld, aber trotzdem danke. – Javi

+0

Nein, das ist nicht der Fall. Mit dem zweiten Argument der isValid-Methode ConstraintValidatorContext können Sie dieses Verhalten überschreiben. Sie können die addError() -Methode dazu verwenden, um anzugeben, dass der Fehler in einem bestimmten Feld angezeigt werden soll, sowie den Standardfehler auf Klassenebene zu entfernen. – GaryF

0

Wie der Compiler die Anmerkungen konstant sein muß nun (dh der Wert zum Zeitpunkt der Kompilierung bestimmen kann.) Wenn ich es vermute ich richtig sieht aus wie Sie diese Anmerkung, dass die Werte zu bezeichnen, verwenden von Diese Felder sollten gleich sein, wenn sie durch den Equal Field Validator laufen. Ein Ansatz, den Sie verwenden könnten, ist die Reflexion. Statt mit dem Wert, mit Anmerkungen versehen mit dem Feldnamen statt mit Anmerkungen versehen zu versuchen

public class MyBean{ 

    private String field1; 

    @EqualsField("field1") 
    private String field2; 
} 

Dann in Ihrem Validator Sie den Namen des Feldes und Nutzung Reflexion lesen kann für den Zugriff auf das

Object o = object.getClass().getDeclaredField(annotationValue).get(object); 
o == object.(field with annotation) OR 
o.equals(object.(field with annotation)); 

Je nachdem, was Sie versuchen zu tun, müssen Sie möglicherweise Logik basierend auf dem Feldtyp hinzufügen, aber immer noch das gleiche allgemeine Prinzip.

+0

OK, aber wie kann ich auf das Objekt zugreifen, in dem sich die Annotation im EqualsFieldValidator befindet? – Javi

+0

Das geht leider nicht. – GaryF

Verwandte Themen