2011-01-04 22 views
8

Tengo un validador de beans personalizado que comprueba si un campo determinado en una entidad es único para algunas condiciones. Si la validación falla, el mensaje debe incluir un campo (por ejemplo, el ID) de la entidad ya existente. Así, por ejemplo, el mensaje debe ser:Interpolar parámetros específicos de validación en el mensaje de validación de beans

"Product 42 already has such a value defined, choose a unique value." 

Es esto posible mediante la validación de frijol?

AFAICS, el formato de los mensajes pueden incluir parámetros, tales como:

"Length must be between {min} and {max}." 

Pero esto sólo se puede hacer referencia a los atributos "estáticos" de la anotación de validación, en este caso:

@Size(min=1, max=16) 
private String name; 

En En mi caso, el valor solo se conoce dentro de isValid de mi validador personalizado.

Respuesta

2

tienes razón !, y por lo que quieres !, usted puede construir mensaje de violación de restricción dentro del método isValid(). Para esto, las restricciones Anotación debe ser específica para la clase particular en la que se ha aplicado y debe ser una restricción de validación de nivel de clase. Dentro de isValid antes de devolver falso en caso de falla de validación puede crear un mensaje que consista en el valor de la instancia de clase. Por ejemplo:

@check class Test{ int id; @validations...on fields}. 

public boolean isValid(Test value, ConstraintValidatorContext context) 
{ 
// your check logic 
context.disableDefaultConstraintViolation(); 
context.buildConstraintViolationWithTemplate("It should be different for(custom message) .."+ value.id).addConstraintViolation(); 
return false; // based on constraint filure. 

} 

¡Pero creo que quieres hacer esto con las anotaciones de nivel de campo! No tengo idea sobre eso esperando tus resultados.

+0

El problema es que no quiero construir el mensaje final en el validador, solo un formato (para traducciones) y parámetros. Pero supongo que se supone que debo localizar el mensaje dentro del validador. – robinst

+0

Publiqué la solución con la que terminamos como otra respuesta. Pero creo que su respuesta permite mensajes de error más específicos, incluso si la localización debe hacerse dentro del validador, lo acepté. – robinst

0

en realidad no es la solución más bonito, pero lo que terminamos haciendo fue añadiendo algo como lo siguiente en nuestro nivel superior de código de control de excepciones:

String getConstraintViolationMessages(ConstraintViolationException e) { 
    StringBuilder sb = new StringBuilder(); 
    for (ConstraintViolation<?> violation : e.getConstraintViolations()) { 
     sb.append(getMessage(violation)); 
     sb.append("\n"); 
    } 
    sb.setLength(sb.length() - 1); 
    return sb.toString(); 
} 

String getMessage(ConstraintViolation<?> violation) { 
    String key = violation.getMessageTemplate(); 
    String messageFormat = localize(key); 

    Object entity = violation.getRootBean(); 
    String identifier; 
    if (entity instanceof PrimaryKeyed) { 
     identifier = String.valueOf(((PrimaryKeyed) entity).getId()); 
    } else { 
     identifier = entity.toString(); 
    } 

    return MessageFormat.format(messageFormat, identifier); 
} 

Tenga en cuenta que PrimaryKeyed es una interfaz personalizada que se utiliza en nuestras entidades. También tenemos algunas otras interfaces y manejo personalizado que no se muestran arriba.

+0

¿En qué clase están sentados estos dos métodos? Mi restricción personalizada con 'context.buildConstraintViolationWithTemplate (" {no.mobitroll.rest.resources.entities.beans.validators.QuizType.enum} "). AddConstraintViolation();' aún no interpola el valor. – Stephane

+0

@Stephane Los tenemos en una clase de manejador de excepciones de nivel superior, lo que probablemente sea bueno tener independientemente. A dónde agregue esto realmente depende de su arquitectura y de los marcos que use, así que no puedo darle una respuesta más específica, lamentablemente. – robinst

Cuestiones relacionadas