2012-08-09 7 views
13

Sto convalidando due campi, "password" e "confirmPassword" nel modulo per l'uguaglianza utilizzando HibernateValidator come specificato in this answer. Di seguito è riportato il descrittore di vincoli (interfaccia di convalida).Convalida campi incrociati con HibernateValidator non visualizza messaggi di errore

package constraintdescriptor; 

import constraintvalidator.FieldMatchValidator; 
import javax.validation.Constraint; 
import javax.validation.Payload; 
import java.lang.annotation.Documented; 
import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 
import static java.lang.annotation.ElementType.TYPE; 
import java.lang.annotation.Retention; 
import static java.lang.annotation.RetentionPolicy.RUNTIME; 
import java.lang.annotation.Target; 

@Target({TYPE, ANNOTATION_TYPE}) 
@Retention(RUNTIME) 
@Constraint(validatedBy = FieldMatchValidator.class) 
@Documented 
public @interface FieldMatch 
{ 
    String message() default "{constraintdescriptor.fieldmatch}"; 
    Class<?>[] groups() default {}; 
    Class<? extends Payload>[] payload() default {}; 

    /** 
    * @return The first field 
    */ 
    String first(); 

    /** 
    * @return The second field 
    */ 
    String second(); 

    /** 
    * Defines several <code>@FieldMatch</code> annotations on the same element 
    * 
    * @see FieldMatch 
    */ 
    @Target({TYPE, ANNOTATION_TYPE}) 
    @Retention(RUNTIME) 
    @Documented 
    public @interface List{ 
     FieldMatch[] value(); 
    } 
} 

segue è il validatore vincolo (classe di attuazione).


package constraintvalidator; 

import constraintdescriptor.FieldMatch; 
import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 
import org.apache.commons.beanutils.BeanUtils; 

public final class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> 
{ 
    private String firstFieldName; 
    private String secondFieldName; 

    public void initialize(final FieldMatch constraintAnnotation) { 
     firstFieldName = constraintAnnotation.first(); 
     secondFieldName = constraintAnnotation.second(); 
     //System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName); 
    } 

    public boolean isValid(final Object value, final ConstraintValidatorContext cvc) { 
     try { 
      final Object firstObj = BeanUtils.getProperty(value, firstFieldName); 
      final Object secondObj = BeanUtils.getProperty(value, secondFieldName); 
      //System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj); 
      return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj); 
     } 
     catch (final Exception e) { 
      System.out.println(e.toString()); 
     } 
     return true; 
    } 
} 

Il seguente è il fagiolo validatore mappato con la pagina JSP (come specificato commandName="tempBean" con il tag <form:form></form:form>).

package validatorbeans; 

import constraintdescriptor.FieldMatch; 
import javax.validation.constraints.Size; 
import org.hibernate.validator.constraints.NotEmpty; 

@FieldMatch.List({ 
    @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match", groups={TempBean.ValidationGroup.class}) 
}) 

public final class TempBean 
{   
    @NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.") 
    private String password; 
    @NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.") 
    private String confirmPassword; 

    public interface ValidationGroup {}; 

    //Getters and setters     
} 

UPDATE

E 'tutto funziona correttamente e che la convalida destinato. Rimane solo una cosa è visualizzare il messaggio di errore specificato sopra la classeall'interno di @FieldMatch non viene visualizzata la solo una domanda:come visualizzare i messaggi di errore sulla pagina JSP quando si verifica una violazione di convalida?

