Saturday, 1 December 2018

Spring mvc: Parameters to custom validation annotation

This is continuation to my previous post. In my previous post, I explained how to validate the user name by using the custom annotation @ValidUserName’.

@Constraint(validatedBy = UserNameValidatior.class)
@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidUserName {
         String message() default "Please provide valid user name. User name must have more than 5 characters and < 15 and it shouldn't contain special characters other than _, -";

         Class<?>[] groups() default {};

         Class<? extends Payload>[] payload() default {};

}

One problem with above annotation is that, it is not configurable. I can’t set the minimum, maximum number of characters in an user name. In this post, I am extending the behavior of @ValidUserName annotation, by adding minChars, maxChars attributes.

@Constraint(validatedBy = UserNameValidatior.class)
@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidUserName {
         String message() default "Invalid User name";

         Class<?>[] groups() default {};

         Class<? extends Payload>[] payload() default {};
        
         int minChars() default 5;
        
         int maxChars() default 15;

}

I can specify the minChars, maxChars value in @ValidUserName annotation like below. If you do not specify these values, then by default minChars=5 and maxChars=15.

public class Student {

         @ValidUserName(minChars=8, maxChars=11)
         private String userName;

         .....
         .....
}

UserNameValidator class is updated like below.

public class UserNameValidatior implements ConstraintValidator<ValidUserName, String> {
         private String USERNAME_PATTERN;
         private Pattern pattern;

         @Override
         public void initialize(ValidUserName annotation) {

                  int minChars = annotation.minChars();
                  int maxChars = annotation.maxChars();

                  USERNAME_PATTERN = "^[a-z0-9_-]{" + minChars + "," + maxChars + "}$";
                  pattern = Pattern.compile(USERNAME_PATTERN);

         }

         @Override
         public boolean isValid(String userName, ConstraintValidatorContext context) {

                  if (userName == null) {
                           return false;
                  }

                  Matcher matcher = pattern.matcher(userName);
                  return matcher.matches();
         }

}

Find the below working application.

ValidUserName.java
package com.sample.myApp.annotations;

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;

import com.sample.myApp.validators.UserNameValidatior;

@Constraint(validatedBy = UserNameValidatior.class)
@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidUserName {
 String message() default "Invalid User name";

 Class<?>[] groups() default {};

 Class<? extends Payload>[] payload() default {};
 
 int minChars() default 5;
 
 int maxChars() default 15;

}

HelloWorldController.java
package com.sample.myApp.controllers;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.sample.myApp.model.Student;

@Controller
public class HelloWorldController {

 @RequestMapping("/registration")
 public String getRegistrationpage() {
  return "registration";
 }

 @RequestMapping("/registerMe")
 public ModelAndView getHelloMessage(@Valid @ModelAttribute("studentInfo") Student student,
   BindingResult bindingResult) {
  if (bindingResult.hasErrors()) {
   ModelAndView modelAndView = new ModelAndView("registration");
   return modelAndView;
  }

  ModelAndView modelAndView = new ModelAndView("welcome");

  modelAndView.addObject("message", "Dear User, your details are registered");

  return modelAndView;
 }

}

Student.java
package com.sample.myApp.model;

import java.util.Date;
import java.util.List;

import javax.validation.constraints.DecimalMax;

import com.sample.myApp.annotations.ValidUserName;

public class Student {

 @ValidUserName(minChars=8, maxChars=11)
 private String userName;

 @DecimalMax(value = "40")
 private int age;

 private List<String> hobbies;
 private Date dateOfBirth;

 public Date getDateOfBirth() {
  return dateOfBirth;
 }

 public void setDateOfBirth(Date dateOfBirth) {
  this.dateOfBirth = dateOfBirth;
 }

 public String getUserName() {
  return userName;
 }

