Open In App

Spring Boot – Service Class Example for Displaying Response Codes and Custom Error Codes

Improve
Improve
Like Article
Like
Save
Share
Report

Sometimes the error or status messages in webpages would be different from the default error message thrown by Tomcat (or any other server). An important reason for this is websites want to look unique in their approach to their users. So, a customized page for displaying status codes is always better than the standard template. Spring Boot makes it easier in this case to handle several possibilities of wrong URLs entered by the user. To start with, Spring Boot is simple enough for basic configurations with Spring Initializr (https://start.spring.io/). The following steps need to be followed after going to the starter site:

  1. The site would already have default values for group, artifact, package name, etc which can be changed per the requirements.
  2. The latest stable version of Spring would have been selected in the starter by default but you can try the unstable SNAPSHOT and M3 versions if you prefer.
  3. There is also an option to add dependencies. For our tutorial we would be coding only RESTful web services, it would be sufficient to add Spring Web and Spring Boot DevTools dependency. Spring Boot DevTools provides features faster application restarts, LiveReload, and other configurations which ensures that the developer need not restart the application every time the code is changed.

After all the steps, the project can be downloaded as a zip file. After extracting the content in the zip files, it can be imported into the IDE by clicking:

  1. Import -> Maven -> Existing Maven Projects -> Next
  2. Click browse, go to the location where the project is downloaded, select the project folder and click select folder.

Now it’s time to mention the output expectations for this tutorial. The expected output is demonstrated with screenshots. The service class is expected to show output only for GET requests, other methods should display a 405 error code.

 

If the parameter values do not match the specified possible values or no parameter is present, a page not found error page should be displayed.

 

A request to GET /format=text should return a simple return message displaying the current time and status code as OK using HashMap as the response data format.

 

A request to GET /format=page should display the webpage. This is subjective in each case and in this case we are only going to display a sample webpage available in the public domain.

 

The above requirements can be coded in Controller classes annotated with the @RestController annotation as demonstrated in the example given below.

Controller.java File

Java




package com.springboot.springbootdemo;
  
import java.lang.annotation.Repeatable;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.MethodNotAllowedException;
  
@RestController
public class Controller implements ErrorController {
  
    @GetMapping("/format=page")
    public ResponseEntity<Object> page()
    {
        return ResponseEntity.status(HttpStatus.FOUND)
            .location(URI.create(
            .build();
    }
  
    @GetMapping("/format=text")
    public HashMap<String, String> text()
    {
        HashMap<String, String> map
            = new HashMap<String, String>();
        SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd'T'HH:mm:ssZ");
        Date date = new Date(System.currentTimeMillis());
        String formattedString = formatter.format(date);
        map.put("currentTime", formattedString);
        map.put("status", "OK");
        return map;
    }
  
    @PostMapping("/**")
    public HashMap<String, String> all_except_get()
    {
        HashMap<String, String> map
            = new HashMap<String, String>();
        map.put("status", "401");
        return map;
    }
  
    @DeleteMapping("/**")
    public HashMap<String, String> all_delete()
    {
        HashMap<String, String> map = all_except_get();
        return map;
    }
  
    @PutMapping("/**")
    public HashMap<String, String> all_put()
    {
        HashMap<String, String> map = all_except_get();
        return map;
    }
  
    @PatchMapping("/**")
    public HashMap<String, String> all_patch()
    {
        HashMap<String, String> map = all_except_get();
        return map;
    }
  
    @RequestMapping("/error")
    public ResponseEntity<Object> handleError()
    {
        return ResponseEntity.status(HttpStatus.FOUND)
            .location(URI.create(
                "http://localhost:8002/LoginRegistration/404error.html"))
            .build();
    }
  
    public String getErrorPath() { return "/error"; }
}


An explainer of the code given above:

  • The function ResponseEntity<Object> page() annotated with @GetMapping(“/format=page”) handles requests to GET /format=page by redirecting the control to the webpage “https://www.geeksforgeeks.org/resource-injection-in-java-ee/” with the command ‘return ResponseEntity.status(HttpStatus.FOUND).location(URI.create(“https://www.geeksforgeeks.org/resource-injection-in-java-ee/”)).build();’
  • URI.create() creates a new URI object which parses the webpage link as URI.
  • The location() method searches for the location of the URI to which the control is to be redirected. HttpStatus.FOUND returns the response code which signifies whether the URL is reachable or not.
  • The build() method builds this entire stream of commands which is then processed by ResponseEntity.status. This entire response is then returned by the Java function after which the control is redirected to the given URL depending on the status code for the request.
  • The function ResponseEntity<Object> text annotated with @GetMapping(“/format=text”) handles requests to GET /format=text by declaring and returning the object of type HashMap<String, String>.
  • The object returns the HashMap with two key-value pairs. One key-value pair is the status code with the message “OK” and another key-value pair is the current date and time formatted as an ISO 8601 string, i.e, in the “yyyy-MM-dd’T’HH:mm’Z” format.
  • The above format can be achieved using the formatter command “SimpleDateFormat formatter= new SimpleDateFormat(“yyyy-MM-dd’T’HH:mm:ssZ”);”. The current date and time is stored in a variable using the command “Date date = new Date(System.currentTimeMillis());” which is then formatted into a string using the formatter “String formattedString=formatter.format(date);” which we declared just now.
  • The formatted string is then added to the map along with the status message. Now, the message to be displayed for the corresponding URL is returned as a map.
  • Since the service is expected to handle only GET requests and a 405 error is to be shown for other requests, (“/**”) is used after each annotation mapping to receive all requests for a given type (POST, PUT, DELETE and PATCH) and throw the 405 error message.

For example,

Java




@PostMapping("/**")
public HashMap<String, String> all_except_get()
{
    HashMap<String, String> map
        = new HashMap<String, String>();
    map.put("status", "405");
    return map;
}


is the function to handle all POST requests. Similarly, the function given below handles all the DELETE requests:

Java




@PutMapping("/**")
public HashMap<String, String> all_put() {
HashMap<String, String> map = all_except_get();
     return map;
}


As it is evident from the above code, a map with a status code need not be declared and returned each time. Since it has already been defined once, the function is invoked to get the map value into the variable which is then returned. The same procedure is followed for @DeleteMapping(“/**”) and @PatchMapping(“/**”) as well.

application.properties File

server.port=8075
server.error.whitelabel.enabled=false

Before coding the custom error handler methods, it is necessary to add the lines “server.error.whitelabel.enabled=false” in the application.properties file so that the default whitelabel error page can be overridden. 

Note: Spring Boot uses port 8080 by default to start Tomcat. If it is required to use a different port, the port number has to be mentioned in the application.properties file with the server.port=8075.

Now back to coding the error handler methods in the service class. The getErrorPath() method returns the path of the error page, which in this case returns the “/error” which is appended to the URL. Subsequently, there has to be a function to handle the error URL, which is given below:

Java




@RequestMapping("/error")
public ResponseEntity<Object> handleError()
{
    return ResponseEntity.status(HttpStatus.FOUND)
        .location(URI.create(
        .build();
}


Similar to how it was demonstrated for the @GetMapping(“/format=page”), the return statement transfers the control to the error page. Some functions that can be coded using the service class, including the custom error function, are demonstrated and explained in the examples given above.



Last Updated : 25 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads