0

I have a Factory<T> that uses the InputStream from ContainerRequestContext to create T. In my factory I mark and reset the InputStream so that Jersey can then inject the body into the endpoint parameter. This works fine

problem: if I swap the ordering of these parameters (String body first, then @Context T t) it breaks. Jersey has closed the InputStream before my Factory<T> tries to read from the InputStream.

Factory<T>:

@Override
public T provide() {
    InputStream inputStream = containerRequestContext.getEntityStream();
    inputStream.mark(Integer.MAX_VALUE);

    T t = new T(inputStream);

    inputStream.reset();
    return t;
}

ResourceConfig endpoint (works):

@POST
public Response getBodyDouble(@Context T t, String body) {}

ResourceConfig endpoint (creating T fails):

@POST
public Response getBodyDouble(String body, @Context T t) {}

Stack trace:

java.lang.IllegalStateException: Entity input stream has already been closed.
        at org.glassfish.jersey.message.internal.EntityInputStream.ensureNotClosed(EntityInputStream.java:225)
        at org.glassfish.jersey.message.internal.InboundMessageContext.getEntityStream(InboundMessageContext.java:762)
        at com.-.TFactory.provide(TFactory.java:xx)

Is there a way to prevent Jersey from closing the InputStream when it injects the body? Or some way to re-open it? Thanks

  • Even if Jersey didn't close the input stream, it would already have **consumed** the stream, so preventing close will not make the code work anyway. Why would you need the body twice anyway? If you really do, 1) create `t` from `body`, 2) create `body` from `t`, 3) accept a `byte[]` and create both from it, 4) accept `InputStream` and create both from it, or 5) ... *many other ways to do it* – Andreas Jun 26 '19 at 19:05
  • Right. But potentially an unclosed stream could be reset or wrapped so that downstream consumers could use it. – Alex Petrovich Jun 26 '19 at 21:04
  • I'm writing a wrapper library, so the use-case is just me wanting to keep the second endpoint contract safe :) It's a scary error, and it's not obvious (except for people who know jersey) that the parameter ordering would fix the problem – Alex Petrovich Jun 26 '19 at 21:06
  • What would fix the problem is not asking Jersey for the request body twice. Otherwise see [Logging HttpRequest parameters and request body](https://stackoverflow.com/q/6322362/5221149) or [Spring REST service: retrieving JSON from Request](https://stackoverflow.com/q/10457963/5221149) or any other [similar question](https://www.google.com/search?q=java+request+body+logger). – Andreas Jun 26 '19 at 21:13
  • There are _a lot_ of use cases where you would want access to the body outside of the resource method. – Paul Samsotha Jun 26 '19 at 22:00
  • One way would be to force Jersey to buffer the entity. If you created a filter that casted the ContainerRequestContext to ContainerRequest, you could call cr.bufferEntity(). That's just one solution I can think of. Not sure if it is the _best_ though. – Paul Samsotha Jun 26 '19 at 22:02

0 Answers0