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 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); } } }