risingTide risingTide - 2 months ago 27
Java Question

Returning an excel document via a Java REST service with Apache Wink

I need to return a Microsoft Excel file from a Java REST service. I'm using WebSphere 8.5 which inherently uses Apache Wink as it's JAX-RS implementation; that's a requirement which I can not change. I am also using Java 7 JDK. Here is the error I'm receiving:


org.apache.wink.server.internal.handlers.FlushResultHandler
handleResponse The system could not find a
javax.ws.rs.ext.MessageBodyWriter or a DataSourceProvider class for
the com.somewhere.else.message.core.BaseResponseMessage type and
application/vnd.ms-excel mediaType. Ensure that a
javax.ws.rs.ext.MessageBodyWriter exists in the JAX-RS application for
the type and media type specified.


Here is my Java Resource class method:

@GET
@Path("/report")
@Produces("application/vnd.ms-excel")
public Response getReport() {

int fileSize = 0;

byte[] reportByteArray = null;

ResponseBuilder responseBuilder = null;
InputStream report = null;

BaseResponseMessage<InputStream> baseResponseMessage = new
BaseResponseMessage<InputStream>();

Path reportPath = null;

String localPath = "C:/Users/me/Report.xls";

responseBuilder = Response.ok(baseResponseMessage);

responseBuilder.header("Content-Description", "File Transfer");
responseBuilder.header("Content-Disposition", "attachment;
filename=Report.xls");
responseBuilder.header("Content-Transfer-Encoding", "binary");
responseBuilder.header("Connection", "Keep-Alive");

reportPath = Paths.get(localPath);

if (Files.exists(reportPath)) {

if (Files.isReadable(reportPath)) {

reportByteArray = Files.readAllBytes(reportPath);

report = new ByteArrayInputStream(reportByteArray);
}
}

fileSize = report.available();

responseBuilder.header("Content-Length", fileSize);

baseResponseMessage.setPayload(report);

return responseBuilder.build();
}


I do know from looking at the debugger that the path and the excel file are found correctly, and the fileSize is populated correctly as well.

I will gladly provide any more information that is needed. Thank you for your time!

Answer

The problem was the existence of the BaseResponseMessage. Apparently because I was actually returning the BaseResponseMessage in the Response object instead of the actual InputStream JAX-RS didn't know how to process it since (as the error states) there isn't a MessageBodyWriter or DataSourceProvider specifically associated with that combination. Funny how the error message actually revealed the actual problem had I read it more closely! :p

When the code above is modified to remove the BaseResponseMessage and do something like this:

responseBuilder = Response.ok(report);

then it will work just fine.

[As an aside, returning an InputStream is not really a good idea anyway; the code has since been modified to return a StreamingOutput object.]