users@jersey.java.net

[Jersey] Re: Jersey2: Impossible to POST with empty entity?

From: cowwoc <cowwoc_at_bbs.darktech.org>
Date: Fri, 08 Nov 2013 11:25:42 -0500

According to http://stackoverflow.com/a/14879077/14731 this wouldn't
work, because @Consumes only matches if the client specifies a
Content-Type. According to the post, the fallback to
"application/octet-stream" only kicks in if there are no other methods
annotated with @Consumes. Meaning, the first @Consumes always wins if
Content-Type is missing.

Can you alter this behavior in JAX-RS given what the author has posted
in the Stackoverflow post about the HTTP specification?

Gili

On 08/11/2013 6:52 AM, Marek Potociar wrote:
> You should simply create a method that consumes
> "application/octet-stream", inject HttpHeaders into one of the method
> parameters and check if "Content-Type" headers is present. If it is
> not, you are sure the request did not contain any "Content-type"
> headers. All requests without any "Content-type" header should get
> automatically routed by JAX-RS runtime to such method.
>
> Would that work?
>
> Marek
>
> On 07 Nov 2013, at 18:36, cowwoc <cowwoc_at_bbs.darktech.org
> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>
>> Marek,
>>
>> Below, you proposed I migrate from
>>
>> @POST @Consumes("terminal") /companies/5
>>
>> to
>>
>> @POST /companies/5/terminals
>>
>> I just discovered a problem with this approach.
>>
>> According to http://stackoverflow.com/a/14879077/14731 if version
>> 1 of my API doesn't require a Content-Type (since the request body is
>> empty) but version 2 adds a Content-Type and request body, then I
>> have no way of controlling which method version 1 get routed to.
>> There is no way to specify @Consumes for the case with no Content-Type.
>>
>> Either @Consumes needs to support matching a non-existent
>> Content-Type, or I am forced to specify a Content-Type for an empty
>> body. In the latter case, you need to modify the Client API to let me
>> pass a Content-Type for requests without a body.
>>
>> Gili
>>
>> On 07/11/2013 11:46 AM, cowwoc wrote:
>>> On 07/11/2013 11:16 AM, Marek Potociar wrote:
>>>>
>>>> On 07 Nov 2013, at 16:41, cowwoc <cowwoc_at_bbs.darktech.org
>>>> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>>>>
>>>>> Hi Marek,
>>>>>
>>>>> Are you proposing adding the necessary API methods but throwing
>>>>> RuntimeExceptions unless some flag is set? I would support this
>>>>> approach, although in practice I don't think you'll need such a
>>>>> flag because we're talking about legal requests. Whether a request
>>>>> is "legal but non-sense" is a subjective matter.
>>>>
>>>> What I'm thinking is to make a flag (which could be by default
>>>> enabled in the Jersey test client and) that would make sure Jersey
>>>> is not trying to remove any headers. (Even though in this case I
>>>> think we have a different problem - look at the post(...) method
>>>> javadoc and the sentece about overwriting Content-* headers; there
>>>> is also a related bug filed on that already, IIRC).
>>>
>>> I see the problem (Content-* headers) but perhaps we can exploit a
>>> hole in the specification. If the entity does not provide a
>>> Content-Type then there is nothing to set, hence no overwriting
>>> takes place.
>>>
>>> PS: I couldn't find the relevant bug report. Where is it?
>>>
>>>>
>>>>> To prove my point, I'll provide you with specific examples for the
>>>>> use-cases I was inquiring about:
>>>>>
>>>>> * POST with a Content-Type but no body
>>>>> o When a parent resource may be used to create different
>>>>> kinds of child resources, the Content-Type is used to
>>>>> specify which kind of resource to create.
>>>>>
>>>> That is not very RESTful. Representation should not drive the
>>>> resource "type".
>>>
>>> Where does it say that?
>>>
>>>>> o
>>>>>
>>>>>
>>>>> o Example
>>>>> + Create a new "terminal" by invoking POST /companies/5
>>>>> with Content-Type: application/vnd.company.terminal
>>>>> + Create a new "expense report" by invoking POST
>>>>> /companies/5 with Content-Type:
>>>>> application/vnd.company.expense-report
>>>>>
>>>> Yuck! I certainly would not want to support the above, or make it
>>>> any easier to support that. If you want to create new resources
>>>> like this, you should better design a separate "collection" URIs
>>>> for that - /companies/5/teminals , /companies/5/expense-reports
>>>
>>> I think I can make this change, but I don't think it's right for
>>> Jersey to be opinionated. The REST community has many different
>>> opinions on the "right way" of doing things. If we're going to start
>>> eliminating functionality based on individual opinions we're going
>>> to anger a lot of users.
>>>
>>>>> * POST without either a Content-Type or body
>>>>> o Used to insert a new element into a collection (there is
>>>>> no confusion about the kind of child resource being created).
>>>>> o Example: Create a new "transaction" by invoking POST
>>>>> /transactions: http://stackoverflow.com/a/147299/14731
>>>>>
>>>> This is doable, right?
>>>
>>> I'm not sure. Are you expecting me to pass null into entity or
>>> MediaType in this method?
>>> https://jersey.java.net/apidocs/snapshot/jersey/javax/ws/rs/client/Entity.html#entity(T,
>>> javax.ws.rs.core.MediaType)
>>> <https://jersey.java.net/apidocs/snapshot/jersey/javax/ws/rs/client/Entity.html#entity%28T,%20javax.ws.rs.core.MediaType%29>
>>> If so, the Javadoc should really mention that passing null is an
>>> acceptable way to omit the field.
>>>
>>> Thanks,
>>> Gili
>>
>