Spring Boot — REST with Custom Error Msg and Log | Code Factory

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.10.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.codeFactory</groupId>
<artifactId>spring-boot-custom-err-response-and-logger</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-custom-err-response-and-logger</name>
<description>Rest endpoint with validation</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.codeFactory;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author code.factory
*/
@SpringBootApplication
public class SpringBootCustomErrResponseAndLogger {
public static void main(String[] args) {
SpringApplication.run(SpringBootCustomErrResponseAndLogger.class, args);
}
}
package com.codeFactory;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.codeFactory.utility.LogInterceptor;/**
* @author code.factory
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
}
}
package com.codeFactory.controller;import javax.validation.Valid;import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.codeFactory.model.Employee;/**
* @author code.factory
*/
@RestController
@Validated
public class EmployeeController {
@PostMapping(value = "employee", consumes = "application/json", produces = "application/json")
public ResponseEntity<Employee> displayEmployee(@Valid @RequestBody Employee employee) {
return ResponseEntity.ok(employee);
}
}
package com.codeFactory.model;import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* @author code.factory
*/
public class Employee {
@Min(value = 1, message = "Id can't be less than 1 or bigger than 999999")
@Max(999999)
private int id;
@Size(max = 15, message = "Name must be less than 15 characters")
@NotBlank
@Pattern(regexp = "^[A-Za-z ]*$", message = "Only characters allowed")
private String name;
@NotBlank
@Pattern(regexp = "^[A-Za-z ]*$", message = "Only characters allowed")
private String designation;
@NotBlank
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package com.codeFactory.utility;import java.util.UUID;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/**
* @author code.factory
*/
public class LogInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestId = UUID.randomUUID().toString();
log(request, response, requestId);
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
request.setAttribute("requestId", requestId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
LOGGER.info("Request Id: {}, Handle: {} , Request take time: {}",
request.getAttribute("requestId"), handler, executeTime);
LOGGER.info("Response status: {}, Content type: {}",
response.getStatus(), response.getContentType());
}
private void log(HttpServletRequest request, HttpServletResponse response, String requestId) {
LOGGER.info("Request Id: {}, Host {} HttpMethod: {}, URI: {}",
requestId, request.getHeader("host"), request.getMethod(), request.getRequestURI());
}
}
package com.codeFactory.utility;import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
/**
* @author code.factory
*/
@ControllerAdvice
public class ValidationUtil {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
@ResponseBody
public Error handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) {
BindingResult result = ex.getBindingResult();
List<String> errorList = new ArrayList<>();
result.getFieldErrors().forEach((fieldError) -> {
errorList.add(fieldError.getObjectName() + "." + fieldError.getField() + " : "
+ fieldError.getDefaultMessage() + " : rejected value [" + fieldError.getRejectedValue() + "]");
});
result.getGlobalErrors().forEach((fieldError) -> {
errorList.add(fieldError.getObjectName() + " : " + fieldError.getDefaultMessage());
});
return new Error(HttpStatus.BAD_REQUEST, errorList);
}
public static class Error {
private int errorCode;
private String error;
private List<String> fieldErrors = new ArrayList<>();
public Error(HttpStatus status, List<String> fieldErrors) {
this.errorCode = status.value();
this.error = status.name();
this.fieldErrors = fieldErrors;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public List<String> getFieldErrors() {
return fieldErrors;
}
public void setFieldErrors(List<String> fieldErrors) {
this.fieldErrors = fieldErrors;
}
}
}
com.codeFactory.utility.LogInterceptor   : Request Id: 1ae345fb-7d48-4f94-b507-d4e18dd29d36, Host localhost:8080  HttpMethod: POST, URI: /employee
com.codeFactory.utility.LogInterceptor : Request Id: 1ae345fb-7d48-4f94-b507-d4e18dd29d36, Handle: com.codeFactory.controller.EmployeeController#displayEmployee(Employee) , Request take time: 736
com.codeFactory.utility.LogInterceptor : Response status: 200, Content type: application/json
com.codeFactory.utility.LogInterceptor : Request Id: 210e19d3-11d5-415d-9a3b-e89f85c63667, Host localhost:8080 HttpMethod: POST, URI: /employee
com.codeFactory.utility.LogInterceptor : Request Id: 210e19d3-11d5-415d-9a3b-e89f85c63667, Handle: com.codeFactory.controller.EmployeeController#displayEmployee(Employee) , Request take time: 114
com.codeFactory.utility.LogInterceptor : Response status: 400, Content type: application/json

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Wrapping up the Virtual Meetup

A Complete Guide To Uipath ReFramework

Happy Chinese Bull Year,Bull Bull Lucky bags Aidrops from Cocos-BCX

Ultimate Beginners Guide To Understanding Blockchain Traceability — (Part 8)

Unity Tips: Scriptable Objects

Different Lights in Unity

Yet another guide to Sockets Programming

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Code Factory

Code Factory

More from Medium

2 Ways to Upload Files to Amazon S3 In Your Spring Boot Project

Why Spring Boot is called opinionated?

Secure your Spring Boot Rest API with Keycloak

Obfuscate Spring Boot Applications with Proguard Maven Plugin