I have a Spring Boot application with an already working endpoint that produces an xlsx file.
Now, I want to implement content negotation on this endpoint but I always receive 406 Not Acceptable
.
{
"timestamp": "2021-03-09T18:44:56.997+0000",
"status": 406,
"error": "Not Acceptable",
"message": "Could not find acceptable representation",
"path": "/students/excel"
}
And I am using URL parameters and I am calling it like that
localhost:8080/students/excel/excel?format=xlsx
The implementation
Endpoint
@PostMapping(path = "/excel", produces = {"application/vnd.ms-excel"})
public byte[] generateExcel(HttpServletResponse response, final @RequestBody @NonNull Criteria criteria) {
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=Students.xlsx");
return studentService.generateExcelReport(response, criteria);
}
The method that is finalizing the excel file.
public static byte[] write(HttpServletResponse response, final @NonNull XSSFWorkbook workbook) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
os.writeTo(response.getOutputStream());
workbook.write(os);
workbook.close();
return os.toByteArray();
} catch (final IOException ex) {
throw new RuntimeException("Error generating excel", ex);
}
}
And the relevant method on WebConfiguration
that implements WebMvcConfigurer
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("format").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.APPLICATION_JSON).
mediaType("xlsx", MediaType.MULTIPART_FORM_DATA);
}
I tried a lot of combinations with MediaType
and on WebConfiguration
and the attribute of produces
like
application/csv
to check if there is a possibility that it could work due to formating of the excel file and others. But I couldn't overcome this status. When setting it to application/json
and text/plain
it works but it's not the wanted functionality or the correct one.
When I am not using content negotiation, the generation of the excel works as I mentioned.
Edit:
Based on suggestions, I changed the content type to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
and changed the header of both Accept
and Content-Type
on Postman and still receive 406
.
This is how the request on Postman looks
I also debugged the application and it doesn't enter the method of the endpoint, it seems to fail instantly because of the produces value.
Ι want to add that this is a POST request that accepts a JSON. So, using any other content-type on Postman will break it.
Update
It works by using the accept header instead of parameters and changing WebConfigurer
method. But, I wanted to to use URL parameters and to understand why they don't work.
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true).
favorParameter(false).
ignoreAcceptHeader(false).
useJaf(false);
}
I found a solution in order to make it work with URL parameters, as it was my first intention.
I added a new Media Type of vnd.ms-excel
on WebConfiguration
as following.
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("format").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.APPLICATION_JSON).
mediaType("xlsx", new MediaType("application","vnd.ms-excel"));
}
On Accept
header of the request I added the value application/vnd.ms-excel
.
Finally, by calling the excel endpoint now with the needed format it generates the excel file properly.
localhost:8080/students/excel/excel?format=xlsx