JAX-RS (Reasteasy) Response.readEntity throws: IllegalStateException: RESTEASY003290: Entity is not backed by an input stream

14,196

Solution 1

Response is an abstract class and RESTEasy has different sub classes for client and server, see BuiltResponse and ClientResponse. Not all methods are supported in each sub class.

Response#readEntity needs to be backed by an input stream:

Method throws an ProcessingException if the content of the message cannot be mapped to an entity of the requested type and IllegalStateException in case the entity is not backed by an input stream or if the original entity input stream has already been consumed without buffering the entity data prior consuming.

A BuiltResponse is never backed by an input stream and therefore you get a IllegalStateException.

You can use Response#getEntity, it doesn't need an input stream.

Solution 2

Thanks for the hint.

I ended up with the following that worked for me. Simply return a new instance of the class below.

class MockResponse extends BuiltResponse {
    private Object entity;

    public MockResponse() {
    }
    public MockResponse(Object entity) {
        this.entity = entity;
    }
    @Override
    public <T> T readEntity(Class<T> type) {
        return (T) entity;
    }

    @Override
    public <T> T readEntity(Class<T> type, Type genericType, Annotation[] anns) {
        return (T) entity;
    }
}

Solution 3

Today I went through the same situation. Finally I have the below solution. Just mock the readEntity method in BuiltResponse to return whatever response you need. It worked for me.

Share:
14,196
Niels
Author by

Niels

Updated on June 14, 2022

Comments

  • Niels
    Niels almost 2 years

    I have JUnit test of a method which send a JAX-RS POST call. To be independent from external resources I have mocked the REST client and said that a dummy response should be returned. Works great, no problem. But:

    When calling myResponse.readEntity(String.class) I always get the following Exception:

    java.lang.IllegalStateException: RESTEASY003290: Entity is not backed by an input stream

    Here is my code snippet which fails:

    import com.google.gson.JsonObject;
    import com.google.gson.JsonPrimitive;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import static org.hamcrest.CoreMatchers.is;
    import static org.hamcrest.MatcherAssert.assertThat;
    import org.junit.Test;
    
    public class SimpleTest {
    
        @Test
        public void testReadResponse() {
            final JsonObject responseContent = new JsonObject();
            responseContent.add("field", new JsonPrimitive("This is a JSON for testing."));
            final String expected = responseContent.toString();
            final Response.ResponseBuilder builder = Response.ok()
                .entity(responseContent.toString())
                .header("Content-Type", MediaType.APPLICATION_JSON);
            final Response dummyResponse = builder.build();
            final String result = dummyResponse.readEntity(String.class); // <-- Exception is thrown here!
            assertThat("JSON Strings are not identical.", result, is(expected));
        }
    }
    

    and the Stacktrace:

       java.lang.IllegalStateException: RESTEASY003290: Entity is not backed by an input stream
        at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:230)
        at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:219)
        at de.me.myproject.SimpleTest.testReadResponse(SimpleTest.java:43)
    

    In my production code, which calls a not mocked REST API, it returns a automatically build response, where the .readEntity(String.class) method works fine.

  • Pang
    Pang about 7 years
    Please edit your post and show the actual code as text instead of screenshots. Others can't copy and paste from your images. See here for details. Thank you.
  • SSK
    SSK over 6 years
    Creating a mockResponse like above is not helping me. Not sure where am I going wrong :(
  • timekeeper
    timekeeper over 5 years
    getEntity() does solve the problem. Adding to getEntity(), one can typecast the getEntity() response into custom POJO and then use the usual getXXX() to perform assertEquals(typecastedResponse.getXXX(), expected)