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(a)redhat.com
<mailto:mkopecky@redhat.com>> wrote:
Hi.
The mailing-list on sourceforge
(resteasy-developers(a)lists.sourceforge.net
<mailto:resteasy-developers@lists.sourceforge.net>) has been
deprecated. Forwarding to correct mailing list (
resteasy-dev(a)lists.jboss.org <mailto:resteasy-dev@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/...
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(a)gmail.com>
<mailto:sean.dawson2014@gmail.com>
To: resteasy-devel. <resteasy-developers(a)lists.sourceforge.net>
<mailto:resteasy-developers@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.