users@jersey.java.net

Re: [Jersey] jersey-multipart throwing NPE

From: Craig McClanahan <Craig.McClanahan_at_Sun.COM>
Date: Fri, 21 Nov 2008 00:50:39 -0800

Gili wrote:
> Craig McClanahan wrote:
>
>> For *all* HTTP headers, it is legal to have multiple values for the same
>> header, so a general purpose API has to support that option. For the
>> simple case where you know there is only one value (or for where you
>> don't care about anything other than the first value), try this:
>>
>> bodyPart.getParameterizedHeaders().getFirst("Content-Disposition").get("name");
>>
>>
>
> Yeah, I just remembered this when reading an older post you made about
> ParameterizedHeaders. <shudder> HTTP headers sure are complex.
>
I don't know if I would agree with that, but I'm biased ... I've been
working with this HTTP stuff for almost a decade now :-).
> Okay, so I'll get cracking using this new API but I would like to humbly
> suggest you need to explain a lot of these details in the Javadoc. It should
> be easier for end-users to pick up on these concepts without reading through
> the HTTP specification. I suspect that even developers who are quite
> familiar with HTTP will drop the ball on the HTTP header complexity.
>
>
I can definitely appreciate the desire for more context. However, you
also need to appreciate that the developers of *any* framework have to
make *some* assumptions about the knowledge of the users of those APIs,
lest you chase the experienced folks away by burying them in details
they learned years ago.

In the particular case at hand, I'm going to assume anyone coming to
jersey-multipart has at least a passing familiarity with the fact that
HTTP supports multiple values for the same header (consider headers like
"Accept" and "Accept-Language"). Many APIs try to prevent you from
dealing with things like that, thinking "nobody would *ever* care about
the second value for a particular header." I don't believe in that kind
of API design.
> I would suggest you write something along the following lines:
>
> [...]
> Here is a sample HTTP header:
> Content-Disposition: attachment; filename=bear.jpeg;
> inline; filename=panda.jpeg;
>
> The above header means: ("Content-Disposition=attachment" and
> "filename=bear.jpeg") or ("Content-Disposition=inline" or
> "filename="panda.jpeg")
>
To make that interpretation, I assume the character after "bear.jpeg"
should really be a comma (','), not a semicolon (';'), right? And in
your meaning definition, the "or" between "inline" and "panda.jpeg"
should really be an "and". Otherwise, you're not following the specs
for HTTP headers -- and nobody you are trying to communicate is going to
be able to understand you, no matter what API you are using :-).
> Here is some sample code for parsing the header:
> -
> bodyPart.getParameterizedHeaders().getFirst("Content-Disposition").getParameters().get("filename")
> returns "bear.jpeg"
> -
> bodyPart.getParameterizedHeaders().get("Content-Disposition").get(1).getParameters().get("filename")
> returns "panda.jpeg"
> [...]
>
> BTW: Please note how long this API is turning out to be.
Well, real life can actually be complicated sometimes :-).
> Instead of
> getFirst("Content-Disposition").getParameters().get("filename") why don't
> you remove getParameters() and place get() directly on the
> ParameterizedHeader?
>
>
To me that seems like it would be confusing. Are you getting the value
of the header, or the value of the parameter of the header? The current
APIs make that very explicit:

* getFirst("Content-Disposition").getValue() -- returns value
"attachment" in the example above.

* getFirst("Content-Disposition").getParameters().get("filename") --
returns value "bear.jpeg"
  in the example above.

where I would be confused by the following call:

* getFirst("Content-Disposition").get("filename") -- huh? I thought
getFirst() returned a header,
  not a Map ????? Now I have to go read the *!??!*!##!*!*!! javadocs to
see what it really does.
> Gili
>
Craig