Results 1 to 6 of 6

Thread: Help with Creating Custom Annotation for Form Validation

  1. #1

    Default 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. #2
    Join Date
    Jun 2009
    Posts
    6

    Default

    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

  3. #3

    Default

    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?

  4. #4
    Join Date
    Jun 2009
    Posts
    6

    Default

    Quote 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

  5. #5

    Default

    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>

  6. #6
    Join Date
    Jan 2013
    Posts
    1

    Default use @NotBlank for String

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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •