<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p>Hi Sean,</p>
<p>I'm still unable to reproduce this. What container do you use?</p>
<p>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:</p>
<ol>
<li>mvn package -DskipTests</li>
<li>deploy</li>
<li>mvn test</li>
</ol>
<p>I see this exception<font face="Courier New, Courier, monospace">:</font><br>
</p>
<p><font face="Courier New, Courier, monospace" size="-1">javax.ws.rs.ProcessingException:
java.lang.IllegalStateException: RESTEASY004575: Input stream
was empty, there is no entity<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:285)<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readEntity(ClientResponse.java:181)<br>
at
org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:219)<br>
at
org.resteasy.test.MyTest.testBuildResponse(MyTest.java:29)<br>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)<br>
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br>
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)<br>
at java.lang.reflect.Method.invoke(Method.java:498)<br>
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)<br>
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)<br>
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)<br>
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)<br>
at
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)<br>
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)<br>
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)<br>
at
org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)<br>
at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)<br>
at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)<br>
at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)<br>
at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)<br>
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)<br>
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)<br>
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)<br>
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)<br>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)<br>
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br>
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)<br>
at java.lang.reflect.Method.invoke(Method.java:498)<br>
at
org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)<br>
at
org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)<br>
at
org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)<br>
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)<br>
at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)<br>
Caused by: java.lang.IllegalStateException: RESTEASY004575:
Input stream was empty, there is no entity<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.readFrom(ClientResponse.java:239)<br>
... 32 more</font><br>
<br>
</p>
<p>Marek<br>
</p>
<div class="moz-cite-prefix">On 06/14/2016 09:08 PM, Sean Dawson
wrote:<br>
</div>
<blockquote
cite="mid:CAMzkG1J4P8y2hQtCO6KbDkOwmTf5G_aEO6VHLcnJOVXLXA6BZQ@mail.gmail.com"
type="cite">
<div dir="ltr">
<div><br>
</div>
<div>Hi Marek, thanks for the response.</div>
<div><br>
</div>
<div>So I think you're right - that in the simplest of
testcases, buffering of the (null) entity is NOT attempted.</div>
<div><br>
</div>
<div>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...</div>
<div><br>
</div>
<div>Exception in thread "main"
javax.ws.rs.RedirectionException: HTTP 304 Not Modified<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:172)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:60)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:104)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)<br>
Disconnected from the target VM, address: '<a
moz-do-not-send="true" href="http://127.0.0.1:64538">127.0.0.1:64538</a>',
transport: 'socket'<br>
at com.sun.proxy.$Proxy18.download(Unknown Source)<br>
at Client.main(Client.java:29)</div>
<div>Process finished with exit code 1</div>
<div><br>
</div>
<div>And this...</div>
<div><br>
</div>
<div>Exception in thread "main" java.lang.NullPointerException<br>
at
org.jboss.resteasy.util.ReadFromStream.readFromStream(ReadFromStream.java:30)<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientResponse.bufferEntity(ClientResponse.java:307)<br>
at
org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:155)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:60)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:104)<br>
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)<br>
at com.sun.proxy.$Proxy18.download(Unknown Source)<br>
at Client.main(Client.java:29)</div>
<div>Process finished with exit code 1<br>
</div>
<div><br>
</div>
<div>Is one line registering this exception mapper provider on
the server (ie. adding it for the second run)...</div>
<div><br>
</div>
<div>
<pre style="color:rgb(0,0,0);font-family:"Courier New";font-size:9pt;background-color:rgb(255,255,255)"><span style="color:rgb(128,128,0)">@Provider
</span><span style="color:rgb(0,0,128);font-weight:bold">public class </span>MyExceptionMapper <span style="color:rgb(0,0,128);font-weight:bold">implements </span>ExceptionMapper<WebApplicationException>
{
<span style="color:rgb(128,128,0)">@Override
</span><span style="color:rgb(128,128,0)"> </span><span style="color:rgb(0,0,128);font-weight:bold">public </span>Response toResponse(WebApplicationException wae)
{
<span style="color:rgb(0,0,128);font-weight:bold">int </span>status = wae.getResponse().getStatus();
Response.ResponseBuilder responseBuilder = Response.<span style="font-style:italic">status</span>(status);
<span style="color:rgb(0,0,128);font-weight:bold">return </span>responseBuilder.entity(wae.toString()).build();
}
}
</pre>
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?<br>
</div>
<div><br>
</div>
<div><br>
</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Tue, Jun 14, 2016 at 4:44 AM, Marek
Kopecky <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:mkopecky@redhat.com" target="_blank">mkopecky@redhat.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div text="#000000" bgcolor="#FFFFFF">
<p>Hi.<br>
</p>
<p>The mailing-list on sourceforge (<a
moz-do-not-send="true"
href="mailto:resteasy-developers@lists.sourceforge.net"
target="_blank"><a class="moz-txt-link-abbreviated" href="mailto:resteasy-developers@lists.sourceforge.net">resteasy-developers@lists.sourceforge.net</a></a>)
has been deprecated. Forwarding to correct mailing list
( <a moz-do-not-send="true"
href="mailto:resteasy-dev@lists.jboss.org"
target="_blank">resteasy-dev@lists.jboss.org</a> ).<br>
</p>
<p>Yes, "A 304 response cannot contain a message-body",
see <a moz-do-not-send="true"
href="https://tools.ietf.org/html/rfc7232#section-4.1"
target="_blank">https://tools.ietf.org/html/rfc7232#section-4.1</a><br>
</p>
<div>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:<br>
<br>
<pre style="color:rgb(0,0,0);font-family:"Source Code Pro";font-size:10.5pt;background-color:rgb(255,255,255)"><span style="color:rgb(128,128,0)">@GET
</span><span style="color:rgb(128,128,0)">@Path</span>(<span style="color:rgb(0,128,0);font-weight:bold">"nothing"</span>)
<span style="color:rgb(128,128,0)">@Produces</span>(<span style="color:rgb(0,128,0);font-weight:bold">"application/octet-stream"</span>)
<span style="color:rgb(0,0,128);font-weight:bold">public </span>InputStream nothing() {
<span style="color:rgb(0,0,128);font-weight:bold">if </span>(<span style="color:rgb(0,0,128);font-weight:bold">true</span>) {
<span style="color:rgb(0,0,128);font-weight:bold">throw new </span>WebApplicationException(<span style="color:rgb(0,0,255)">304</span>);
}
<span style="color:rgb(0,0,128);font-weight:bold">return new </span>ByteArrayInputStream(<span style="color:rgb(0,128,0);font-weight:bold">"hello"</span>.getBytes());
}
-----------------------------------------------------------------------------------
Response response = <span style="color:rgb(102,14,122);font-style:italic">client</span>.target(generateURL(<span style="color:rgb(0,128,0);font-weight:bold">"/nothing"</span>)).request().get();
<span style="color:rgb(0,0,128);font-weight:bold">int </span>code = response.getStatus();
<span style="color:rgb(0,0,128);font-weight:bold">if </span>(code == <span style="color:rgb(0,0,255)">200</span>) {
InputStream is = response.readEntity(InputStream.<span style="color:rgb(0,0,128);font-weight:bold">class</span>);
Assert.<span style="font-style:italic">assertEquals</span>(<span style="color:rgb(0,128,0);font-weight:bold">"hello"</span>, TestUtil.<span style="font-style:italic">readString</span>(is));
}
<span style="color:rgb(0,0,128);font-weight:bold">if </span>(code == <span style="color:rgb(0,0,255)">304</span>) {
<span style="color:rgb(0,0,128);font-weight:bold">try </span>{
response.readEntity(InputStream.<span style="color:rgb(0,0,128);font-weight:bold">class</span>);
Assert.<span style="font-style:italic">fail</span>(<span style="color:rgb(0,128,0);font-weight:bold">"ProcessingException was not thrown"</span>);
} <span style="color:rgb(0,0,128);font-weight:bold">catch </span>(ProcessingException e) {
<span style="color:rgb(128,128,128);font-style:italic">// expected exception
</span><span style="color:rgb(128,128,128);font-style:italic"> </span>}
}
response.close();</pre>
But I found some performance issue with 304. If I use
this end-point:
<pre style="color:rgb(0,0,0);font-family:"Source Code Pro";font-size:10.5pt;background-color:rgb(255,255,255)"><span style="color:rgb(128,128,0)">@GET
</span><span style="color:rgb(128,128,0)">@Path</span>(<span style="color:rgb(0,128,0);font-weight:bold">"nothing"</span>)
<span style="color:rgb(0,0,128);font-weight:bold">public </span>Response nothing()
{
<span style="color:rgb(0,0,128);font-weight:bold">return </span>Response.<span style="font-style:italic">status</span>(<span style="color:rgb(0,0,255)">304</span>).entity(<span style="color:rgb(0,128,0);font-weight:bold">"test"</span>).build();
}</pre>
In WildFly, body is erased in Undertow (AFAIK), but
RESTEasy could do this too. Check for 304 can be
implemented here:
<a moz-do-not-send="true"
href="https://github.com/resteasy/Resteasy/blob/master/resteasy-jaxrs/src/main/java/org/jboss/resteasy/core/ServerResponseWriter.java#L50"
target="_blank">https://github.com/resteasy/Resteasy/blob/master/resteasy-jaxrs/src/main/java/org/jboss/resteasy/core/ServerResponseWriter.java#L50</a>
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 --------
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<th align="RIGHT" nowrap="nowrap"
valign="BASELINE">Subject: </th>
<td>[Resteasy-developers] Proper handling of
NotModified/304</td>
</tr>
<tr>
<th align="RIGHT" nowrap="nowrap"
valign="BASELINE">Date: </th>
<td>Fri, 10 Jun 2016 10:50:03 -0400</td>
</tr>
<tr>
<th align="RIGHT" nowrap="nowrap"
valign="BASELINE">From: </th>
<td>Sean Dawson <a moz-do-not-send="true"
href="mailto:sean.dawson2014@gmail.com"
target="_blank"><sean.dawson2014@gmail.com></a></td>
</tr>
<tr>
<th align="RIGHT" nowrap="nowrap"
valign="BASELINE">To: </th>
<td>resteasy-devel. <a moz-do-not-send="true"
href="mailto:resteasy-developers@lists.sourceforge.net"
target="_blank"><resteasy-developers@lists.sourceforge.net></a></td>
</tr>
</tbody>
</table>
<div>
<div class="h5">
<div dir="ltr">
<div> </div>
<div>I posted this on users but I'm thinking it's
a RestEasy bug at this point.</div>
<div> </div>
<div>The code seems to buffer the entity and then
throw a processing exception if the status is
bad.</div>
<div> </div>
<div>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).</div>
<div> </div>
<div>Am I missing something?</div>
<div> </div>
<div>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.</div>
<div> </div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</blockquote>
<br>
</body>
</html>