Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Controller - show JSON instead of Whitelabel Error Page (in browser)

Hi have a simple spring controller that returns ResponseStatusException in case of error.

@RestController
@RequestMapping("/process")
public class ProcessWorkitemController {
    @Autowired MyService service;
    
    @GetMapping("/{id}")
    public ResponseEntity<?> findById(@PathVariable Long id) {
        Optional<MyObj> opt = service.getObj(id);
        opt.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("Process id %s not found", id), null));
        
        return ResponseEntity.ok(opt.get());
    }
}

This works perfctely if invoked with SoapUI: it shows me a Json as follows:

{
   "timestamp": "2021-01-20T10:59:48.082+0000",
   "status": 404,
   "error": "Not Found",
   "message": "Process id 1 not found",
   "path": "/workspace-manager/process/1"
}

When I call the same service with the browser it shows the whitelabel error page with my custmo error message.

I want a JSON as response even on the browser, is this possible?

Thanks in advance.

like image 858
cloooze Avatar asked Oct 27 '25 08:10

cloooze


1 Answers

I would avoid using ResponseStatusException, especially when building an application that needs a unified way of handling exceptions. What I would do instead is the following:

  1. Create a new class and annotate with an @RestControllerAdvice. This will effectively be the main entrypoint for exception handling of your app.
  2. Create methods that handle different types of exceptions and return a response using the message and/or information from the exceptions.
  3. Simply throw such an exception either from the service layer or from the controller layer and let the exception handler handle it.

A simple example is the following (disregard the inner classes -- only there in order to save space).

  1. Exception handler:
@RestControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(ServiceException.class)
    public ResponseEntity<ExceptionResponse> handleException(ServiceException e) {
        return ResponseEntity
            .status(e.getStatus())
            .body(new ExceptionResponse(e.getMessage(), e.getStatus().value()));
    }

    public static class ExceptionResponse {

        private final String message;
        public String getMessage() { return message; }

        private final Integer code;
        public Integer getCode() { return code; }

        public ExceptionResponse(String message, Integer code) {
            this.message = message;
            this.code = code;
        }

    }

}
  1. Base ServiceException:
package com.ariskourt.test.controllers;

import org.springframework.http.HttpStatus;

public abstract class ServiceException extends RuntimeException{

    public ServiceException(String message) {
        super(message);
    }

    public abstract HttpStatus getStatus();

}
  1. Controller
@RestController
@RequestMapping("/process")
public class ProcessController {

    @GetMapping("/{id}")
    public ResponseEntity<?> findById(@PathVariable Long id) {
        return Optional
        .of(1L)
        .filter(number -> number.equals(id))
        .map(ResponseEntity::ok)
        .orElseThrow(() -> new ProcessNotFoundException(String.format("Process with id %s not found", id)));
    }

}

With all that in place, you should a unified way of handling exceptions which also always returns the correct message not matter the client.

like image 102
akortex Avatar answered Oct 30 '25 07:10

akortex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!