2010-10-25 10 views
9

Ho un modulo che desidero convalidare. Contiene 2 variabili di indirizzo. address1 ha sempre essere convalidati, indirizzo2 deve essere convalidato in base ad alcune condizioniSpring MVC e JSR-303 hibernate convalida convalida

public class MyForm { 
    String name; 
    @Valid Address address1; 
    Address address2; 
} 

public class Address { 
    @NotEmpty 
    private String street; 
} 

mio controller convalida e si lega automaticamente la mia forma obj

@RequestMapping(...) 
public ModelAndView edit(
     @ModelAttribute("form") 
     @Valid 
     MyForm form, 
     BindingResult bindingResult, 
     ...) 

     if(someCondition) { 
      VALIDATE form.address2 USING JSR 303 

il problema è che se uso il validatore LocalValidatorFactoryBean i non può riutilizzare l'oggetto BinidingResult fornito da Spring. Il bind non funziona come l'oggetto di destinazione del 'risultato' è 'MyForm' e non 'Indirizzo'

validate(form.getAddress2(), bindingResult) //won't work 

mi chiedo qual è il/approccio standard pulito per fare la convalida condizionale.

Stavo pensando di creare un nuovo BindingResult al mio controller.

final BindingResult bindingResultAddress2 = new BeanPropertyBindingResult(address2, "form"); 
validate(form.getAddress2(), bindingResultAddress2); 

ma poi la lista degli errori ottengo da bindingResultAddress2 non possono essere aggiunti al generale 'bindingResult' come i nomi dei campi non sono corretti ('street' invece di 'address2.street') ed il legame non funzionerà

Un approccio sporco sarebbe estendere BeanPropertyBindingResult per accettare alcune stringhe da aggiungere al nome del campo .. hai un approccio migliore?

risposta

5

L'approccio standard per la convalida strutture gerarchiche è quello di utilizzare pushNestedPath()/popNestedPath(), anche se non sono sicuro di come gioca con JSR-303:

bindingResult.pushNestedPath("address2"); 
validate(form.getAddress2(), bindingResult); 
bindingResult.popNestedPath(); 
+1

Grazie axtavt, funziona. Mi chiedo se questo sia l'approccio migliore per farlo, perché non ci sono attributi di gruppo in @Valid e se il concetto di gruppi JSR-303 è l'unico modo per ottenere la convalida condizionale – mickthompson

+3

C'è una richiesta di funzione per i gruppi in '@ Valido' : https://jira.springframework.org/browse/SPR-6373 – axtavt

+0

molto utile, grazie – mickthompson

1

mi sono mai provato, ma penso che il l'approccio corretto sta usando validator groups.

+0

Purtroppo @Valid non ha gruppi – mickthompson

+0

È spiacevole - vedere il mio commento sopra.Penso che sarebbe una grande aggiunta alle specifiche e che questo livello di praticità dovrebbe essere favorito rispetto all'idealismo. –

+0

O per placare gli idealisti, dovremmo smettere di chiamare questo 'Bean Validation Framework' e iniziare a chiamarlo 'Java Validation Framework' e aggiungere il supporto per gli argomenti del metodo e restituire valori oltre ai grafici degli oggetti. –

0

Prima di tutto, vediamo @javax.validation.Valid API

Mark un'associazione come cascata. L'oggetto associato verrà convalidato in cascata.

Quando framework Spring utilizza @Valid come marcatore per convalidare i suoi oggetti comando, si corrompe il suo scopo. Spring dovrebbe invece creare la tua specifica annotazione che specifica i gruppi che dovrebbero essere validati.

Purtroppo, è necessario utilizzare Primavera API native Validator se avete bisogno di validare alcuni gruppi

public void doSomething(Command command, Errors errors) { 
    new BeanValidationValidator(SomeUserCase.class, OtherUserCase.class) 
     .validate(command, errors); 

    if(errors.hasErrors()) { 

    } else { 

    } 
} 

BeanValidationValidator può essere implementato come

public class BeanValidationValidator implements Validator { 

    javax.validation.Validator validator = ValidatorUtil.getValidator(); 

    private Class [] groups; 

    public BeanValidationValidator(Class... groups) { 
     this.groups = groups; 
    } 

    public void validate(Object command, Errors errors) { 
     Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(command, groups); 

     for(ConstraintViolation<Object> constraintViolation: constraintViolationSet) { 
      errors.rejectValue(constraintViolation.getPropertyPath().toString(), null, constraintViolation.getMessage()); 
     } 
    } 

} 
+0

Non sono rispettosamente in accordo sul fatto che l'aggiunta di gruppi all'annotazione @Valid sarebbe una corruzione del suo scopo. Lo vedo come un miglioramento. @Valid dice "questo oggetto deve essere convalidato". L'aggiunta di gruppi significherebbe in effetti "questo oggetto dovrebbe essere convalidato in questo modo". Non c'è alcun motivo per cui quella stessa affermazione non possa essere applicata alle associazioni in cascata per i grafici degli oggetti e agli argomenti del metodo. Inoltre, le specifiche dovrebbero evolversi con evidenti aggiunte di valore; L'aggiunta di gruppi a @Valid consentirebbe a molti framework di eliminare codice ripetuto. Le specifiche dovrebbero favorire la praticità rispetto all'idealismo. –

Problemi correlati