3

I'm using Spring boot 1.5.10. I have a RestController that handles file uploads, which I'm calling from another process using RestTemplate.

When the file I'm trying to upload is too big, Tomcat triggers a org.apache.tomcat.util.http.fileupload.FileUploadBase.SizeLimitExceededException (as expected). I want to handle it nicely by returning a custom HTTP response, but so far none of my attempts seem to matter in any way because restTemplate.exchange always throws the following exception:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://127.0.0.1:8080/api/upload": Software caused connection abort: recv failed; nested exception is java.net.SocketException: Software caused connection abort: recv failed

What I've tried so far:

What have I missed? Why is my handler's response ignored?

Update:

I tried the ExceptionHandler approach on Mac and it works as expected. Could this be Windows-specific ?


Here's some of my code (significant bits only):

Upload controller method:

   @PostMapping("/upload")
    public ResponseEntity<?> uploadFile(
            @RequestParam("file") MultipartFile file
            ) throws IOException {

        // do something with the file
        return new ResponseEntity<>("Successfully uploaded '" + file.getOriginalFilename() +"'",
                new HttpHeaders(), HttpStatus.OK);    
    }

RestTemplate call:

    RestTemplate restTemplate = new RestTemplate();
    URL url = new URL("http", this.targetHostname, this.targetPort, "/upload");

    // build request
    MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
    map.add("file", new PathResource(path));
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);

    // perform HTTP request
    ResponseEntity<String> result;
    try {
        result = restTemplate.exchange(
                url.toURI(),
                HttpMethod.POST,
                requestEntity,
                String.class);
    } catch (RestClientException e) {
        log.error("Exception during file upload: ", e);
        return;
    }
    log.debug("Result of upload: " + result);

Attempt with ExceptionHandler:

@ControllerAdvice
public class RestResponseEntityExceptionHandler {

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    ResponseEntity<?> handleMultipartException(HttpServletRequest request, Throwable ex) throws Throwable {
        Throwable cause = ex.getCause();
        if (cause instanceof IllegalStateException) {
            Throwable cause2 = cause.getCause();
            if (cause2 instanceof FileUploadBase.SizeLimitExceededException) {
                return new ResponseEntity<>(cause2.toString(), HttpStatus.PAYLOAD_TOO_LARGE);
            }
        }

        throw ex;
    }
}

Attempt with ErrorHandler:

@RestController
public class RestErrorController implements ErrorController {

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return "Some error message";
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}
Olivier Gérardin
  • 1,113
  • 14
  • 27

0 Answers0