Last active
November 17, 2021 11:49
-
-
Save jonikarppinen/6ade2554946df21db0a6 to your computer and use it in GitHub Desktop.
Example of using ExceptionHandler in Spring Boot: a controller method that returns either binary data or error JSON
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.company.project.controllers; | |
import org.springframework.http.HttpHeaders; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.MediaType; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.web.bind.annotation.*; | |
import java.util.Random; | |
/** | |
* Example of a Spring Boot controller method that can return either: | |
* - 200 OK with binary data (application/pdf) | |
* - 503 Service Unavailable with JSON error message | |
* | |
* (Everything defined as static nested classes just for readability of this example.) | |
* | |
* @author Joni Karppinen | |
* @since 2015-10-28 | |
*/ | |
@RestController | |
public class PdfOrErrorController { | |
/** | |
* Successful case, returns byte[] (fake PDF data) | |
* Content type will be application/pdf | |
*/ | |
@RequestMapping(value = "/test", method = RequestMethod.GET) | |
public ResponseEntity<byte[]> test() { | |
// Set Content-Type header (+ content disposition, etc, if you want) | |
// (Not using "produces", because that depends on request's Accept header including | |
// "application/pdf" and otherwise returns 406 Not Acceptable.) | |
HttpHeaders headers = new HttpHeaders(); | |
headers.setContentType(MediaType.parseMediaType("application/pdf")); | |
String filename = "output.pdf"; | |
headers.setContentDispositionFormData(filename, filename); | |
return new ResponseEntity<>(getDataOrThrowException(), headers, HttpStatus.OK); | |
} | |
/** | |
* Error case, returns ErrorResponse which Spring automatically converts to JSON (using Jackson) | |
* Content type will be application/json | |
*/ | |
@ExceptionHandler(OriginalExceptionFromAnotherApi.class) | |
@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE) | |
public ErrorResponse handle(OriginalExceptionFromAnotherApi e) { | |
return new ErrorResponse(e.getMessage()); // use message from the original exception | |
} | |
private Random random = new Random(); | |
/** | |
* Fake "service layer" | |
*/ | |
private byte[] getDataOrThrowException() { | |
if (random.nextBoolean()) { | |
return getBinaryData(); | |
} | |
else { | |
throw new OriginalExceptionFromAnotherApi("Failed because the other API is down!"); | |
} | |
} | |
private byte[] getBinaryData() { | |
byte[] b = new byte[20]; | |
random.nextBytes(b); | |
return b; | |
} | |
/** | |
* Defines the JSON output format of error responses | |
*/ | |
private static class ErrorResponse { | |
public String message; | |
public ErrorResponse(String message) { | |
this.message = message; | |
} | |
} | |
private static class OriginalExceptionFromAnotherApi extends RuntimeException { | |
public OriginalExceptionFromAnotherApi(String message) { | |
super(message); | |
} | |
} | |
} |
I found that adding this two lines in application.properties it doesn't redirect me anymore to the /error page
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried this and it is not returning JSON, just the default Whitelabel page that says I haven't made an explicit mapping for /error. In fact, it does exactly the same thing as if I had used response.sendError instead. How do I get rid of the Whitelabel page and return JSON?