 public void setUserName(String userName) {
  this.userName = userName;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public List<String> getHobbies() {
  return hobbies;
 }

 public void setHobbies(List<String> hobbies) {
  this.hobbies = hobbies;
 }

}

UserNameValidatior.java
package com.sample.myApp.validators;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import com.sample.myApp.annotations.ValidUserName;

public class UserNameValidatior implements ConstraintValidator<ValidUserName, String> {
 private String USERNAME_PATTERN;
 private Pattern pattern;

 @Override
 public void initialize(ValidUserName annotation) {

  int minChars = annotation.minChars();
  int maxChars = annotation.maxChars();

  USERNAME_PATTERN = "^[a-z0-9_-]{" + minChars + "," + maxChars + "}$";
  pattern = Pattern.compile(USERNAME_PATTERN);

 }

 @Override
 public boolean isValid(String userName, ConstraintValidatorContext context) {

  if (userName == null) {
   return false;
  }

  Matcher matcher = pattern.matcher(userName);
  return matcher.matches();
 }

}

Create registration.jsp, welcome.jsp files under WEB-INF/jsp folder.


registration.jsp
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>User Information Page</title>
</head>

<body>
 <h2 style="color: red;">
  <form:errors path="studentInfo.*" />
 </h2>

 <form method="post" action="/springdemo/registerMe" id="f1">
  <table>
   <tr>
    <td>User Name :</td>
    <td><input type="text" name="userName" value="" /></td>
   </tr>
   <tr>
    <td>Age :</td>
    <td><input type="text" name="age" value="" /></td>
   </tr>
   <tr>
    <td>Hobbies :</td>
    <td><select multiple name="hobbies">
      <option value="cricket">Cricket</option>
      <option value="chess">Chess</option>
      <option value="football">Football</option>
      <option value="tennis">Tennis</option>
    </select></td>
   </tr>

   <tr>
    <td>Date Of Birth</td>
    <td><input type="text" name="dateOfBirth" value="" /></td>
   </tr>
   <tr>
    <td><input type="submit" name="submit" value="submit"
     style="font-size: 18px;" /></td>
   </tr>
  </table>
 </form>

</body>
</html>

welcome.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<!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>Hello World Spring Web MVC</title>
</head>
<body>
 <h1>${message}</h1>

 <h3>
  User Name : ${studentInfo.userName} <br /> 
  Age : ${studentInfo.age} <br />
  Hobbies: ${studentInfo.hobbies} <br />
  Date Of Birth: ${studentInfo.dateOfBirth}
 </h3>
</body>
</html>

Create HelloWorld-servlet.xml, studentMessages.properties, web.xl files under WEB-INF folder.

HelloWorld-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 <mvc:annotation-driven />

 <context:component-scan
  base-package="com.sample.myApp" />

 <bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
 </bean>

 <bean id="messageSource"
  class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

  <property name="basename" value="WEB-INF/studentMessages" />

 </bean>

</beans>

studentMessages.properties
ValidUserName.studentInfo.userName=Please provide valid {0}. {0} must have more than {1} characters and < {2} and it shouldn't contain special characters other than _, -";
DecimalMax.studentInfo.age={0} must be less than or equal to {2}


web.xml
<web-app id="WebApp_ID" version="2.4"
 xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 <display-name>Spring MVC Hello WorldApplication</display-name>

 <servlet>
  <servlet-name>HelloWorld</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>HelloWorld</servlet-name>
  <url-pattern>/</url-pattern>
 </servlet-mapping>

</web-app>

Create index.jsp file under webapp folder.


index.jsp
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Welcome Page</title>
</head>

<body>
 <h3>Dear Student, click on below button to register yourself</h3>
 <form method="post" action="/springdemo/registration" id="f1">
  <input type="submit" name="submit" value="submit"
   style="font-size: 18px;" />
 </form>
</body>
</html>

Project structure looks like below.
Run the application on server, you can able to see below screen.
Click on submit button.
Enter invalid values for user name, age and click on submit button.



Previous                                                 Next                                                 Home

No comments:

Post a Comment