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.
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
@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);
You saved my day! Many many thanks! :)
ReplyDeleteThis is a very useful bit, thank you:
ReplyDeleteByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(response.getEntityInputStream(), bos);
byte[] result = bos.toByteArray();
Great post. Thanks
ReplyDeletethank you :)
ReplyDeleteNice Article
DeleteWith "streaming" you are talking about HTTP completed upload/download to/from a server, right?! :)
ReplyDeleteYes complete download from a rest api. Upload is also similar.
DeleteI need to stream records as they are available. Hence i have
ReplyDeleteimport java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import javax.ws.rs.core.StreamingOutput;
import org.apache.log4j.Logger;
public class StreamingOutputImpl extends RetrieverResource implements StreamingOutput {
private static final Logger LOGGER = Logger.getLogger(StreamingOutputImpl.class);
private OutputStream os;
public StreamingOutputImpl(final RequestParameters parameters, final String basePath) {
super(parameters, basePath);
}
@Override
public void write(final OutputStream os) throws IOException {
this.os = os;
read();
}
@Override
public void writeRecord(final GenericRecord record) {
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(os));
writer.write(record.toString());
writer.flush();
} catch (final IOException e) {
LOGGER.error("Error while write record " + record, e);
}
}
}
Assuming i have 100 records, and writeRecord() is invoked 100 times. I see the output in browser (with @GET and @POST) only after 100 th record and not after every record.
Any suggestions?
How to implement the client in Jersey 2?
ReplyDeleteJust return the byte[] as entity works for me.
ReplyDeletefor documents < 2GB yes, but for streaming data (a radio program that runs 24/7 for years for example) this would not be sufficient.
DeleteByteArrayOutputStream bos = new ByteArrayOutputStream();
ReplyDeleteIOUtils.copy(response.getEntityInputStream(), bos);
byte[] result = bos.toByteArray();
YOU SIMPLY SAVED ME!!! Thanks a lot!!!