Announcement Announcement Module
Collapse
No announcement yet.
Help with Creating Custom Annotation for Form Validation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with Creating Custom Annotation for Form Validation

    Hi,

    I am currently making a form for user account creation and two of the fields are for password and the confirmation of password. I would like to show an error message like the ones from Hibernate Validator saying that the two passwords should match if the two passwords entered by the user aren't equal. I hope someone can help me with this.

    Thanks in advance.

    PS: I am using Spring 3 Framework and Hibernate Validator for form validation. I am not using the SimpleFormController in any of my classes and I don't intend on using it since it's already deprecated.

  • #2
    Hi,

    you can implement your own constraint annotaton and use it for such kind of requirements.

    Code:
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    
    @Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = FieldMatchValidator.class)
    @Documented
    public @interface FieldMatch {
    	String message() default "{validator.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( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
    	@Retention(RetentionPolicy.RUNTIME)
    	@Documented
    	@interface List {
    		FieldMatch[] value();
    	}
    }

    and implementation

    Code:
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    import org.apache.commons.beanutils.BeanUtils;
    
    public class FieldMatchValidator implements
    		ConstraintValidator<FieldMatch, Object> {
    	private String firstFieldName;
    	private String secondFieldName;
    
    	public void initialize(final FieldMatch constraintAnnotation) {
    		firstFieldName = constraintAnnotation.first();
    		secondFieldName = constraintAnnotation.second();
    	}
    
    	public boolean isValid(final Object value,
    			final ConstraintValidatorContext context) {
    		try {
    			final Object firstObj = BeanUtils
    					.getProperty(value, firstFieldName);
    			final Object secondObj = BeanUtils.getProperty(value,
    					secondFieldName);
    
    			return firstObj == null && secondObj == null || firstObj != null
    					&& firstObj.equals(secondObj);
    		} catch (final Exception ignore) {
    			// ignore
    		}
    		return true;
    	}
    }
    and you can use like
    Code:
    @FieldMatch.List( { @FieldMatch(first = "password", second = "password2", message = "The password fields must match") })
    for details http://stackoverflow.com/questions/1...idator-jsr-303

    Comment


    • #3
      Hi,

      Thank you very much for the reply. I would just like to ask how am I going to show the message specified in the annotation? I am bit confused because I am used to putting validation annotations above fieldnames in my POJO. However, in the example you've given, the validation annotation is specified above the class itself. What model attribute should I add in the POST method of my controller for me to be able to show it with the <form:errors path=""/> tag?

      Comment


      • #4
        Originally posted by trishasales View Post
        Hi,

        Thank you very much for the reply. I would just like to ask how am I going to show the message specified in the annotation? I am bit confused because I am used to putting validation annotations above fieldnames in my POJO. However, in the example you've given, the validation annotation is specified above the class itself. What model attribute should I add in the POST method of my controller for me to be able to show it with the <form:errors path=""/> tag?
        "password" and "password2" are the names of my fields in pojo so you can stil put annotations above fields and use errors tag like <form:errors path="password"/> in jsp

        Comment


        • #5
          Hi,

          I still cannot display the error message from the @FieldMatch annotation. Am I missing something? Here are my codes:

          ApplicationUser.java (POJO):
          Code:
          package ETPS.web;
          
          import java.util.Calendar;
          import java.util.GregorianCalendar;
          
          import org.hibernate.validator.constraints.Length;
          import org.hibernate.validator.constraints.NotEmpty;
          
          import ETPS.web.constraints.FieldMatch;
          
          @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match.")
          public class ApplicationUser {
          
          	@NotEmpty(message = "User ID is a required field.")
          	@Length(min = 4, message = "Must contain 4 characters.")
          	private String userId;
          	
          	@NotEmpty(message = "Name of User is a required field.")
          	private String nameOfUser;
          	
          	@NotEmpty(message = "Password is a required field.")
          	private String password;
          	
          	@NotEmpty(message = "Please re-enter password.")
          	private String confirmPassword;
          	
          	@NotEmpty(message = "Role is a required field.")
          	private String role;
          
          	private String enrollmentDate;
          	private String userView;
          	
          	public String getUserId() {
          		return userId;
          	}
          	
          	public void setUserId(String userId) {
          		this.userId = userId;
          	}
          	
          	public String getNameOfUser() {
          		return nameOfUser;
          	}
          	
          	public void setNameOfUser(String nameOfUser) {
          		this.nameOfUser = nameOfUser;
          	}
          	
          	public String getPassword() {
          		return password;
          	}
          	
          	public void setPassword(String password) {
          		this.password = password;
          	}
          	
          	public String getConfirmPassword() {
          		return confirmPassword;
          	}
          	
          	public void setConfirmPassword(String confirmPassword) {
          		this.confirmPassword = confirmPassword;
          	}
          	
          	public String getRole() {
          		return role;
          	}
          	
          	public void setRole(String role) {
          		this.role = role;
          	}
          	
          	public String getUserView(int i) {
          		switch (i) {
          		case 0:
          			this.userView = "/WEB-INF/jsp/includes/adminMainMenu.jsp";
          		break;
          		case 1:
          			this.userView = "/WEB-INF/jsp/includes/superMainMenu.jsp";
          		break;
          		case 2:
          			this.userView = "/WEB-INF/jsp/includes/userMainMenu.jsp";
          		break;
          		case 3:
          			this.userView = "/WEB-INF/jsp/includes/operMainMenu.jsp";
          		break;	
          		}
          		
          		return userView;
          	}
          	
          }
          RegisterApplicationUserController.java:
          Code:
          package ETPS.web.controllers;
          
          import java.util.ArrayList;
          import java.util.List;
          
          import javax.validation.Valid;
          
          import org.springframework.stereotype.Controller;
          import org.springframework.ui.Model;
          import org.springframework.validation.BindingResult;
          import org.springframework.web.bind.annotation.ModelAttribute;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RequestMethod;
          
          import ETPS.web.ApplicationUser;
          import ETPS.web.managers.ApplicationUserManager;
          
          @Controller
          @RequestMapping(value = "/registerApplicationUser")
          public class RegisterApplicationUserController {
          
          	ApplicationUserManager applicationUserManager = new ApplicationUserManager();
          	
          	public ApplicationUserManager getLoginManager() {
          		return applicationUserManager;
          	}
          	
          	public void setLoginManager(ApplicationUserManager applicationUserManager) {
          		this.applicationUserManager = applicationUserManager;
          	}
          	
          	@ModelAttribute("roles")
          	public List<String> getRoles() {
          		List<String> roles = new ArrayList<String>();
          		roles.add("Administrator");
          		roles.add("User - Supervisor");
          		roles.add("User");
          		roles.add("Operator");
          		
          		return roles;
          	}
          	
          	@RequestMapping(method = RequestMethod.GET)
          	public String registerApplicationUserForm(Model model) {
          		ApplicationUser applicationUser = new ApplicationUser();
          		model.addAttribute("userView", applicationUser.getUserView(0));
          		model.addAttribute("registerApplicationUserForm", applicationUser);
          		
          		return "registerApplicationUser";
          	}
          	
          	@RequestMapping(method = RequestMethod.POST)
          	public String registerApplicationUser(@ModelAttribute("registerApplicationUserForm") 
          			@Valid ApplicationUser applicationUser, BindingResult result, Model model) {
          		String userId = applicationUser.getUserId();
          		String nameOfUser = applicationUser.getNameOfUser();
          		String password = applicationUser.getPassword();
          		String role = applicationUser.getRole();
          		if (applicationUserManager.hasDuplicate(userId)) {
          			model.addAttribute("errorMessage", "User already exists!");
          			
          			model.addAttribute("userView", applicationUser.getUserView(0));
          			return "registerApplicationUser";
          		} else if ((result.hasErrors())||
          				!(applicationUserManager.registerApplicationUser(userId, 
          						nameOfUser, password, role))) {
          			model.addAttribute("userView", applicationUser.getUserView(0));
          			
          			return "registerApplicationUser";
          		} else {
          			model.addAttribute("userView", applicationUser.getUserView(0));
          			model.addAttribute("userId", applicationUser.getUserId());
          			model.addAttribute("nameOfUser", applicationUser.getNameOfUser());
          			model.addAttribute("password", applicationUser.getPassword());
          			model.addAttribute("confirmPassword", 
          					applicationUser.getConfirmPassword());
          			model.addAttribute("role", applicationUser.getRole());
          			model.addAttribute("enrollmentDate", 
          					applicationUserManager.getEnrollmentDate(userId));
          			model.addAttribute(applicationUser);
          			
          			return "viewApplicationUser";
          		}
          	}
          	
          }
          registerApplicationUser.jsp:
          Code:
          <%@ include file="/WEB-INF/jsp/includes/taglib-include.jsp" %>
          
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          	<head>
          		<title>Electronic Tax Payment System &raquo; Application User Registration</title>
          		<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
          		<link rel="stylesheet" type="text/css" href="http://localhost:8080/ETPS/stylesheet.css"/>
          	</head>
          	<body>
          		<div id="container">
          			<c:import url="/WEB-INF/jsp/includes/header.jsp"/>
          			<div class="content">
          				<c:import url="${userView}"/>
          				<div class="mainContent">
          					<form:form modelAttribute="registerApplicationUserForm">
          						<fieldset>
          							<legend>Application User Information</legend>
          							<p class="error"><c:out value="${errorMessage}"/></p>
          							Please fill up the following form:
          							<table>
          								<tr>
          									<td>User ID:</td>
          									<td>
          										<form:input path="userId" maxlength="4" size="4"/>
          									</td>
          									<td>
          										<form:errors path="userId" cssClass="error"/>
          									</td>
          								</tr>
          								<tr>
          									<td>Name of User:</td>
          									<td>
          										<form:input path="nameOfUser" maxlength="50"/>
          									</td>
          									<td>
          										<form:errors path="nameOfUser" cssClass="error"/>
          									</td>
          								</tr>
          								<tr>
          									<td>Password:</td>
          									<td>
          										<form:password path="password" maxlength="8"/>
          									</td>
          									<td>
          										<form:errors path="password" cssClass="error"/>
          									</td>
          								</tr>
          								<tr>
          									<td>Confirm Password:</td>
          									<td>
          										<form:password path="confirmPassword" maxlength="8"/>
          									</td>
          									<td>
          										<form:errors path="confirmPassword" cssClass="error"/>
          									</td>
          								</tr>
          								<tr>
          									<td>Role:</td>
          									<td>
          										<form:select path="role" items="${roles}"/>
          									</td>
          									<td>
          										<form:errors path="role" cssClass="error"/>
          									</td>
          								</tr>
          								<tr>
          									<td></td>
          									<td>
          										<input type="submit" value="Submit"/>&nbsp;
          										<input type="reset" value="Reset"/>
          									</td>
          									<td></td>
          								</tr>
          							</table>
          						</fieldset>
          					</form:form>
          				</div>
          			</div>
          			<c:import url="/WEB-INF/jsp/includes/footer.jsp"/>
          		</div>
          	</body>
          </html>
          viewApplicationUser.jsp:
          Code:
          <%@ include file="/WEB-INF/jsp/includes/taglib-include.jsp" %>
          
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          	<head>
          		<title>Electronic Tax Payment System</title>
          		<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
          		<link rel="stylesheet" type="text/css" href="http://localhost:8080/ETPS/stylesheet.css"/>
          	</head>
          	<body>
          		<div id="container">
          			<c:import url="/WEB-INF/jsp/includes/header.jsp"/>
          			<div class="content">
          				<c:import url="${userView}"/>
          				<div class="mainContent">
          					<fieldset>
          						<legend>Application User Information</legend>
          						<table>
          							<tr>
          								<td>User ID:</td>
          								<td><c:out value="${userId}"/></td>
          							</tr>
          							<tr>
          								<td>Name of User:</td>
          								<td><c:out value="${nameOfUser}"/></td>
          							</tr>
          							<tr>
          								<td>Password:</td>
          								<td><c:out value="${password}"/></td>
          							</tr>
          							<tr>
          								<td>Confirm Password:</td>
          								<td><c:out value="${confirmPassword}"/></td>
          							</tr>
          							<tr>
          								<td>Role:</td>
          								<td><c:out value="${role}"/></td>
          							</tr>
          							<tr>
          								<td>Enrollment Date:</td>
          								<td><c:out value="${enrollmentDate}"/></td>
          							</tr>
          						</table>
          					</fieldset>
          				</div>
          			</div>
          			<c:import url="/WEB-INF/jsp/includes/footer.jsp"/>
          		</div>
          	</body>
          </html>

          Comment


          • #6
            use @NotBlank for String

            Use @NotBlank instead of @NotEmpty.
            @NotBlank is for String and @NotEmpty is for Element/Object

            Comment

            Working...
            X