In my previous tutorial I have shown how to validate input data coming from client or end user to Spring REST Controller. Now in this tutorial I will show you how to validate data in Spring Service Layer.

The reason behind validating input data in Service Layer is, input data from client may not always pass through the REST controller method and if you do not validate in Service layer also then unaccepted data may pass through the Service layer causing different issues.

Here I will use standard Java jsr-303 validation framework. I need to also use the validator provider, so here hibernate validator framework is used.

Example

Validator dependency in pom.xml file

<dependency>
	<groupId>javax.validation</groupId>
	<artifactId>validation-api</artifactId>
	<version>1.1.0.Final</version>
</dependency>
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>5.4.1.Final</version>
</dependency>

The whole pom file

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.roytuts</groupId>
	<artifactId>spring-rest</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-rest Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<properties>
		<failOnMissingWebXml>false</failOnMissingWebXml>
		<java-version>1.8</java-version>
		<spring.version>4.3.1.RELEASE</spring.version>
		<jackson.version>2.8.6</jackson.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>
		<!-- validator start -->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.4.1.Final</version>
		</dependency>
		<!-- validator end -->
	</dependencies>

	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>${java-version}</source>
					<target>${java-version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

We will use annotation based Spring MVC, so create below classes

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "jeejava.controllers", "jeejava.services" })
public class AppConfig {

}

@Configuration tells it is a configuration file; @EnableWebMvc tells it is Spring MVC; @ComponentScan looks for the annotated controllers, services classes in the respective packages.

Create below validator configuration class

import javax.validation.Validator;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class ValidatorConfig {

	@Bean
	public Validator localValidatorFactoryBean() {
		return new LocalValidatorFactoryBean();
	}

}

Create below class in order to initialize the configurations and servlet mapping for Spring MVC

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class, ValidatorConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

}

Create below POJO class that will be act as an input to the method

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;

public class RequestParam {

	@NotEmpty(message = "Name is required field")
	@NotNull(message = "Name is required field")
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

Here in the above class I have used two annotations @NotNull and @NotEmpty to make sure that name attribute is neither null or empty(“”).

Now create below service interface

import jeejava.dto.RequestParam;

public interface SpringRestService {

	String getGreetingMsg(RequestParam requestParam);

}

The corresponding service implementation class

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Valid;
import javax.validation.Validator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jeejava.dto.RequestParam;

@Service
public class SpringRestServiceImpl implements SpringRestService {

	@Autowired
	private Validator validator;

	@Override
	public String getGreetingMsg(@Valid RequestParam requestParam) {
		Set<ConstraintViolation<RequestParam>> violations = validator.validate(requestParam);
		if (!violations.isEmpty()) {
			StringBuilder sb = new StringBuilder();
			for (ConstraintViolation<RequestParam> constraintViolation : violations) {
				sb.append(constraintViolation.getMessage());
			}
			throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations);
		}
		return "Hi " + requestParam.getName() + ", Good Morning!";
	}

}

In the above class I have @Autowired the validator bean defined in ValidatorConfig class. I have also used the @Valid annotation in service method to make sure that input parameter is valid according to the specified constraint in the POJO class.

Now create below Spring REST Controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import jeejava.dto.RequestParam;
import jeejava.services.SpringRestService;

@RestController
public class SpringRestController {

	@Autowired
	private SpringRestService service;

	@RequestMapping(value = "/greeting", method = RequestMethod.POST)
	public Object getGreetingMsg(@RequestBody RequestParam requestParam) {
		return service.getGreetingMsg(requestParam);
	}

}

In the above REST controller method I have not used @Valid annotation to avoid any validation here.

So now if you run the application in Tomcat server, you will get below output

request body

{
        "name" : ""
}

or

{
        "name" : null
}

response body

HTTP Status 500 - Request processing failed; nested exception is javax.validation.ConstraintViolationException: Error occurred: Name is required field

type Exception report

message Request processing failed; nested exception is javax.validation.ConstraintViolationException: Error occurred: Name is required field

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ConstraintViolationException: Error occurred: Name is required field
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:648)

request body

{
        "name" : "Soumitra"
}

response body

Hi Soumitra, Good Morning!

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit | Email Me

Leave a Reply

Your email address will not be published. Required fields are marked *