(l'annotazione @NotEmpty su entrambi i campi password e confirmPassword nelle opere di classe TempBean e visualizza i messaggi specificati sulla violazione, la cosa non sta accadendo con @FieldMatch).

sto usando gruppo convalida sulla base di this question come specificato nella this blog e funziona bene causando interruzioni nella visualizzazione dei messaggi di errore (come potrebbe sembrare).


Nella pagina JSP questi due campi sono specificati come segue.

<form:form id="mainForm" name="mainForm" method="post" action="Temp.htm" commandName="tempBean"> 

    <form:password path="password"/> 
    <font style="color: red"><form:errors path="password"/></font><br/> 

    <form:password path="confirmPassword"/> 
    <font style="color: red"><form:errors path="confirmPassword"/></font><br/> 

</form:form> 
+1

Il motivo per cui la convalida non è stata eseguita è a causa di questa affermazione nella domanda "* Tutto è nello stesso pacchetto" validatore di pacchetti ";" * ". HibernateValidator richiede la ** definizione pubblica ** per entrambi * descrittore di vincoli (l'annotazione) * e * il validatore di vincoli (la classe di implementazione) * e li ho dichiarati entrambi nello stesso pacchetto e, di conseguenza, il modificatore predefinito ** no il modificatore ** è stato applicato a entrambi (poiché è improbabile che dichiarino più di una classe o un'interfaccia come * public * nello stesso pacchetto). – Tiny

+0

Rimane comunque un problema. Non visualizza ancora messaggi di errore come specificato da [questo] (http://stackoverflow.com/questions/1972933/cross-field-validation-with-hibernate-validator-jsr-303#comment8918149_2155576) commento. Qualcuno conosce il motivo per cui non visualizza i messaggi di errore anche se la convalida viene eseguita correttamente? – Tiny

+0

ok, penso che dovresti pubblicare la tua soluzione sui validatori pacchetto-privato come risposta. Per quanto riguarda i messaggi di errore è probabile che si sia verificato un problema con il modulo: dichiarazione di errori che non è specificata nella domanda. –

risposta

19

Puoi provare il tuo metodo isValid per essere così? (Questo è certamente lavorando per me nel progetto live):

public boolean isValid(final Object value, final ConstraintValidatorContext cvc){ 
    boolean toReturn = false; 

    try{ 
     final Object firstObj = BeanUtils.getProperty(value, firstFieldName); 
     final Object secondObj = BeanUtils.getProperty(value, secondFieldName); 

     //System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj); 

     toReturn = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj); 
    } 
    catch (final Exception e){ 
     System.out.println(e.toString()); 
    } 
    //If the validation failed 
    if(!toReturn) { 
     cvc.disableDefaultConstraintViolation(); 
     //In the initialiaze method you get the errorMessage: constraintAnnotation.message(); 
     cvc.buildConstraintViolationWithTemplate(errorMessage).addNode(firstFieldName).addConstraintViolation(); 
    } 
    return toReturn; 
} 

Inoltre vedo che si sta implementando l'interfaccia ConstraintValidator con una oggetto, letteralmente. Dovrebbe essere l'oggetto di supporto che hai dal tuo modulo:

tempBean // quello che hai specificato nel comandoNome effettivamente.

Così si implementazione dovrebbe in questo modo:

implements ConstraintValidator<FieldMatch, TempBean> 

Questo non è probabilmente il problema qui, ma come un riferimento futuro, questo è come dovrebbe essere.

UPDATE

All'interno della vostra interfaccia FieldMatch/annotazione avete due metodi: primo e secondo, aggiungere un altro chiamato errorMessage ad esempio:

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

/** 
* @return The first field 
*/ 
String first(); 

/** 
* @return The second field 
*/ 
String second(); 

/** 
    @return the Error Message 
*/ 
String errorMessage 

Guardate dentro di voi il metodo dalla classe di convalida - stai ricevendo il primo e il secondo nome del campo lì. Quindi aggiungi semplicemente errorMessage, ad esempio:

private String firstFieldName; 
    private String secondFieldName; 
    //get the error message name 
    private String errorMessagename; 
public void initialize(final FieldMatch constraintAnnotation) 
{ 
    firstFieldName = constraintAnnotation.first(); 
    secondFieldName = constraintAnnotation.second(); 
    errorMessageNAme = constraintAnnotation.errorMessage(); 

    //System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName); 
} 

All'interno di isValida, prendi lo stesso, come per il nome del primo e del secondo campo e usalo.

+0

Ho provato e ha funzionato, signore! Offrire la taglia richiede alcune ore da ora in poi, lo assegnerò alla tua risposta più tardi quando il sistema lo consentirà. Basta dire una cosa aggiuntiva, per favore, in questo metodo ** stesso ** 'cvc.buildConstraintViolationWithTemplate (" Le password in entrambi i campi devono corrispondere. "). AddNode (password) .addConstraintViolation();', Ho specificato il messaggio di errore . C'è un modo per recuperare il messaggio specificato in '@ FieldMatch.List ({})'? Non importa se non c'è modo di farlo. È una cosa secondaria. Per me, è una grande cosa sapere che ha funzionato secondo la tua risposta. Grazie mille – Tiny

+0

@Tiny controlla anche la mia risposta aggiornata. – Eugene

+0

Ora funziona tutto bene grazie all'intera applicazione. Grazie mille, signore! – Tiny