Custom Validation using group and MessageSource in SpringBoot

Directory Structure

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.0.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.7.RELEASE'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.google.guava:guava:28.0-jre'
    testImplementation 'junit:junit:4.12'
    implementation 'org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
	compile 'javax.validation:validation-api:2.0.1.Final'
    

    components {
        withModule('org.springframework:spring-beans') {
            allVariants {
                withDependencyConstraints {
                    it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } }
                }
            }
        }
    }
}

bootJar {
    mainClassName = 'GradleDemo.App'
}

task runJar{
	dependsOn 'assemble'
	dependsOn 'jar'
	doLast{
  		javaexec { 
    		main="-jar";
    		args = [
            	"build/libs/"+rootProject.name+".jar"
           	]
		} 
	}
}

settings.gradle

rootProject.name = 'SpringBoot'

application.properties

server.port=9090
logging.level.org.springframework=DEBUG

messages.properties

date.connot.future=Date of birth cannot be future dateddddddddddddd

CreateUserGroup.java

package app;

public interface CreateUserGroup { }

User.java

package app;

import java.util.Date;

import javax.validation.constraints.Past;
import javax.validation.constraints.Size;

public class User {
	
	private Integer id;
	
	@Size(min=2,message="Size cannot be less than 2")
	private String name;
	
	@Past(message = "{date.connot.future}",groups = {CreateUserGroup.class})
	private Date birthDate;
	
	public User() {
		 
	}
	
	public User(Integer id, String name, Date birthDate) {
		super();
		this.id = id;
		this.name = name;
		this.birthDate = birthDate;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirthDate() {
		return birthDate;
	}
	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}
}

HelloGradleController.java

package app;

import java.net.URI;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

@RestController
@CrossOrigin
public class HelloGradleController {
    
    @PostMapping("/createUser")
    public ResponseEntity<Object> createUser(@Validated({CreateUserGroup.class}) @RequestBody User user){
    	URI location = ServletUriComponentsBuilder
    						.fromCurrentRequest()
    						.path("/{id}")
    						.buildAndExpand(user.getId()).toUri();
    	return ResponseEntity.created(location).build();
    }

}

App.java

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource
          = new ReloadableResourceBundleMessageSource();
         
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
    
    @Bean
    public LocalValidatorFactoryBean getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}

ErrorField.java

package app.exception;

public class ErrorField {
	private String errorMessage;
	private String field;
	
	public ErrorField(){
		
	}
	
	public ErrorField(String errorMessage, String field) {
		super();
		this.errorMessage = errorMessage;
		this.field = field;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public String getField() {
		return field;
	}

	public void setField(String field) {
		this.field = field;
	}	
}

ExceptionResponse.java

package app.exception;

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

public class ExceptionResponse {
	private Date timestamp;
	private String message;
	private String details;
	private List<ErrorField> errorFieldList;
	
	public ExceptionResponse(Date timestamp, String message, String details, List<ErrorField> errorFieldList) {
		super();
		this.timestamp = timestamp;
		this.message = message;
		this.details = details;
		this.errorFieldList = errorFieldList;
	}

	public Date getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(Date timestamp) {
		this.timestamp = timestamp;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getDetails() {
		return details;
	}

	public void setDetails(String details) {
		this.details = details;
	}

	public List<ErrorField> getErrorFieldList() {
		return errorFieldList;
	}

	public void setErrorFieldList(List<ErrorField> errorFieldList) {
		this.errorFieldList = errorFieldList;
	}
}

AppExceptionHandling.java

package app.exception;

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

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
@RestController
public class AppExceptionHandling extends ResponseEntityExceptionHandler {

	@Override
	protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
			HttpHeaders headers, HttpStatus status, WebRequest request) {
		List<ErrorField> errorFieldList = new ArrayList<>();
		for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
			ErrorField errorField = new ErrorField(fieldError.getDefaultMessage(), fieldError.getField());
			errorFieldList.add(errorField);
		}
		ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
				ex.getBindingResult().toString(), errorFieldList);
		return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
	}

}

Output :

Leave a Comment