2016-04-05 10 views
1

Ich möchte standard javax.validation für Eigenschaften und meine eigene Validierung für funktionale Validierungen verwenden. Die vereinfachte Unterklasse wie folgt aussieht:Wie verwende ich javax.validation (JSR303) für eine Basisklasse?

public class TestData extends AbstractData { 
    @NotNull 
    Long id = null; 

    @NotNull 
    Long value = null; 

    public Set<ConstraintViolation<TestData>> validateFunctional() { 
    Set<ConstraintViolation<TestData>> violations = new HashSet<>(); 
    if (id < 42 || value > 4711) { 
     //--- here comes another question: how do I create a constraint violation? 
    } 
    return violations; 
    } 
} 

Dies ist die Basisklasse:

public abstract class AbstractData { 
    public Set<ConstraintViolation<?>> validate() { 
    //--- First validate single properties 
    Set<ConstraintViolation<?>> violations = validator.validate(this); 
    } 
    //--- Single props OK => validate functional 
    if (violations.isEmpty()) { 
    violations.add(validateFunctional()); 
    } 
    return violations; 
} 

Gibt dem Fehler Mismatch

Typ: kann nicht von Set < ConstraintViolation <AbstractData> > konvertieren Set < EinschränkungViolation <? > >

+0

Es gibt keine Möglichkeit für den Compiler, den generischen Typ so abzuleiten, wie Sie es getan haben. – dambros

+0

Sie haben Recht. Der Compiler kann nicht von AbstractData in? Konvertieren. Aber wie kann ich diese Pseudo-Typ-Sicherheit loswerden? Es scheint mir, dass die Schnittstelle Validator.validate nur schlecht entworfen ist. Oder ich verstehe es einfach nicht ... –

Antwort

0

Ich glaube, das sein sollte, was Sie suchen:

public abstract class AbstractData<T> { 

    abstract T getObj(); 

    public Set<ConstraintViolation<T>> isValid(){ 
    //do your custom validations if needed 
    return Validation.buildDefaultValidatorFactory() 
      .getValidator().validate(getObj()); 
    } 
} 

POJO validiert werden:

public class Bar extends AbstractData<Bar> { 
    @NotNull 
    private Long id; 

    @NotNull 
    private Long value; 

    @CustomConstraint 
    private Long customConstraint; 

    @Override 
    public Bar getObj() { 
     return this; 
    } 
} 

Dann einfach bar.isValid() nennen.

EDIT:

In Bezug auf Ihre Frage zu einer benutzerdefinierten Einschränkung, können Sie es wie folgt tun:

@Constraint(validatedBy = {CustomConstraint.CustomConstraintValidator.class}) 
@Target({ElementType.FIELD, ElementType.PARAMETER}) 
@Retention(value = RetentionPolicy.RUNTIME) 
@Documented 
public @interface CustomConstraint { 

    String message() default "Invalid value"; 

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

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

    class CustomConstraintValidator implements ConstraintValidator<CustomConstraint, Long> { 

     @Override 
     public void initialize(CustomConstraint customConstraint) { 

     } 

     @Override 
     public boolean isValid(Long obj, ConstraintValidatorContext constraintValidatorContext) { 
      if (obj == null) 
       return false; 

      if (obj < 10) 
       return false; 

      return true; 
     } 
    } 
} 

In diesem Beispiel, wenn ich ein langes Feld mit @CustomConstraint mit Anmerkungen versehen und den Wert übergeben niedriger als 10 oder null, gibt der Validator einen Fehler zurück, andernfalls nicht. Die Validierung selbst ist in dem Beispiel nutzlos, ich habe einfach etwas aufgesetzt, das als Schnipsel für Sie dient, um deins zu bauen.

+0

Interessanter Ansatz. Die benutzerdefinierten Validierungen befinden sich jedoch in den Unterklassen und nicht in der Basisklasse. Um die wirklich seltsamen Generika in validator.validate zu überwinden, besteht Ihre Lösung darin, die Unterklasse als generischen Parameter für ihre eigene Basisklasse anzugeben, die auch die Methode "abstract T getObj()" benötigt, die einfach "this" zurückgibt. Ich hoffe wirklich, dass dieses JSR ein Update bekommt, das es nutzbar macht. Ich bin nicht auf der Suche nach einem benutzerdefinierten Validator, sondern stattdessen nach einem Code, der 'leicht' eine Constraint-Verletzung erzeugt, die ich zu dem Satz von Verletzungen hinzufügen kann. –

+0

Ich denke, vielleicht missverstehen Sie hier die ganzen Generika, denn ich sehe nichts falsch daran, wie es durch 'validate()' implementiert wird. – dambros

+0

Es ist nicht falsch. Es ist nur unnötig kompliziert ohne irgendwelche Vorteile. Der erste zu validierende Parameter() ist die zu validierende Bean. So kennt es die Klasse. Diese Pseudoart-Sicherheit ist nicht erforderlich. Ihre Lösung schlug vor, einen Getter in die Basisklasse einzufügen, nur um dem zu entsprechen. –

Verwandte Themen