You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When making a http request with xml as a request body, The deserialized request body is null.
The project uses quarkus-rest-jaxb for xml support. The endpoint definition is similar to this:
When sending an xml body to the endpoint, the request body is deserialized and passed to the myEndpoint method.
Actual behavior
The request parameter of myEndpoint is null.
How to Reproduce?
Finding exact steps to reproduce the issue might prove difficult since a race condition is likely involved. The issue occurred when testing the application on a testing environment whereas everything worked as expected when running the application locally.
Output of uname -a or ver
No response
Output of java -version
Java 21
Quarkus version or git rev
3.13.1
Build tool (ie. output of mvnw --version or gradlew --version)
entityStream.available() is called to check whether the stream is empty. The documentation for this method states:
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking, which may be 0, or 0 when end of stream is detected.
This might lead to a stream wrongfully being classified as empty. No bytes being available to be read without blocking does not necessarily imply that there are no bytes to be read at all.
I have been able to test this theory by attaching a debugger to the application and creating a breakpoint on the return null; line. When I reevaluate isInputStreamEmpty(entityStream) once the
breakpoint has been reached the result is false. Moreover, entityStream.available() is now larger than 0.
This issue can likely be avoided by adjusting the isInputStreamEmpty method and no longer using entityStream.available() to check whether the stream is empty.
A possible workaround for this issue is to add a request filter like this to the project:
This request filter reads one byte from the stream and then resets the streams start. This ensures that there is always at least one byte available for reading in a non-blocking manner.
The text was updated successfully, but these errors were encountered:
To be honest, I have no idea why entityStream.available() == 0 was added (it wasn't done by me for sure). Moreover, we don't see to use that in any other MessageBodyReader.
I agree we should remove it.
I have created a PR such that the stream emptiness check is no longer relies on available(). As it turns out, the additional check entityStream.available() == 0 was not added without reason though. It seems like StreamUtil.isEmpty() is not able to reliably detect empty streams by itsself, for example when the request body is empty. This would then cause an exception during deserialization. My proposed solution is to instead read a byte from the stream and check whether its end has been read. This approach should be able to reliably categorize streams as empty / not empty.
Describe the bug
When making a http request with xml as a request body, The deserialized request body is null.
The project uses
quarkus-rest-jaxb
for xml support. The endpoint definition is similar to this:Expected behavior
When sending an xml body to the endpoint, the request body is deserialized and passed to the
myEndpoint
method.Actual behavior
The
request
parameter ofmyEndpoint
is null.How to Reproduce?
Finding exact steps to reproduce the issue might prove difficult since a race condition is likely involved. The issue occurred when testing the application on a testing environment whereas everything worked as expected when running the application locally.
Output of
uname -a
orver
No response
Output of
java -version
Java 21
Quarkus version or git rev
3.13.1
Build tool (ie. output of
mvnw --version
orgradlew --version
)No response
Additional information
I believe this issue is caused by the ServerJaxbMessageBodyReader class:
entityStream.available()
is called to check whether the stream is empty. The documentation for this method states:This might lead to a stream wrongfully being classified as empty. No bytes being available to be read without blocking does not necessarily imply that there are no bytes to be read at all.
I have been able to test this theory by attaching a debugger to the application and creating a breakpoint on the
return null;
line. When I reevaluateisInputStreamEmpty(entityStream)
once thebreakpoint has been reached the result is
false
. Moreover,entityStream.available()
is now larger than 0.This issue can likely be avoided by adjusting the
isInputStreamEmpty
method and no longer usingentityStream.available()
to check whether the stream is empty.A possible workaround for this issue is to add a request filter like this to the project:
This request filter reads one byte from the stream and then resets the streams start. This ensures that there is always at least one byte available for reading in a non-blocking manner.
The text was updated successfully, but these errors were encountered: