[resteasy-dev] [Resteasy-developers] Proper handling of NotModified/304

Marek Kopecky mkopecky at redhat.com
Mon Jun 20 04:53:05 EDT 2016


Hi Sean,

I'm still unable to reproduce this. What container do you use?

I use WildFly (with Undertow) with RESTEasy 3.0.17. I attach WildFly 
application (with end-point and exception mapper) and junit test with 
client part. I still see only ProcessingException:

 1. mvn package -DskipTests
 2. deploy
 3. mvn test

I see this exception:

javax.ws.rs.ProcessingException: java.lang.IllegalStateException: 
RESTEASY004575: Input stream was empty, there is no entity
     at 
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:285)
     at 
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readEntity(ClientResponse.java:181)
     at 
org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:219)
     at org.resteasy.test.MyTest.testBuildResponse(MyTest.java:29)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
     at 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
     at 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
     at 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
     at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
     at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
     at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
     at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
     at 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
     at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
     at 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at 
org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
     at 
org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
     at 
org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
     at 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
     at 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.lang.IllegalStateException: RESTEASY004575: Input stream 
was empty, there is no entity
     at 
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:239)
     ... 32 more

Marek

On 06/14/2016 09:08 PM, Sean Dawson wrote:
>
> Hi Marek, thanks for the response.
>
> So I think you're right - that in the simplest of testcases, buffering 
> of the (null) entity is NOT attempted.
>
> There are a few other differences that may factor in to this but once 
> I've modified the simple version to be slightly closer to our 
> environment, the difference on the client between this...
>
> Exception in thread "main" javax.ws.rs.RedirectionException: HTTP 304 
> Not Modified
>  at 
> org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:172)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:60)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:104)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
> Disconnected from the target VM, address: '127.0.0.1:64538 
> <http://127.0.0.1:64538>', transport: 'socket'
>  at com.sun.proxy.$Proxy18.download(Unknown Source)
>  at Client.main(Client.java:29)
> Process finished with exit code 1
>
> And this...
>
> Exception in thread "main" java.lang.NullPointerException
>  at 
> org.jboss.resteasy.util.ReadFromStream.readFromStream(ReadFromStream.java:30)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.ClientResponse.bufferEntity(ClientResponse.java:307)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:155)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:60)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:104)
>  at 
> org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
>  at com.sun.proxy.$Proxy18.download(Unknown Source)
>  at Client.main(Client.java:29)
> Process finished with exit code 1
>
> Is one line registering this exception mapper provider on the 
> server (ie. adding it for the second run)...
>
> @Provider public class MyExceptionMapperimplements ExceptionMapper<WebApplicationException>
> {
>      @Override public Response toResponse(WebApplicationException wae)
>      {
>          int status = wae.getResponse().getStatus();
>          Response.ResponseBuilder responseBuilder = Response.status(status);
>          return responseBuilder.entity(wae.toString()).build();
>      }
> }
> In both cases the status code is 304.  My actual exception mapper(s) 
> are more complicated than this - setting media types, etc - but in 
> this simple version, the above shows our issue.  What more/else should 
> I be doing instead?
>
>
>
> On Tue, Jun 14, 2016 at 4:44 AM, Marek Kopecky <mkopecky at redhat.com 
> <mailto:mkopecky at redhat.com>> wrote:
>
>     Hi.
>
>     The mailing-list on sourceforge
>     (resteasy-developers at lists.sourceforge.net
>     <mailto:resteasy-developers at lists.sourceforge.net>) has been
>     deprecated. Forwarding to correct mailing list (
>     resteasy-dev at lists.jboss.org <mailto:resteasy-dev at lists.jboss.org> ).
>
>     Yes, "A 304 response cannot contain a message-body", see
>     https://tools.ietf.org/html/rfc7232#section-4.1
>
>     Sean, can you sent example of your end-point and client part? I
>     tried to use this endpoint and client. It works as I expected. Any
>     NPE is thrown:
>
>     @GET @Path("nothing")
>     @Produces("application/octet-stream")
>     public InputStream nothing() {
>          if (true) {
>              throw new WebApplicationException(304);
>          }
>          return new ByteArrayInputStream("hello".getBytes());
>     }
>
>     -----------------------------------------------------------------------------------
>
>     Response response =client.target(generateURL("/nothing")).request().get();
>     int code = response.getStatus();
>     if (code ==200) {
>          InputStream is = response.readEntity(InputStream.class);
>          Assert.assertEquals("hello", TestUtil.readString(is));
>     }
>     if (code ==304) {
>          try {
>              response.readEntity(InputStream.class);
>              Assert.fail("ProcessingException was not thrown");
>          }catch (ProcessingException e) {
>              // expected exception }
>     }
>     response.close();
>
>     But I found some performance issue with 304. If I use this end-point:
>
>     @GET @Path("nothing")
>     public Response nothing()
>     {
>         return Response.status(304).entity("test").build();
>     }
>
>     In WildFly, body is erased in Undertow (AFAIK), but RESTEasy could
>     do this too. Check for 304 can be implemented here:
>     https://github.com/resteasy/Resteasy/blob/master/resteasy-jaxrs/src/main/java/org/jboss/resteasy/core/ServerResponseWriter.java#L50
>     Now, interceptors are applied to these kinds of responses. This is
>     not necessary and it may not be optimal for performance. Alessio,
>     Ron, WDYT? Marek -------- Forwarded Message --------
>     Subject: 	[Resteasy-developers] Proper handling of NotModified/304
>     Date: 	Fri, 10 Jun 2016 10:50:03 -0400
>     From: 	Sean Dawson <sean.dawson2014 at gmail.com>
>     <mailto:sean.dawson2014 at gmail.com>
>     To: 	resteasy-devel. <resteasy-developers at lists.sourceforge.net>
>     <mailto:resteasy-developers at lists.sourceforge.net>
>
>     I posted this on users but I'm thinking it's a RestEasy bug at
>     this point.
>     The code seems to buffer the entity and then throw a processing
>     exception if the status is bad.
>     In the case of 304, no body is provided (and this seems to be
>     correct according to the standard).  I have found no way server
>     side to return anything but null as the entity.  So attempting to
>     buffer it on a 304 just seems plain incorrect (and results in an NPE).
>     Am I missing something?
>     Setting the custom header on the response does work - but I'm not
>     sure that'll make it back to the client when it passes through
>     servers that usually strip those out.
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/resteasy-dev/attachments/20160620/1d776102/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: NotModified.zip
Type: application/zip
Size: 22183 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/resteasy-dev/attachments/20160620/1d776102/attachment-0001.zip 


More information about the resteasy-dev mailing list