2011-01-04 1 views
8

J'ai un validateur de bean personnalisé qui vérifie si un champ donné sur une entité est unique pour certaines conditions. Si la validation échoue, le message doit inclure un champ (par exemple l'ID) de l'entité déjà existante. Ainsi, par exemple, le message doit être:Interpolation des paramètres spécifiques à la validation dans le message de validation du bean

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

Est-ce possible en utilisant la validation du bean?

AFAICS, le format des messages peuvent inclure des paramètres, tels que:

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

Mais cela ne peut référencer les attributs "statiques" de l'annotation de validation, dans ce cas:

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

En Dans mon cas, la valeur n'est connue que dans isValid de mon validateur personnalisé.

Répondre

2

Vous avez raison !, Et pour ce que vous voulez !, vous pouvez générer un message de violation de contrainte à l'intérieur de la méthode isValid(). Pour cela, les contraintes Annotation doivent être spécifiques à une classe particulière sur laquelle elles ont été appliquées et il doit s'agir de contraintes de validation au niveau de la classe. À l'intérieur de isValid avant de renvoyer false en cas d'échec de la validation, vous pouvez créer un message contenant la valeur de l'instance de la classe. Par exemple:

@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. 

} 

Mais je pense que vous voulez faire avec annotations de niveau du terrain! Je n'ai aucune idée de cela dans l'attente de vos résultats.

+0

Le problème est que je ne veux pas construire le message final dans le validateur, seulement un format (pour les traductions) et des paramètres. Mais je suppose que je suis supposé localiser le message dans le validateur. – robinst

+0

J'ai posté la solution nous avons fini avec comme une autre réponse. Mais je pense que votre réponse permet des messages d'erreur plus spécifiques, même si la localisation doit être faite à l'intérieur du validateur, je l'ai accepté. – robinst

0

Ce n'est pas vraiment la plus belle solution, mais ce que nous avons fini par faire était d'ajouter quelque chose comme ce qui suit à notre haut niveau du code de gestion des exceptions:

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

Notez que PrimaryKeyed est une interface personnalisée qui est utilisé sur nos entités. Nous avons également d'autres interfaces et une gestion personnalisée non montrée ci-dessus.

+0

Dans quelle classe ces deux méthodes sont-elles assises? Ma contrainte personnalisée avec un 'context.buildConstraintViolationWithTemplate (" {no.mobitroll.rest.resources.entities.beans.validators.QuizType.enum} "). AddConstraintViolation();' n'interpole pas encore la valeur. – Stephane

+0

@Stephane Nous les avons dans une classe de gestionnaire d'exceptions de niveau supérieur, ce qui est probablement une bonne chose à avoir indépendamment. Là où vous ajoutez cela dépend vraiment de votre architecture et des frameworks que vous utilisez, donc je ne peux malheureusement pas donner une réponse plus précise. – robinst

Questions connexes