<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">In the previous algorithm, parameter values were themselves interpolated which was undesirable and could lead to security issue.<div>I have reworked the algorithm to resolve the custom ResourceBundle in priority, the built-in bundle as a back up and finally regular parameters.</div><div><br></div><div>Check it out</div><div><br></div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h2 class="title" style="clear: both; font-family: sans-serif; color: rgb(0, 51, 153); font-size: 140%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">4.3.&nbsp;Message interpolation</h2></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; "><a name="default-messageresolver" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a>4.3.1.&nbsp;Default message interpolation</h3></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A conforming implementation includes a default message interpolator. This message interpolator shall use the algorithm defined here to interpolate message descriptors into human-readable messages.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Each constraint defines a message descriptor via its&nbsp;<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">message</tt>&nbsp;property. Every constraint definition shall define a default message descriptor for that constraint. Messages can be overridden at declaration time in constraints by setting the&nbsp;<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">message</tt>&nbsp;property on the constraint.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The message descriptor is a string literal and may contain one or more message parameters. Message parameters are string literals enclosed in braces.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="d0e2703" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example&nbsp;4.1.&nbsp;Message using parameters</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">Value must be between {min} and {max}</pre></div><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h4 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 100%; margin-top: 10px; padding-top: 5px; font-weight: bold; "><a name="default-resolution-algorithm" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a>4.3.1.1.&nbsp;Algorithm</h4></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The default message interpolator uses the following steps:</p><div class="orderedlist" style="font-family: sans-serif; font-size: 14px; "><ol type="1" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Message parameters are extracted from the message string and used as keys to search the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ResourceBundle</tt>&nbsp;named&nbsp;<tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidationMessages</tt>&nbsp;(often materialized as the property file<tt class="filename" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">/ValidationMessages.properties</tt>&nbsp;and its locale variations) using the defined locale (see below). If a property is found, the message parameter is replaced with the property value in the message string. Step 1 is applied recursively until no replacement is performed (ie. a message parameter value can itself contain a message parameter).</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Message parameters are extracted from the message string and used as keys to search the Bean Validation provider's built-in&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ResourceBundle</tt>&nbsp;using the defined locale (see below). If a property is found, the message parameter is replaced with the property value in the message string. Contrary to step 1, step 2 is not processed recursively.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">If step 2 triggers a replacement, then step 1 is applied again. Otherwise step 4 is performed.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Message parameters are extracted from the message string. Those matching the name of an attribute of the constraint declaration are replaced by the value of that attribute.</p></li></ol></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The defined locale is as followed:</p><div class="itemizedlist" style="font-family: sans-serif; font-size: 14px; "><ul type="disc" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">if the locale is passed to the interpolator method i<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">nterpolate(String, CosntraintDescriptor, Object, Locale)</tt>, this&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;instance is used.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">otherwise, the default&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;as provided by&nbsp;<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale.getDefault()</tt>&nbsp;is used.</p></li></ul></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The proposed algorithm ensures that custom resource bundle always have priority over built-in resource bundle at all level of the recursive resolution. It also ensures that constraint declarations attributes values are not expanded further.</p></div></div><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; "><a name="custom-message-resolution" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a>4.3.2.&nbsp;Custom message interpolation</h3></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A custom message interpolator may be provided (e.g., to interpolate contextual data, or to adjust the default&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale&nbsp;</tt>used). A message interpolator implements the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;interface.</p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">/**
 * Interpolate a given constraint violation message.
 *
 * @author Emmanuel Bernard
 * @author Hardy Ferentschik
 */
public interface MessageInterpolator {
        /**
         * Interpolate the message from the constraint parameters and the actual validated object.
         * The locale is defaulted according to the &lt;code>MessageInterpolator&lt;/code> implementation
         * See the implementation documentation for more detail.
         *
         * @param message The message to interpolate.
         * @param constraintDescriptor The constraint descriptor.
         * @param value The object being validated
         *
         * @return Interpolated error message.
         */
        String interpolate(String message,
                                           ConstraintDescriptor constraintDescriptor,
                                           Object value);

        /**
         * Interpolate the message from the constraint parameters and the actual validated object.
         * The Locale used is provided as a parameter
         *
         * @param message The message to interpolate.
         * @param constraintDescriptor The constraint descriptor.
         * @param value The object being validated
         * @param locale the locale targeted for the message
         *
         * @return Interpolated error message.
         */
        String interpolate(String message,
                                           ConstraintDescriptor constraintDescriptor,
                                           Object value,
                                           Locale locale);
}</pre><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><i class="parameter" style="font-family: sans-serif; font-size: 14px; "><tt style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">message</tt></i>&nbsp;is the message descriptor as seen in&nbsp;<tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@ConstraintAnnotation.message</tt>&nbsp;or provided to the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintContext</tt>&nbsp;methods.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><i class="parameter" style="font-family: sans-serif; font-size: 14px; "><tt style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">constraintDescriptor</tt></i>&nbsp;is the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintDescriptor</tt>&nbsp;object representing the metadata of the failing constraint (see&nbsp;<a href="file:///Users/manu/projects/specs/303/specbook/build/en/html/constraintmetadata.html" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Constraint metadata request API</a>).</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><i class="parameter" style="font-family: sans-serif; font-size: 14px; "><tt style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">value</tt></i>&nbsp;is the value being validated.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator.interpolate(String, ConstraintDescriptor, Object)</tt>&nbsp;is invoked by for each constraint violation report generated. The default&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;is implementation specific.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator.interpolate(String, ConstraintDescriptor, Object, Locale)</tt>&nbsp;can be invoked by a wrapping&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;to enforce a specific&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;value by bypassing or overriding the default&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;strategy.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A message interpolator implementation shall be threadsafe.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The message interpolator is provided to the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactory</tt>&nbsp;at construction time using&nbsp;<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactoryBuilder.messageInterpolator(MessageInterpolator)</tt>. This message interpolator is shared by all validators generated by this&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactory</tt>.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">It is possible to override the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;implementation for a given&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Validator</tt>&nbsp;instance by invoking<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactory.defineValidatorState().messageInterpolator(messageInterpolator).getValidator()</tt>.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">It is recommended that&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;implementations delegate final interpolation to the Bean Validation default&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;to ensure standard Bean Validation interpolation rules are followed, The default implementation is accessible through&nbsp;<tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactoryBuilder.getDefaultMessageInterpolator()</tt>.</p></div><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; "><a name="validationapi-message-examples" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a>4.3.3.&nbsp;Examples</h3></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">These examples describe message interpolation based on the default message interpolator's built-in messages (see&nbsp;<a href="file:///Users/manu/projects/specs/303/specbook/build/en/html/standard-resolver-messages.html" title="Appendix&nbsp;B.&nbsp;Standard ResourceBundle messages" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Appendix&nbsp;B,&nbsp;<i style="font-family: sans-serif; font-size: 14px; ">Standard ResourceBundle messages</i></a>), and the&nbsp;<tt class="filename" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidationMessages.properties</tt>file shown in table&nbsp;<a href="file:///Users/manu/projects/specs/303/specbook/build/en/html/validationapi.html#table-messageinterpolation" title="Table&nbsp;4.2.&nbsp;message interpolation" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Table&nbsp;4.2, “message interpolation”</a>. The current locale is assumed English.</p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">//ValidationMessages.properties
myapp.creditcard.error=credit card number not valid</pre><div style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><br class="webkit-block-placeholder"></div><div class="table" style="font-family: sans-serif; font-size: 14px; "><a name="table-messageinterpolation" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Table&nbsp;4.2.&nbsp;message interpolation</b></p><table summary="message interpolation" border="1" style="font-family: sans-serif; font-size: 14px; border-collapse: collapse; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; empty-cells: hide; width: 100%; "><colgroup style="font-family: sans-serif; font-size: 14px; "><col align="center" style="font-family: sans-serif; font-size: 14px; "><col style="font-family: sans-serif; font-size: 14px; "></colgroup><tbody style="font-family: sans-serif; font-size: 14px; "><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">Failing constraint declaration</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">interpolated message</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">@NotNull</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">must not be null</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">@Max(30)</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">must be less than or equal to 30</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">@Size(min=5, max=15, message="Key must have between {min} and {max} characters")</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">Key must have between 5 and 15 characters</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">@Digits(integer=9, fraction=2)</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">numeric value out of bounds (&lt;9 digits>.&lt;2 digits> expected)</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">@CreditCard(message={myapp.creditcard.error})</td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; ">credit card number not valid</td></tr></tbody></table></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Here is an approach to specify the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;value to choose on a given&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Validator</tt>.&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;aware&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>. See&nbsp;<a href="file:///Users/manu/projects/specs/303/specbook/build/en/html/validationapi.html#bootstrapping" title="4.4.&nbsp;Bootstrapping" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Section&nbsp;4.4, “Bootstrapping”</a>&nbsp;for more details on the APIs.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="validationapi-message-examples-specificlocale" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example&nbsp;4.2.&nbsp;Use MessageInterpolator to use a specific Locale value</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; position: static; z-index: auto; ">/**
 * delegates to a MessageInterpolator implementation but enforce a given Locale
 */
public class LocaleSpecificMessageInterpolator implements MessageInterpolator {
    private final MessageInterpolator defaultInterpolator;
    private final Locale defaultLocale;

    public LocaleSpecificMessageInterpolator(MessageInterpolator interpolator, Locale locale) {
        this.defaultLocale = locale;
        this.defaultInterpolator = interpolator;
    }

    /**
     * enforece the locale passed to the interpolator
     */
    public String interpolate(String message, 
                              ConstraintDescriptor constraintDescriptor, 
                              Object value) {
        return defaultInterpolator.interpolate(message, constraintDescriptor, 
                                           value, this.defaultLocale);
    }

    // no real use, implemented for completeness
    public String interpolate(String message,
                              ConstraintDescriptor constraintDescriptor,
                              Object value,
                              Locale locale) {
        return defaultInterpolator.interpolate(message, constraintDescriptor, value, locale);
    }
}


Locale locale = getMyCurrentLocale();
MessageInterpolator interpolator = new LocaleSpecificMessageInterpolator(
                                       validatorFactory.getMessageInterpolator(),
                                       locale);

Validator validator = validatorFactory.defineValidatorState()
                                      .messageInterpolator(interpolator)
                                      .getValidator();</pre></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Most of the time, however, the relevant&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;will be provided by your application framework transparently. This framework will implement its own version of&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;and pass it during the<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ValidatorFactory</tt>&nbsp;configuration. The application will not have to set the&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Locale</tt>&nbsp;itself. This example shows how a container framework would implement&nbsp;<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">MessageInterpolator</tt>&nbsp;to provide a user specific default locale.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="validationapi-message-examples-jsflocale" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example&nbsp;4.3.&nbsp;Contextual container possible MessageInterpolator implementation</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; position: static; z-index: auto; ">public class ContextualMessageInterpolator {
    private final MessageInterpolator delegate;

    public ContextualMessageInterpolator(MessageInterpolator delegate) { 
        this.delegate = delegate; 
    }

    public String interpolate(String message, ConstraintDescriptor constraintDescriptor, 
                              Object value) {
        Locale locale = Container.getManager().getUserLocale();
        return this.delegate.interpolate(
                        message, constraintDescriptor, value, locale );
    }

    public String interpolate(String message, ConstraintDescriptor constraintDescriptor, 
                              Object value, Locale locale) {
        return this.delegate.interpolate(message, constraintDescriptor, value, locale);
    }
}


//Build the ValidatorFactory
ValidatorFactoryBuilder builder = Validation.getBuilder();
ValidatorFactory factory = builder
    .messageInterpolator( new ContextualMessageInterpolator( builder.getDefaultMessageInterpolator() ) )
    .build();

//The container uses the factory to validate constraints using the specific MessageInterpolator
Validator validator = factory.getValidator();</pre></div></div></span></div></div></body></html>