Export CSV File - JAX RS - REST - AJAX

Viewed 10354

I create a function to download a CSV File. I will use that to download simple reports. I got the error below on Netbeans using Wildfly and JAX RS

RESTEASY002005: Failed executing POST /reports/downloadCSV/: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: java.io.FileWriter of media type: application/octet-stream

Here is my Code:

Controller

Update on ParametersClass

@POST
@Path("/downloadCSV")
@Produces("application/octet-stream")
public Response downloadCSV(ParametersClass param) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    FileWriter fileWriter = null;
    Date date = new Date();
    try {
        fileWriter = new FileWriter("MainReport_"+dateFormat.format(date)+".csv");
        fileWriter.append(csvService.mainReport(dateFormat.parse(param.getStartDate()),dateFormat.parse(param.getEndDate())));
        fileWriter.flush();
        fileWriter.close();

        ResponseBuilder response = Response.ok((Object) fileWriter);  
        response.header("Content-Disposition","attachment; filename=\"MainReport_"+dateFormat.format(date)+".csv\"");  
        return response.build();  
    } catch (ParseException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

The csvService returns a String like:

 Column1,column2,column3
 cellInfo1,cellInfo2,cellInfo3
 ,cellInfo2,cellInfo3
 cellInfo1,,cellInfo3
 cellInfo1,cellInfo2,
 ,,cellInfo3

I tried using a different @Produces => @Produces('text/csv') , @Produces('application/octet-stream')

If I remove the Annotation @Produces I got the following error:

RESTEASY002010: Failed to execute: javax.ws.rs.NotSupportedException: RESTEASY003200: Could not find message body reader for type: class com.xo.CSVFile of content type: application/x-www-form-urlencoded;charset=UTF-8

AJAX

     var dateRange = new Object();
     dateRange.startDate = '2017-07-20';
     dateRange.endDate = '2017-08-10';
     $.ajax({
          type: 'POST',
          url: appPath + '/api/reports/downloadCSV/',
          data: JSON.stringify(dateRange),
          async:true,
          success: function(data) {
           }
     });

What I'm doing wrong ? Could you help to me please!

.

SOLUTION Thanks to @albert-bos

1st. Check the link in the solution from @albert-bos below.

2nd: Check this link too

3rd:

Controller:

@POST
@Path("/downloadCSV")
@Produces("text/csv")
public List<LinkedHashMap<String, String>> downloadCSV(ParametersClass param) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    try {
        return csvService.mainReport(dateFormat.parse(param.getStartDate()),dateFormat.parse(param.getEndDate()));
    } catch (ParseException ex) {
        return null;
    }
}

MessageBodyWriter: I create a class called CSVMessageBodyWritter (check the link) but I adpated the method writeTo:

 @Override
 public void writeTo(Object t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
      CsvSchema schema = null;
      CsvSchema.Builder schemaBuilder = CsvSchema.builder();
      if(t!=null){
           List<LinkedHashMap<String, String>> reportArray = (List<LinkedHashMap<String, String>>) t;
           LinkedHashMap<String, String> headers = reportArray.get(0);

           for (String col : headers.keySet()) {
                 schemaBuilder.addColumn(col);
           }
           schema = schemaBuilder.build().withLineSeparator("\r");
           CsvMapper mapper = new CsvMapper();
           mapper.writer(schema).writeValues(entityStream).writeAll(reportArray);
      }
 }
3 Answers

I don't have enough rep so can't add a comment for the answer of Albert Bos.

There is a PITFALL with that solution: you can suddenly run into the problem when you get empty csv file even if it should have a data. It happens because of result of getSize method.

I'm not sure which version of JAX-RS is supposed to be used in that example (in the article), but accordingly to the jax-rs documentation, result of getSize is ignored for JAX-RS 2.0, but for JAX-RS 1.X it seems to be used and "return 0" makes downloaded file empty. Make sure you return "-1". I've encountered it when tried to implement csv export in JIRA rest plugin (I guess it's based on first version of JAX-RS).

Related