I have the below class that tries to return some data in the form of an excel spreadsheet. I'm getting the error
MessageBodyWriter not found for media type=application/octet-stream, type=class org.apache.poi.xssf.usermodel.XSSFWorkbook
I've also tried @Produces("application/vnd.ms-excel")
, but have gotten similar errors. Anyone have a suggestion as to how I can get this to return a spreadsheet? The last time I got an error message similar to this (complaining that a message body writer couldn't be found for arraylist) I just wrapped it in a generic entity. That trick didn't work this time.
@PermitAll
@Path("uploadWorkbook")
public class ExcelUploadResource {
@Context
ResourceContext resourceContext;
@Inject
JobService jobService;
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response list() {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Job definitions");
int rowNum = 0;
for(Job job : jobService.list()){
Row row = sheet.createRow(rowNum++);
int cellNum = 0;
for(String field : job.toList()){
Cell cell = row.createCell(cellNum++);
cell.setCellValue(field);
}
}
GenericEntity<XSSFWorkbook> entity = new GenericEntity<XSSFWorkbook>(workbook) {};
ResponseBuilder response = Response.ok(entity);
response.header("Content-Disposition",
"attachment; filename=jobs.xls");
return response.build();
}
}
You can't just use arbitrary objects with the data type application/octet-stream
. What you first need to understand is how objects are serialized. This is done with the use of MessageBodyWriter
s. You can learn more about them in JAX-RS Entity Providers.
How the writer works is that it is passed the entity and the response stream. The writer is supposed to take the entity and write the contents of the entity to the response stream. The writers are looked up by the type of entity we return and the media type expected, in your case you want it to be application/octet-stream
.
What the error is saying is that there is no writer to handle the conversion of your XSSFWorkbook
. When you talk about application/octet-stream
, you're mostly dealing with binary files. XSSFWorkbook
is not a binary file. When working with application/octet-stream
, you'll mostly be working with byte[]
, File
, InputStream
, and StreamingOutput
entity types. So if you want to use application/octet-stream
, then you would need to change the entity to be one of those types.
I've never used Apache POI, but just going through a quick tutorial, it looks like what you probably want to use for this case is the StreamingOutput
, you can just use the XSSFWorkbook#write(OutputStream)
method to write the workbook to the StreamingOutput
public Response getExcelFile() {
XSSFWorkbook workbook = new XSSFWorkbook();
...
StreamingOutput output = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
workbook.write(out);
out.flush();
}
};
return Response.ok(output)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=jobs.xls")
.build();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With