Search code examples
javajsonjerseyput

How to send and receive a PUT request containing JSON with jersey?


Here is what I have for server:

@PUT
@Path("/put")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.TEXT_PLAIN })
public Response insertMessage(Message m) {
    return Response.ok(m.toString(), MediaType.TEXT_PLAIN).build();
}

for client:

ClientConfig config = new DefaultClientConfig();
config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(new Message("a", "b", "message"));
ClientResponse response = service.path("put").accept(MediaType.APPLICATION_JSON)
                .type(MediaType.APPLICATION_JSON)
               .put(ClientResponse.class, json);
System.out.println(response.getStatus() + " " + response.getEntity(String.class));

For Message:

public class Message {
    private String sender;
    private String receiver;
    private String content;
    @JsonCreator
    public Message() {}
    @JsonCreator
    public Message(@JsonProperty("sender") String sender,
            @JsonProperty("receiver")String receiver,
            @JsonProperty("content")String content) {
        this.sender = sender;
        this.receiver = receiver;
        this.content = content;
    }
}

And I kept getting HTTP 406. I have

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

in my web.xml.


Solution

  • You're getting a 406 error because your Jersey resource and your client request aren't matching up: Jersey is generating a text response but your client states it will only accept JSON. Here's what W3C says about a 406 error:

    The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.

    You'll need to either change your Jersey PUT method to produce JSON...

    ...
    @Produces({ MediaType.APPLICATION_JSON })
    public Response insertMessage(Message m) {
        return Response.ok(m.toString()).build();
    }
    

    Or use text/plain for your accept media type on the client request:

    service.accept(MediaType.TEXT_PLAIN);
    

    Looking over your edits, the original 415 error was caused by the missing service.type(MediaType.APPLICATION_JSON) from the client request. Again from W3C, a 415 error is:

    The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.

    Here's the W3C reference I'm using: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html