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.