Hi all,
I'm trying to develop a custom constraint for field matching (as "retype password" for example);
Everything is ok except when I try to add the error to the jsp error field like this:
Code:
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("test").addNode(secondFieldName).addConstraintViolation();
it returns me this error:
HTTP Status 500 - java.lang.IllegalArgumentException: The source to convert from must be an instance of @javax.persistence.Transient java.lang.String; instead it was a org.andreadorigo.webapp.entities.User
These are my classes:
Person.javaCode:
@MappedSuperclass
@FieldMatch.List({
@FieldMatch(first = "password", second = "retypePassword"),
@FieldMatch(first = "email", second = "confirmEmail")
})
public abstract class Person {
.
.
.
}
FieldMatch.javaCode:
package org.andreadorigo.webapp.validators.costraints;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import org.andreadorigo.webapp.validators.FieldMatchValidator;
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch {
String message() default "{constraints.fieldmatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* @return The first field
*/
String first();
/**
* @return The second field
*/
String second();
/**
* Defines several <code>@FieldMatch</code> annotations on the same element
*
* @see FieldMatch
*/
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List
{
FieldMatch[] value();
}
}
FieldMatchValidator.javaCode:
package org.andreadorigo.webapp.validators;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.andreadorigo.webapp.validators.costraints.FieldMatch;
import org.apache.commons.beanutils.PropertyUtils;
public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object>
{
private String firstFieldName;
private String secondFieldName;
@Override
public void initialize(final FieldMatch constraintAnnotation)
{
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
}
@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context)
{
try
{
final Object firstObj = PropertyUtils.getProperty(value, firstFieldName);
final Object secondObj = PropertyUtils.getProperty(value, secondFieldName);
boolean test = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
if(!test) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("test").addNode(secondFieldName).addConstraintViolation();
}
return test;
}
catch (final Exception ignore)
{
// ignore
}
return true;
}
}
userForm.jspCode:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/css/test.css' />" />
<script type="text/javascript" src="<c:url value='/resources/js/jQuery.js' />"></script>
</head>
<body>
<spring:message code="label.test"/>
<form:form method="post" action="/user/add/" commandName="user" >
<table>
<tr>
<td>Email</td>
<td><form:input path="email" /></td>
<td><form:errors path="email"></form:errors></td>
</tr>
<tr>
<td>Confirm Email</td>
<td><form:input path="confirmEmail" /></td>
<td><form:errors path="confirmEmail"></form:errors></td>
</tr>
<tr>
<td>Password</td>
<td><form:input path="password" /></td>
<td><form:errors path="password"></form:errors></td>
</tr>
<tr>
<td>Retype Password</td>
<td><form:input path="retypePassword" /></td>
<td><form:errors path="retypePassword"></form:errors></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add"/>
</td>
</tr>
</table>
</form:form>
<script>
</script>
</body>
</html>