Hi,
I know it is valid HTTP, that is not in dispute :-) what we disagree
on is whether this is a common 80% case for HTTP *applications*.
If you get an InputStream from Servlet does it return null when no
content is present? What about a Reader? Thus in those cases it may
make sense not to return null to retain similar expectations (see
later for more on this).
With respect to high-level more application specific processing say
with XML and JAXB i think it depends on the application specific
aspects of what you are doing. I have written many examples with JAXB
and have as of yet not been required to explicitly support no content
in the request and am happy to let the runtime deal with returning of
a client error. WebDAV is the only use case that i currently know of
that supports no content or content. What you are asking me to do is
require that i do the checking myself as well as change my existing
applications to avoid NPEs when a client is in error.
This is why i prefer an annotated solution for what i consider the 20%
case, for example:
@Consumes("application/xml")
@POST
public void post(@NoContent JAXBBean bean) { ... }
and for the specific WebDAV we can tweak support for the JAXB
processing to support the semantics of common WebDAV usage. The
@NoContent annotation (for want of a better word) would result in the
return of specific stuff for no content dependent on the Java type and
message body reader, thus the semantics do not always have to be null
e.g there could be a default value for some Java types perhaps (e.g.
for WebDav it could be an empty PropPatch/Find JAXB bean, which means
the client does not have to deal with the null case, one less thing to
deal with).
The current situation does not crash anything on the server
application directly with an NPE. With lower-level types like
InputStream, Reader, byte[] and String it can still be determined if
there is no content, but! i think we should change that so by default
a 400 client error is returned for byte[], String, File etc (this
requires clarifications to the JAX-RS spec). When using JAXB the
current situation is a 400 Client Error is returned.
What i am proposing is a solution for what i consider that 20% case
where clients can PUT or POST no content or content and it is not a
client error to do so. The annotation documents this is the case for
both existing and new developers, additionally it means we can
potentially support additional information in the WADL and generated
HTML for developers writing clients.
In summary i am proposing the opposite of what you are proposing as
the default case :-) if you can convince me that your proposed default
case covers the 80% use-case bracket, namely content and no content
sent by the client is the common case, i will change my mind :-)
Paul.
On Dec 16, 2008, at 7:46 AM, Markus Karg wrote:
> Paul,
>
> I see it differently. I think that stability of the default solution
> must be the first target to match, and this includes the zero-body
> case, since it is valid HTTP and it is a thing that the Microsoft
> Redirectory does with EVERY single PUT (sending an empty PUT first).
> So it is not an edge case. I think it would be like programming a
> "for good whether only" software if JAX-RS imposes programmers
> targeting use of the Microsoft client to take extra care of empty
> bodies. Dealing with null pointers is a totally common thing in the
> Java area and I do not see why there should be any difference for
> this single injected argument, while all the rest of variables still
> can be null. I would agree with you if Java would have special
> language support for pointers that never can be null (like C++ has
> in a limited way). But it lacks this. And again, I am NOT talking
> about WebDAV so I have to disagree with a WebDAV special reader. It
> is VALID HTTP and has nothing to do with WebDAV. The case that
> Content-Type is provided but Content-Length is null imposes no
> specialities: Content-Type selects the method to call, and Content-
> Length imposes null to be used. It is plain old Java in my eyes that
> a parameter can be null and imposes no special complexity for the
> average programmer. Actually from my understanding of logic, it is
> the only valid solution to set the argument to null if Content-
> Length is zero and I was very surprised to get an empty String body
> when I changed the body type to String. No joke. Using blank Strings
> is completely strange!
>
> Let's face the consequences:
>
> My Solution: Straightforward Java solution, works in all cases as
> Java programmers are used to deal with NULLs.
>
> Your Solution: Imposes an add "Java doesn't know NULLs and Strings
> can be blank but never NULL" semantics which is not typical to Java,
> and will crash if the JAX-RS programmer forgets to add an additional
> (!) annotation, or will work with WebDAV solely while the problem is
> not related to WebDAV at all.
>
> At least from my view, I cannot see that the Pros of your idea would
> outwight the Cons of your proposal. But maybe I did not get the
> point why your proposal should be any better than mine.
>
> Regards
> Markus
>
> From: Paul.Sandoz_at_Sun.COM [mailto:Paul.Sandoz_at_Sun.COM]
> Sent: Montag, 15. Dezember 2008 12:47
> To: dev_at_jersey.dev.java.net
> Subject: Re: [Jersey] JAX-RS based WebDAV support
>
>
> On Dec 11, 2008, at 7:45 PM, Markus KARG wrote:
>
>
> Paul,
>
> since the HTTP specification does not enforce that any request must
> have a body with a size larger than zero bytes, JAX-RS should not
> enforce this. So if JAX-RS wants to provide a means for applications
> to deal with this issue, my proposal is that the default is to
> inject null. If there is an application that is unable to deal with
> that, it must check for null. This is straightforward interpretation
> of the HTTP specification. It is ok if you want to add an optional
> annotation that will prevent calling a method in case of a null
> body. But since that is the exception (from the HTTP specification
> view) the default must be to inject null.
>
>
> I think we agree we need to do something. But i disagree with the
> default solution because i think it is poor from an ease of use
> perspective. I expect the common case is that content is expected
> thus having the runtime deal with the case when no content occurs
> is very useful rather than having the developer deal with this case.
> What you are proposing is that the developer remember an edge case
> which if they forgot introduces a potential NPE in their application.
>
> Having thought about it a little more a null value may also be
> specific to the Java type and media type being processed so i am not
> sure we can assume that null is utilized when the Content-Type is
> present and the content length is 0 (where the length is derived
> from the Content-Length header or chunked encoding) for all cases.
>
> In this respect we could propose a solution where by the request
> entity is annotated and declares what should be done if the Content-
> Type is present and the content length is 0. Thus it requires
> explicit developer intervention for JAXB to deal with 0 content
> length. I realize this makes it a little harder for utilizing WebDAV
> support. So... another solution could be to provide message body
> readers for the WebDAV explicit JAXB types that support 0 content
> length. Such support can reuse the general JAXB readers. I think i
> might prefer the latter solution because we are associating specific
> semantics with the WebDAV content/media type and the Java type.
>
>
>
> For the Content-Type: It is valid to provide a content type even
> with a missing body. The HTTP specification does not say that
> Concent-Type may only be sent if Content-Length is larger than zero.
> So I do not see the problem. If a client does not send a Content-
> Type but sends an empty body it is obvious that the client does not
> care about any content type specific behaviour. But I do not see
> that this is related to the zero-bytes-content, since a client today
> could send a non-empty body with missing Content-Type and no mathing
> file extension, and then you also do not know which method to call.
> So this problem is not releated to the zero-bytes-problem. Your
> proposal of ConsumesNothing is great, but it is independent of the
> content-length. It solves a different problem.
>
>
> Agreed it is independent of the Content-Type being present with 0
> content length.
>
> Paul.
>
>
> Regards
> Markus
>
> From: Paul.Sandoz_at_Sun.COM [mailto:Paul.Sandoz_at_Sun.COM]
> Sent: Donnerstag, 11. Dezember 2008 10:32
> To: dev_at_jersey.dev.java.net
> Subject: Re: [Jersey] JAX-RS based WebDAV support
>
>
> On Dec 10, 2008, at 7:51 PM, Markus KARG wrote:
>
>
>
>
> Paul,
>
> I do not see that 400 would be a correct return code, since 400
> means "The request could not be understood by the server DUE TO
> MALFORMED SYNTAX.". The syntax was not malformed, it was pretty
> correct!
>
> It depends on what you want to do. The syntax of the request may
> well be malformed because a request entity is absent but a request
> entity is required. The malformed syntax applies to the whole
> request and not just to the syntax of request entity.
>
> As you point out it is correct for a WebDAV method (i presume it is
> allowed in the specification?) but for another application a HTTP
> method may require a request entity and in this case having the
> application have to check for null would be annoying when the
> framework could do that.
>
>
>
>
> So still I believe that nobody out there would say something against
> a single solution of injecting null.
>
> You mean a default solution or an optional solution?
>
>
>
>
> Maybe we should let people vote? ;-)
>
>
> :-) i think it requires more discussion/exploration of the best way
> to provide such a solution.
>
> Part of the difficultly i am having with arriving at a solution is a
> method such as:
>
> @POST
> @Consumes("application/xml")
> public void post(String xxx) {
> }
>
> states that it consumes something. Now if i have two method
> consuming something:
>
> @POST
> @Consumes("application/xml")
> public void post(String xxx) {
> }
>
> @POST
> @Consumes("application/json")
> public void post(String xxx) {
> }
>
> then if the Content-Type is absent then which method would get
> called? we need a way to state that one of these method may be
> called if the Content-Type is absent or another method that gets
> called when the Content-Type is absent, for example:
>
> @POST
> @ConsumesNothing
> public void post() {
> }
>
> And we need to define the case of what happens when the Content-Type
> is present but the content length is 0.
>
> In the WebDAV case is the Content-Type absent from the request?
>
> Paul.
>
>
>
> Regards
> Markus
>
>
>
> For the issue with the empty bodies: We need to find a solution
> since it's really a black spot on the overall great API. I think it
> would be not much a problem to convince everybody that it makes more
> sense to inject null instead of throwing a NullPointerException? :-)
>
> Yes, i can see it both ways. Sometimes you want a null value to be
> propagated and sometimes you do not and want a 400 response instead
> (the latter probably being the most common i suspect).
>
> One solution is to have a separate resource method for a request
> that does not contain a request entity. Another could be to
> annotation the request entity or the resource method that declares
> if there is not content-type then the entity should be assigned a
> null value. I think i prefer the latter solution.
>
> Paul.
>
>
>