2012-08-09 23 views
13

मैं this answer में निर्दिष्ट अनुसार HibernateValidator का उपयोग करके समानता के रूप में दो फ़ील्ड, "पासवर्ड" और "पुष्टिकरण" को मान्य कर रहा हूं। निम्नलिखित बाधा डिस्क्रिप्टर (सत्यापनकर्ता इंटरफ़ेस) है।HibernateValidator के साथ क्रॉस फ़ील्ड सत्यापन कोई त्रुटि संदेश प्रदर्शित नहीं करता

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(); 
    } 
} 

निम्नलिखित बाधा सत्यापनकर्ता (लागू करने वर्ग) है।


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; 
    } 
} 

निम्नलिखित सत्यापनकर्ता सेम जो JSP पेज (<form:form></form:form> टैग के साथ commandName="tempBean" निर्दिष्ट है) के साथ मैप किया गया है है।

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     
} 

अद्यतन

यह सब सही ढंग से काम और सत्यापन का इरादा करता है। @FieldMatch के भीतर TempBean कक्षा के ऊपर निर्दिष्ट त्रुटि संदेश को प्रदर्शित करने के लिए बस एक बात बनी हुई है iee केवल एक प्रश्न प्रदर्शित नहीं किया जा रहा है:सत्यापन उल्लंघन होने पर जेएसपी पृष्ठ पर त्रुटि संदेश कैसे प्रदर्शित करें?

(क्षेत्रों password और confirmPasswordTempBean वर्ग कार्यों में दोनों पर एनोटेशन @NotEmpty और उल्लंघन, बात @FieldMatch साथ नहीं हो रहा है पर निर्दिष्ट संदेशों को प्रदर्शित करता)।

this blog में निर्दिष्ट और यह अच्छी तरह त्रुटि संदेश प्रदर्शित करने में बिना किसी हस्तक्षेप (के रूप में यह लग सकता है) के कारण काम करता है के रूप में मैं सत्यापन समूहthis question के आधार पर उपयोग कर रहा हूँ।


जेएसपी पृष्ठ पर इन दो फ़ील्ड को निम्नानुसार निर्दिष्ट किया गया है।

<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

सत्यापन क्यों नहीं किया गया था इस सवाल के कारण "* सबकुछ एक ही पैकेज में है पैकेज पैकेज वैधकर्ताबीन; * *"। HibernateValidator को ** बाधा परिभाषा ** दोनों * बाधा वर्णनकर्ता (एनोटेशन) * और * बाधा सत्यापनकर्ता (कार्यान्वयन वर्ग) * के लिए आवश्यक है * और मैंने दोनों को एक ही पैकेज में घोषित किया और इसके परिणामस्वरूप, डिफ़ॉल्ट संशोधक ** नहीं संशोधक ** उन दोनों पर लागू किया गया था (क्योंकि एक ही पैकेज में एक से अधिक कक्षा या इंटरफ़ेस * सार्वजनिक * के रूप में घोषित करने की संभावना नहीं है)। – Tiny

+0

हालांकि एक मुद्दा बनी हुई है। यह अभी भी त्रुटि संदेशों को प्रदर्शित नहीं करता है जैसा कि [इस] (http://stackoverflow.com/questions/1972933/cross-field-validation-with-hibernate-validator-jsr-303#comment8918149_2155576) टिप्पणी द्वारा निर्दिष्ट किया गया है। क्या किसी को कारण पता है कि यह त्रुटि संदेशों को प्रदर्शित क्यों नहीं करता है भले ही सत्यापन सही तरीके से किया जाता है? – Tiny

+0

ठीक है, मुझे लगता है कि आपको पैकेज-प्राइवेट वैधकर्ताओं के उत्तर के रूप में अपना समाधान पोस्ट करना चाहिए। त्रुटि संदेशों के लिए यह संभवतः फ़ॉर्म के साथ एक समस्या है: त्रुटियों की घोषणा जो प्रश्न में निर्दिष्ट नहीं है। –

उत्तर

19

क्या आप इस तरह की अपनी वैध विधि को आजमा सकते हैं? (यह निश्चित रूप से लाइव परियोजना में मेरे लिए काम कर रहा है):

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; 
} 

इसके अलावा मुझे लगता है कि आप एक वस्तु साथ ConstraintValidator इंटरफ़ेस कार्यान्वित कर रहे हैं, सचमुच। यह आपके फॉर्म से आपके पास बैकिंग ऑब्जेक्ट होना चाहिए:

tempBean // जिसे आप कमांड नाम में निर्दिष्ट करते हैं।

तो तुम कार्यान्वयन यह पसंद चाहिए:

implements ConstraintValidator<FieldMatch, TempBean> 

यह शायद यहां मुद्दा यह नहीं है, लेकिन एक भविष्य में संदर्भ के रूप में, यह है कि यह कैसे किया जाना चाहिए है।

अद्यतन

अपने FieldMatch इंटरफ़ेस/एनोटेशन के अंदर आप दो तरीकों है: पहले और दूसरे, जोड़ने के एक और उदाहरण के लिए errorMessage कहा जाता है:

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

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

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

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

मान्यता कक्षा से आप विधि के अंदर देखो - आपको पहले और दूसरे फ़ील्ड नाम मिल रहे हैं।, तो बस त्रुटि संदेश जोड़ें, उदाहरण के लिए:

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); 
} 

अंदर इवालिडा इसे प्राप्त करें, वैसे ही आप पहले और दूसरे फ़ील्ड नाम के लिए करते हैं और इसका उपयोग करते हैं।

+0

कोशिश की और यह काम किया, महोदय! उपहार देने के लिए अब कुछ घंटों की आवश्यकता है, जब सिस्टम अनुमति देता है तो मैं इसे बाद में आपके उत्तर में दूंगा। बस एक अतिरिक्त बात कहें, कृपया इस विधि में ** ** ** cvc.buildConstraintViolationWithTemplate ("दोनों फ़ील्ड में पासवर्ड मेल खाना चाहिए।")। एडनोड (पासवर्ड) .addConstraint उल्लंघन(); ', मैंने त्रुटि संदेश निर्दिष्ट किया है । क्या '@ FieldMatch.List ({}) 'में निर्दिष्ट संदेश लाने का कोई तरीका है? कोई फर्क नहीं पड़ता कि ऐसा करने का कोई तरीका नहीं है। यह मामूली बात है। मेरे लिए, यह जानना एक बड़ी बात है कि यह आपके उत्तर के अनुसार काम करता है। बहुत बहुत धन्यवाद – Tiny

+0

@Tiny इसके लिए भी मेरे अद्यतन उत्तर की जांच करें। – Eugene

+0

यह सब मेरे पूरे आवेदन के माध्यम से अब अच्छी तरह से काम कर रहा है। बहुत धन्यवाद, महोदय! – Tiny