Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @ExceptionHandler returns HTTP 406

I've got some strange Error.

What I want to do: The client asks GET: /invoices/invoiceNumber with header Accept: application/pdf and I want to return PDF file. If client forgot about header I return HTTP 406.

The method that returns PDF bytes throws DocumentNotFoundException that is handled by Spring ExceptionHandler and should return 404, but it didn't. Instead of that, I've got 406 and server log:

 2017-06-01 15:14:03.844  WARN 2272 --- [qtp245298614-13] o.e.jetty.server.handler.ErrorHandler    : Error page loop /error

The same magic happens when Spring Security returns HTTP 401.

So I think that problem is that Client Accept application/pdf but Spring ExceptionHandler returns application/json, so jetty dispatcher override 404 with 406 :(

My code:

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Invoice not found")
@ExceptionHandler(DocumentNotFoundException.class)
public void handleException() {
    //impl not needed
}

@GetMapping(value = "invoices/**", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> getInvoicePdf(HttpServletRequest request) {
    String invoiceNumber = extractInvoiceNumber(request);
    final byte[] invoicePdf = invoiceService.getInvoicePdf(invoiceNumber);
    return new ResponseEntity<>(invoicePdf, buildPdfFileHeader(invoiceNumber), HttpStatus.OK);

}

@GetMapping(value = "invoices/**")
public ResponseEntity getInvoiceOther() {
    return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
}

Can someone help me with understanding that?

like image 430
Daniel Wojciechowski Avatar asked Oct 30 '22 07:10

Daniel Wojciechowski


1 Answers

The problem is that Spring tries to convert the error response to application/pdf but fails to find a suitable HttpMessageConverter which supports conversion to PDF.

The easiest solution is to manually create the error response:

@ExceptionHandler(DocumentNotFoundException.class)
public ResponseEntity<?> handleException(DocumentNotFoundException e) {

    return ResponseEntity
        .status(HttpStatus.NOT_FOUND)
        .contentType(MediaType.APPLICATION_JSON_UTF8)
        .body("{\"error\": \"Invoice not found\"}");
}

This bypasses message conversion and results in a HTTP 404 response code.

like image 138
Marvin Frommhold Avatar answered Nov 15 '22 04:11

Marvin Frommhold