Spring Service Layer Bean Validation

Introduction

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.

In this example, I will create Spring MVC project and you may also create Spring Boot and use the same code except the MvcInitializer class and you need to add Spring Boot dependencies instead of Spring MVC.

Prerequisites

Java at least 8, Maven 3.6.1 – 3.6.3, Spring Boot 2.4.5

Project Setup

Create a maven based project in your favorite IDE or tool. The project name is spring-service-layer-bean-validation.

You need to update pom.xml file according to your project type. You need validator dependency and validator provider dependency (such as Hibernate-Validator).

Add the required dependencies into the pom.xml file for maven based project as shown in the below file.

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>spring-service-layer-bean-validation</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.5</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.hibernate.validator</groupId>
			<artifactId>hibernate-validator</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

VO Class

Create below POJO class that will be acting as an input to the REST API. I will pass this VO class in the request body of the REST call.

package com.roytuts.spring.service.layer.bean.validation.vo;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

public class User {

	@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(“”).

Spring Service Class

The corresponding service class that validates the input object is given in the below source code.

package com.roytuts.spring.service.layer.bean.validation.service;

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 com.roytuts.spring.service.layer.bean.validation.vo.User;

@Service
public class GreetingService {

	@Autowired
	private Validator validator;

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

}

In the above class I have @Autowired the validator bean defined in MvcConfig 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 User.

Spring REST Controller

Now create below Spring REST Controller class to expose the service to the client or end user so that you can test your application on input validation.

package com.roytuts.spring.service.layer.bean.validation.rest.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.roytuts.spring.service.layer.bean.validation.service.GreetingService;
import com.roytuts.spring.service.layer.bean.validation.vo.User;

@RestController
public class GreetingRestController {

	@Autowired
	private GreetingService service;

	@PostMapping("/greet")
	public Object getGreetingMsg(@RequestBody User user) {
		return service.getGreetingMsg(user);
	}

}

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

Testing the Application

Run the application in Tomcat server.

URL: http://localhost:8080/greet

Request Body:

{
        "name" : ""
}

or

{
        "name" : null
}

Response body:

{
    "status": 500,
    "error": "Internal Server Error",
    "message": "",
    "path": "/greet"
}

If you check the log then you will find the actual error as given below:

javax.validation.ConstraintViolationException: Error occurred: Name is required fieldName is required field
	at com.roytuts.spring.service.layer.bean.validation.service.GreetingService.getGreetingMsg(GreetingService.java:30)

Now retest the service with the following data.

URL: http://localhost:8080/greet

Request Body:

{
        "name" : "Soumitra"
}

Response Body:

Hi Soumitra, Good Morning!

That’s all. Hope you got an idea how to validate user input in service layer code.

Source Code

Download

1 thought on “Spring Service Layer Bean Validation

  1. Hello, there are any option to use uniquely @Valid in the service method without do manual validation with this code

    Set<ConstraintViolation> violations = validator.validate(user);
    if (!violations.isEmpty()) {
    StringBuilder sb = new StringBuilder();
    for (ConstraintViolation constraintViolation : violations) {
    sb.append(constraintViolation.getMessage());
    }
    throw new ConstraintViolationException(“Error occurred: ” + sb.toString(), violations);
    }

Leave a Reply

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