0

How to return error in springboot and close a Closeable class? When I got some error in springboot and close a closable class is returning 200 OK

don't I need close the Closeable? Is there some way to handle this on springboot?


   CSVPrinter csvPrinter;

    try{

        csvPrinter = new CSVPrinter(httpServletResponse.getWriter() , CSVFormat.DEFAULT);

        System.out.println(1/0); // force exception to jump into catch

    }catch (Exception e) {

        e.printStackTrace();

        try { csvPrinter.close(true); } catch (IOException e1) { e1.printStackTrace(); } // has returned 200 OK when closing CSVPrinter
         
        throw new RuntimeException("Error"); // this are been called but was already returned 200
    }


I've tried on try-with-resources but no success too

    try( final CSVPrinter csvPrinter = new CSVPrinter( httpServletResponse.getWriter() , CSVFormat.DEFAULT) ){

        System.out.println(1/0); // // force exception to jump into catch

    }catch (Exception e) {  // has returned 200 OK 
        throw new RuntimeException("Error"); // this are been called but was already returned 200
    }

I'm inject httpResponse in controller

  @GetMapping("/export")
   public void exportInCsv(
                ExportRequest exportRequest,
                HttpServletResponse httpServletResponse // inject httpreponse
             ){

        exportService.writeResponse(exportRequest,httpServletResponse);
    }

I have no controller exception handler

Dilermando Lima
  • 1,004
  • 8
  • 21

1 Answers1

0

Your controller method (exportInCsv()) doesn't actually return a ResponseEntity object, so GET requests made to this endpoint will always result in 200 responses.

You should either throw a checked exception as a result of a failure to do something (construct or close an instance of CSVPrinter), or implement ResponseEntityExceptionHandler more generally in your code to catch unchecked exceptions and respond with a generic error message (and 400).

Personally, I prefer the former way of doing things, as the code will end up more explicit and allow you more customisation of your endpoint (but it is not a bad idea to do both).

Pseudocode

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


import java.util.UUID;


@RestController
@RequestMapping("/widgets")
public class WidgetController {

    @GetMapping(value = "/{widgetId}", produces = "application/json")
    public ResponseEntity<?> fetchWidget(@PathVariable UUID widgetId) {
        try {
            Widget widget = findWidgetById(widgetId);

            return ResponseEntity.ok().body(widget);
        } catch (CheckedException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    private Widget findWidgetById(UUID widgetId) throws CheckedException {
        Widget widget = findMethodThatMightThrowCheckedException(widgetId);

        return widget;
    }

}

With a checked exception, you also have the option of dealing with it a lower level (closer to where it was initially thrown), but it sounds like you want to bubble it up (and map it to an HTTP response) to the client of your GET /export API.

Blair Nangle
  • 1,221
  • 12
  • 18
  • I tried return `ResponseEntity` or using checked exception then the same result. all erros in all service are been handled perfectly except inside this try-statement that closes closable and return 200 – Dilermando Lima Nov 19 '21 at 13:02
  • Do I really need to change all implementation service and libs to treate download return `ResponseEntity ` ? is there a way to do this writing in httpresponse and if I got some error inside try-with-resource spring-boot don't return 200 before jump into catch? – Dilermando Lima Nov 19 '21 at 13:11
  • Have you tried abstracting your CSV writing logic into a method and writing a test for that method? It should be possible to isolate the unexpected behaviour at the (lower) level of a method or service, rather than just relying on the HTTP response code produced by the controller for feedback. – Blair Nangle Nov 19 '21 at 19:17