2

I'm working on a service to PUT and GET InputStream objects based on a key - these can be anything from basic Strings to files. Here is the PUT method which appears to work just fine:

@PUT
@Path("{key}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response addData(
    final @PathParam("key") String key,
    final InputStream data) {
  final Service service =  new Service();
  try {
    service.addData(key, data);
  } finally {
    IOUtils.closeQuietly(data
  }
  return Response.status(204).build();
}

Now when I want to get the data (based on a key) I want to return the InputStream which is how the object is stored and retrieved. This is what I have currently:

@GET
@Path("/{key}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
  public InputStream getData(
    @PathParam("key") String key) {
  // get service and do other stuff ...
  return service.getData(); //This is an InputStream
}

When I send a GET, I get a status 200 and a 'Response Does Not Contain Any Data' message ... when I examine the request in Fiddler, it doesn't look like the data is attached. Am I missing something simple here? Thanks.

Edit: Here are the responses from:

It seems like there's nothing attached to the response, but I'm not sure. Is there a good way to test whether or not it's returning the InputStream?


Edit2: Interesting. Per peeskillet's suggestion of reading the data to see if it's even there I did this:

final String data = IOUtils.toString(stream);

This returns "" when it should be returning "test". Now I'm not super familiar with IOUtils so maybe their toString(InputStream) is causing it to be "test", but that would suggest that it's not getting set properly in the service.

My service for getting the InputStream data looks something like this:

final InputStream data = getData(_key);
  try {
    if (data == null) {
      return null;
    }
    return object.newBuilder()
      .setKey(_key)
      .setData(data)
      .build();
  } finally {
    IOUtils.closeQuietly(data);
  }

Would anything in the service be causing the stream to be read therefore making it non-accessible?


Edit3: The problem is in the service when I set the data to be returned. If I remove IOUtils.closeQuietly(data); I'm able to get the data back just fine. However this causes issues because I leave an InputStream open... any workaround suggestions?

joshft91
  • 1,755
  • 7
  • 38
  • 53
  • Try and read the stream from inside the resource method and return _that_ result instead of the stream. See if it returns anything – Paul Samsotha Dec 01 '14 at 17:25
  • I added more information to my original post...thanks for the suggestion. It would seem I'm pretty clearly doing something wrong in the service layer. – joshft91 Dec 01 '14 at 17:54
  • If you close the stream RESTeasy can't read from it. You could try to close the stream in your resource-method. But I doubt if you'll have real streaming through all your layers anyway. – lefloh Dec 01 '14 at 20:35
  • I tried wrapping it in a try/finally block in the resource where the `try` gets the InputStream and returns it and then the `finally` closes the stream, but I get the same results as before. I'm assuming the stream is closed first and then it attempts to return what's not there. – joshft91 Dec 01 '14 at 20:59
  • Have you consider return something else rather than an InputStream, from `getData()` method? Like maybe a `byte[]`. See [here](http://stackoverflow.com/a/1264756/2587435) – Paul Samsotha Dec 02 '14 at 19:05

2 Answers2

0

Returning an InputStream should work unless somebody already read from the stream. You can't read twice from an InputStream.

lefloh
  • 10,653
  • 3
  • 28
  • 50
  • As far as I can tell the InputStream has not been read at all. This is the response in the Advanced Rest Client (http://i.imgur.com/OfSSAxj.jpg) and here in Fiddler (http://i.imgur.com/DTtkByr.jpg). It seems that there's nothing attached to it, but I'm not sure if there's a good way to verify whether there is or not. – joshft91 Dec 01 '14 at 17:06
0

The problem was related to leaving the InputStream open. However, there was a bug in the version of RestEasy that caused the InputStream to not be closed. The ticket/fix is found here: https://issues.jboss.org/browse/RESTEASY-741

joshft91
  • 1,755
  • 7
  • 38
  • 53