Here's another example. I'm creating a QRCode as a PNG via a ByteArrayOutputStream
. The resource returns a Response
object, and the stream's data is the entity.
To illustrate the response code handling, I've added handling of cache headers (If-modified-since
, If-none-matches
, etc).
@Path("{externalId}.png")
@GET
@Produces({"image/png"})
public Response getAsImage(@PathParam("externalId") String externalId,
@Context Request request) throws WebApplicationException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// do something with externalId, maybe retrieve an object from the
// db, then calculate data, size, expirationTimestamp, etc
try {
// create a QRCode as PNG from data
BitMatrix bitMatrix = new QRCodeWriter().encode(
data,
BarcodeFormat.QR_CODE,
size,
size
);
MatrixToImageWriter.writeToStream(bitMatrix, "png", stream);
} catch (Exception e) {
// ExceptionMapper will return HTTP 500
throw new WebApplicationException("Something went wrong …")
}
CacheControl cc = new CacheControl();
cc.setNoTransform(true);
cc.setMustRevalidate(false);
cc.setNoCache(false);
cc.setMaxAge(3600);
EntityTag etag = new EntityTag(HelperBean.md5(data));
Response.ResponseBuilder responseBuilder = request.evaluatePreconditions(
updateTimestamp,
etag
);
if (responseBuilder != null) {
// Preconditions are not met, returning HTTP 304 'not-modified'
return responseBuilder
.cacheControl(cc)
.build();
}
Response response = Response
.ok()
.cacheControl(cc)
.tag(etag)
.lastModified(updateTimestamp)
.expires(expirationTimestamp)
.type("image/png")
.entity(stream.toByteArray())
.build();
return response;
}
Please don't beat me up in case stream.toByteArray()
is a no-no memory wise :) It works for my <1KB PNG files...