2011-01-22 16 views
15

मैं हाइबरनेट वैलिडेटर का उपयोग कर रहा हूं और किसी त्रुटि संदेश में श्रेणी के नाम को हल करना चाहता हूं। इस सरल परिदृश्य पर विचार करें:मैं हाइबरनेट वैलिडेटर के साथ संदेश पैरामीटर को गतिशील रूप से कैसे हल करूं?

public class Category { 
    private String name; 
} 

public class Product { 
    @HazardousCategoryConstraint(message = "{haz.cat.error}") 
    private Category category; 
    private String name; 
} 

public class InventoryReport { 
    @Valid 
    private List<Product> products; 
} 


ValidationMessages.properties 
haz.cat.error={name} is a product in the hazardous category list. 

मान लें कि मेरे पास HazardousCategoryConstraint का एक कार्यान्वयन कार्यान्वयन है। वैधकर्ता प्रतिबंधित श्रेणी की सूची के विरुद्ध प्रत्येक श्रेणी का नाम जांचता है। जब मैं मान्य (इन्वेंटरी रिपोर्ट) कॉल करता हूं तो मुझे एक ही स्ट्रिंग को छोड़कर त्रुटियों की संख्या मिलती है। मैं प्रत्येक संदेश में श्रेणी का नाम हल करना चाहता हूं। क्या कोई मुझे गतिशील रूप से पैरामीटर को हल करने के तरीके के बारे में बता सकता है, या मुझे दिखा सकता है कि कैसे?

+0

क्या आप के लिए पूछ रहा है: कैसे त्रुटि संदेश स्ट्रिंग में एक मूल्य डाल करने के लिए? -- क्या ये सही है? – Ralph

+0

@ राल्फ - यह सही है, लेकिन अधिक विशेष रूप से मैं इसे गतिशील होना चाहता हूं। मेरे पास अद्वितीय नामों के साथ श्रेणियों के कई उदाहरण हैं। –

+0

लेकिन जिन नामों को आप संदेश में रखना चाहते हैं वे आपके सत्यापनकर्ता को जानते हैं, है ना? – Ralph

उत्तर

10

आईएमओ, सरल समाधान javax.validation.MessageInterpolator के कस्टम कार्यान्वयन को बनाना है। हाइबरनेट वैलिडेटर के ResourceBundleMessageInterpolator पर मुख्य कार्य को प्रतिनिधि दें और CustomMessageInterpolator में आवश्यक प्रतिस्थापन कार्य करें।

public class CustomMessageInterpolator extends org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator { 

    private static final Pattern MESSAGE_PARAMETER_PATTERN = Pattern.compile("(\\{[^\\}]+?\\})"); 

    @Override 
    public String interpolate(String message, Context context) { 
     String resolvedMessage = super.interpolate(message, context); 
     resolvedMessage = replacePropertyNameWithPropertyValues(resolvedMessage, context.getValidatedValue()); 
     return resolvedMessage; 
    } 

    private String replacePropertyNameWithPropertyValues(String resolvedMessage, Object validatedValue) { 
     Matcher matcher = MESSAGE_PARAMETER_PATTERN.matcher(resolvedMessage); 
     StringBuffer sb = new StringBuffer(); 

     while (matcher.find()) { 
      String parameter = matcher.group(1); 

      String propertyName = parameter.replace("{", ""); 
      propertyName = propertyName.replace("}", ""); 

      PropertyDescriptor desc = null; 
      try { 
       desc = new PropertyDescriptor(propertyName, validatedValue.getClass()); 
      } catch (IntrospectionException ignore) { 
       matcher.appendReplacement(sb, parameter); 
       continue; 
      } 

      try { 
       Object propertyValue = desc.getReadMethod().invoke(validatedValue); 
       matcher.appendReplacement(sb, propertyValue.toString()); 
      } catch (Exception ignore) { 
       matcher.appendReplacement(sb, parameter); 
      } 
     } 
     matcher.appendTail(sb); 
     return sb.toString(); 
    } 

} 

@Test

public void validate() { 
     Configuration<?> configuration = Validation.byDefaultProvider().configure(); 
     ValidatorFactory validatorFactory = configuration.messageInterpolator(new CustomMessageInterpolator()).buildValidatorFactory(); 
     Validator validator = validatorFactory.getValidator(); 

     Product p = new Product(); 
     Category cat = new Category(); 
     cat.setName("s"); //assume specified name is invalid 
     p.setCategory(cat); 

     Set<ConstraintViolation<Product>> violations = validator.validate(p); 
     for(ConstraintViolation<Product> violation : violations) { 
      System.out.println(violation.getMessage()); 
     } 
    } 

आउटपुट

s is a product in the hazardous category list. 
+0

निरंतर जेपीए उपयोग के लिए मैं कस्टम संदेश इंटरपोलेटर कैसे सेट कर सकता हूं? – alexsmail

+0

बस एक ओओ चीज: हाइबरनेट वैलिडेटर के 'रिसोर्सबंडल मैसेजइंटरपोलेटर' को विस्तारित करने के बजाय मैं 'कस्टममेसेजइंटरपोलेटर' में एक प्रतिनिधि का उपयोग हाइबरनेट आंतरिक से स्वतंत्र होने के लिए करता हूं। –

संबंधित मुद्दे