Sunday, April 24, 2011

Jersey streaming binary data

In the previous post I showed how you can post binary data to a jersey REST api. You can also use Jersey to serve files, although its better done by apache or nginx but sometimes you might want to serve thumbnails stored in a database out of a service and put varnish in front of the REST api to cache the thumbnails. This is just a demonstration of using jersey to serve binary data in streaming fashion.

@Path("/download-service")
public class DownaloadService extends SecureRestService {
 private static final AppLogger logger  = AppLogger.getLogger(DownaloadService.class);

 @POST
 @Produces(MediaType.APPLICATION_OCTET_STREAM)
 public StreamingOutput getThumbnail(
   @FormParam("securityKey") final String securityKey,
   @FormParam("guid") final String guid) throws JSONException {
  return new StreamingOutput() {
   @Override
   public void write(OutputStream out) throws IOException {
    try {
     if (!isAuthorized(securityKey)) {
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
     } else {
      //Read thumbnail out of database and dovetail both streams(IOUtils.copy) to directly stream to the response without storing them in memory.
     }
    } catch (Throwable t) {
     logger.error(t);
     response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage());
    }
   }
  };
 }
}


To test this code you can again use Jersey client api and to verify against response status or data you can use the ClientResponse class as shown below

  Form form = new Form();
  form.add("securityKey", getSecureToken());
  form.add("guid", guid);

  ClientResponse response = webResource.path(
    "download-service").post(ClientResponse.class, form);
  Assert.assertNotEquals(HttpServletResponse.SC_NOT_AUTHORIZED, response.getStatus());

  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  IOUtils.copy(response.getEntityInputStream(), bos);
  byte[] result = bos.toByteArray();
  Assert.assertArrayEquals(expected, result);

3 comments:

  1. You saved my day! Many many thanks! :)

    ReplyDelete
  2. This is a very useful bit, thank you:

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    IOUtils.copy(response.getEntityInputStream(), bos);
    byte[] result = bos.toByteArray();

    ReplyDelete