spring-bootcsvservlet-3.0opencsv

java.lang.IllegalStateException: getWriter() has already been called for this response, Even thought its called only once


I am using spring-boot. I want to send a CSV as the attachment of response for which I am using opencsv to write bean to response. Even though response.getWriter() is called only once, I am getting this exception.

While searching for solution, I came to know that we cannot use response.getWriter() and response.getOutputStream() together. But this is not the case here.

I am only calling getWriter and exactly once.

I also checked if it was due to opencsv library by writing a plain string to it e.g. "name, test". But still the same error. So it's not due to opencsv either.

private Pair<Boolean, String> writeCSVToResponse(List<QuestionDownloadResponse> qdrList,  HttpServletResponse response) {
    String fileName = new SimpleDateFormat("'CSV'yyyyMMddHHmmss'.csv'").format(new Date());
    response.reset();
    response.setContentType("application/csv");
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=\"" + fileName + "\"");
    response.setCharacterEncoding("UTF-8");
    //Find answer, for now we will return any if exists
    try {
        Writer writer = response.getWriter();
        // Create Mapping Strategy to arrange the  
        // column name in order 
        final CustomCSVMappingStrategy<QuestionDownloadResponse> mappingStrategy = new CustomCSVMappingStrategy<>();

        mappingStrategy.setType(QuestionDownloadResponse.class); 

        StatefulBeanToCsv<QuestionDownloadResponse> sbc = new StatefulBeanToCsvBuilder<QuestionDownloadResponse>(writer)
           .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
           .withMappingStrategy(mappingStrategy)
           .build();

        sbc.write(qdrList);

    } catch (IOException e) {
        CMSQuestionServiceImpl.logger.error("Error in CSV IO operations", e);
        return Pair.of(false, "Failed to Open file");
    } catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
        CMSQuestionServiceImpl.logger.error("Error in CSV Write operation", e);
        return Pair.of(false,"Failed to write in csv");
    }

}

Why is this exception coming, even when response.getWriter is called exactly once. How to solve this issue.


Solution

  • I found the issue. The problem was that I was sending a String (a message) in response in the controller, but in service, I am sending an attachment. So getWriter() was being called first time in service by me, and the second time by spring to write the response message of type String. Solution: I set the return type of method in the controller to void ex::

    @GetMapping(value = "/downloadCSV") public void downloadCSV(@RequestBody(required = false) List<Integer> items, HttpServletResponse response){

    The only problem is if something goes wrong in service, you cannot send an error message and there are other alternatives to overcome it.