Search code examples
hibernatevalidationbean-validationhibernate-validator

Is it possible mapping another bean than formatter in hibernate validation 1.1 to usin as UL expression?


According to hibernate validation 1.1 reference is possible to use the Unified Expression Language in constraint violation messages. This allows to define error messages based on conditional logic and also enables advanced formatting options. The validation engine makes the following objects available in the EL context:

  • the attribute values of the constraint mapped to the attribute names

  • the currently validated value (property, bean, method parameter etc.) under the name validatedValue

  • a bean mapped to the name formatter exposing the var-arg method format(String format, Object... args) which behaves like java.util.Formatter.format(String format, Object... args) .

There is a class FormatterWrapper on org.hibernate.validator.internal.engine.messageinterpolation package, with this code and which got the funcionality for EL ${formatter}:

/**
 * A wrapper class for {@code java.util.Formatter#format} avoiding lookup problems in     EL engines due to
   * ambiguous method resolution for {@code format}.
 *
  * @author Hardy Ferentschik
 */
  public class FormatterWrapper {
private final Formatter formatter;

public FormatterWrapper(Locale locale) {
    this.formatter = new Formatter( locale );
}

public String format(String format, Object... args) {
    return formatter.format( format, args ).toString();
}

@Override
public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append( "FormatterWrapper" );
    sb.append( "{}" );
    return sb.toString();
}
 }

I found on InterpolationTerm.class this code related with injection but I don't know how get this contextValues to be modified:

private ValueExpression bindContextValues(String messageTemplate, MessageInterpolator.Context messageInterpolatorContext, SimpleELContext elContext) {
    // bind the validated value
    ValueExpression valueExpression = expressionFactory.createValueExpression(
            messageInterpolatorContext.getValidatedValue(),
            Object.class
    );
    elContext.setVariable( VALIDATED_VALUE_NAME, valueExpression );

    // bind a formatter instantiated with proper locale
    valueExpression = expressionFactory.createValueExpression(
            new FormatterWrapper( locale ),
            FormatterWrapper.class
    );
    elContext.setVariable( RootResolver.FORMATTER, valueExpression );

    // map the annotation values
    for ( Map.Entry<String, Object> entry : messageInterpolatorContext.getConstraintDescriptor()
            .getAttributes()
            .entrySet() ) {
        valueExpression = expressionFactory.createValueExpression( entry.getValue(), Object.class );
        elContext.setVariable( entry.getKey(), valueExpression );
    }

    return expressionFactory.createValueExpression( elContext, messageTemplate, String.class );
}

So, I wonder...will it is possible to retrieve mapped beans and to add another custom one? I have read JSR 349 api and I didn't find


Solution

  • If you're using Hibernate Validator, you may add custom beans to your error messages as described in the answer to this question. That way you also could bind another formatter bean.