2012-01-06 17 views
32

Quale configurazione è necessaria per utilizzare le annotazioni da javax.validation.constraints come @Size, @NotNull, ecc.? Qui è il mio codice:Annotazioni da javax.validation.constraints non funzionanti

import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 

public class Person { 
     @NotNull 
     private String id; 

     @Size(max = 3) 
     private String name; 

     private int age; 

     public Person(String id, String name, int age) { 
     this.id = id; 
     this.name = name; 
     this.age = age; 
     } 
} 

Quando provo ad usarlo in un'altra classe, la convalida non funziona (cioè l'oggetto viene creato senza errori):

Person P = new Person(null, "Richard3", 8229)); 

Perché non questo si applica vincoli per id e name? Cos'altro devo fare?

+9

Non funziona per magia, è necessario configurare un validatore. In quale contesto è in esecuzione questo codice? – skaffman

risposta

38

Per JSR-303 validazione di fagioli di lavorare in primavera, è necessario diverse cose:

  1. MVC di configurazione dello spazio dei nomi per le annotazioni: <mvc:annotation-driven />
  2. Il JAR spec JSR-303: validation-api-1.0.0.GA.jar (sembra che tu abbia già quello)
  3. Un'implementazione della specifica, come ad esempio Hibernate Valida zione, che sembra essere l'esempio più comunemente utilizzati: hibernate-validator-4.1.0.Final.jar
  4. nel chicco da convalidare, annotazioni di convalida, sia dal JAR spec o dal vaso implementazione (che avete già fatto)
  5. Nel gestore voi desidera convalidare, annotare l'oggetto che si desidera convalidare con @Valid e quindi includere uno BindingResult nella firma del metodo per acquisire gli errori.

Esempio:

@RequestMapping("handler.do") 
public String myHandler(@Valid @ModelAttribute("form") SomeFormBean myForm, BindingResult result, Model model) { 
    if(result.hasErrors()) { 
     ...your error handling... 
    } else { 
     ...your non-error handling.... 
    } 
} 
+0

Questo ci fornisce la configurazione di default del validatore. Ora, mi piacerebbe configurare il validatore prima di essere utilizzato. Dove posso configurarlo? Qualche sovrascrittura da implementare o setter da chiamare? – Stephane

+2

Il problema che ho riscontrato è che non avevo capito che avevo bisogno di aggiungere '@ Valido' a ciascuna variabile membro, che era anche un oggetto che conteneva vincoli di validazione. – WhiteKnight

+0

Grazie signore, mi hai salvato ore di debugging. – Chad

19

È necessario utilizzare il Validator per verificare se la classe è valida.

Person person = ....; 
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
validator = factory.getValidator(); 
Set<ConstraintViolation<Person>> violations = validator.validate(person); 

Quindi, impostando le violazioni impostate, è possibile trovare le violazioni.

+0

Penso che questo sia perfettamente risposto indipendentemente dal framework utilizzato. grazie .. ma ho un dubbio, come possiamo convalidare un parametro che viene passato ad un metodo nel contesto senza alcun framework. per esempio. 'test (@NotNull String str)', possiamo scrivere il validatore per lo stesso? – agpt

5

Si si deve chiamare un Validatore su l'Entità se si desidera convalidarlo. Quindi otterrai un set di ConstraintViolationException, che in pratica mostra per quale/i campo/i della tua Entità c'è una violazione del vincolo e che cosa era esattamente. Forse puoi anche condividere parte del codice che ti aspetti di convalidare la tua entità.

Una tecnica spesso utilizzata consiste nel convalidare in @PrePersist e nella transazione di rollback se si utilizzano più modifiche ai dati durante la transazione o si eseguono altre azioni quando si riceve un'eccezione di convalida.

Il codice dovrebbe andare in questo modo:

@PrePersist 
public void prePersist(SomeEntity someEntity){ 
    Validator validator = Validation.buildDefaultValidatorFactory.getValidator(); 
    Set<ConstraintViolation<SomeEntity>> = validator.validate(someEntity); 
    //do stuff with them, like notify client what was the wrong field, log them, or, if empty, be happy 
} 
-1

Sono abbastanza nuovo per la primavera quindi per favore prendi la mia risposta con un pizzico di sale. Non ho nemmeno potuto far funzionare @NotNull quando l'ho usato.Avevo uno schermo con i campi di input, non l'ho compilato e ho spostato il mio schermo in avanti (per un eventuale salvataggio su qualche DB).

Mi stavo tormentando solo per inciampare su @NotBlank. Questa è stata la mia risposta comunque. Il campo in questione era vuoto, suppongo che fosse "" o una stringa vuota non nullo per dire. Quindi il controllo per @NotBlank è stato catturato.

Non sono sicuro se questo ti aiuterà, ma non può far male a indagare su questa possibilità se stai anche lottando con alcuni @NotNulls che non sono coinvolti.

1

nel mio caso ho avuto un vincolo a livello di classe personalizzato che non veniva chiamato.

@CustomValidation // not called 
public class MyClass { 
    @Lob 
    @Column(nullable = false) 
    private String name; 
} 

non appena ho aggiunto un vincolo a livello di campo per la mia classe, sia personalizzata o standard, il vincolo a livello di classe iniziato a lavorare.

@CustomValidation // now it works. super. 
public class MyClass { 
    @Lob 
    @Column(nullable = false) 
    @NotBlank // adding this made @CustomValidation start working 
    private String name; 
} 

sembra come comportamento buggy a me, ma abbastanza facile da aggirare i indovinare

+0

Grazie! Sto vedendo questo stesso comportamento. – Steve

-1

è necessario aggiungere @Valid a ogni membro variabile, che era anche un oggetto che conteneva la convalida vincoli.

0

Quindi @Valid all'interfaccia di servizio funzionerebbe solo per quell'oggetto. Se si dispone di ulteriori convalide all'interno della gerarchia dell'oggetto ServiceRequest, è possibile che sia necessario attivare in modo esplicito le convalide. Quindi questo è come ho fatto:

public class ServiceRequestValidator { 

     private static Validator validator; 

     @PostConstruct 
     public void init(){ 
     validator = Validation.buildDefaultValidatorFactory().getValidator(); 
     } 

     public static <T> void validate(T t){ 
     Set<ConstraintViolation<T>> errors = validator.validate(t); 
     if(CollectionUtils.isNotEmpty(errors)){ 
      throw new ConstraintViolationException(errors); 
     } 
    } 

} 

È necessario avere seguenti annotazioni a livello di oggetto se si desidera attivare la convalida per quell'oggetto.

@Valid 
@NotNull 
Problemi correlati