How to send enclose data in DELETE request in Jers

2019-04-21 16:00发布

I have the following server-side code in Jersey 2.x:

@Path("/store/remove/from/group")
@DELETE
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
public Response removeStoresFromGroup(@FormParam("storeName") List<String> storeNames, @FormParam("groupName") String groupName) {
    //......
}

On client side, I want to use Jersey 2.x client to send a delete request to the above web service. However, from the documentation of Jersey client API, I didn't find how to enclose the following data in DELETE request:

WebTarget webTarget = client.target("/store/remove/from/group");
MultivaluedMap<String, String> formData = new MultivaluedHashMap<String, String>();
List<String> storeName = new ArrayList<String>();
storeName.add("Store1");
storeName.add("Store2");
storeName.add("Store3");

formData.addAll("storeName", storeName);
formData.add("groupName", "Group A");

Response response = webTarget.request().accept(MediaType.TEXT_PLAIN).delete();   //The delete() method doesn't take any entity body in the request.

From the Jersey client API, the SyncInvoker class doesn't support a delete method with entity body as its argument. So I can only use either POST or PUT to send the data to the server like the following (but not for DELETE):

Response response = webTarget.request().accept(MediaType.TEXT_PLAIN).post(Entity.form(formData)); 

But I want to use DELETE request since the request is deleting some resources. How to send DELETE request with some entity data via Jersey client?

4条回答
Melony?
2楼-- · 2019-04-21 16:05

Just to note: if you use resteasy implementation of JAX RS Client API, you may use build().invoke():

client.target("$baseUrl$restEndPoint/$entityId")
                .request("application/json")
                .build("DELETE", Entity.entity(entity, MediaType.APPLICATION_JSON))
                .invoke()

But it does not work with jersey

查看更多
beautiful°
3楼-- · 2019-04-21 16:05

You can use webTarget.request().accept(MediaType.TEXT_PLAIN).method("DELETE",yourEntity) to invoke a DELETE with an entity in it.

查看更多
地球回转人心会变
4楼-- · 2019-04-21 16:11

A DELETE with an entity body is not strictly forbidden but it's very uncommon and ignored by some frameworks/servers. The need of an entity body may indicate that a DELETE is not used as it is intended.

For instance: If a GET /customers/4711 returns one customer and you send a DELETE /customers/4711 the next GET on this resource should return a 404. You deleted a resource identified by a URL like defined in the spec.

Your URL /store/remove/from/group does not seem to identify a resource. Using identifiers like /store/4711 or /groups/4711 and sending a DELETE on them would not fit your needs because you want to "remove a store from a group" not delete a store or a group.

Assuming you have a group resource

{
  "id" : 4711,
  "stores" : [123, 456, 789]
}

and you want a result like

{
  "id" : 4711,
  "stores" : [123, 789]
}

you are not deleting anything. You are modifying a resource so PUT, POST or PATCH are appropiate methods. JSON-Patch is a good format for describing such changes. A request would look like this:

PATCH /groups/4711 HTTP/1.1
Content-Type: application/json-patch

[
  {
    "op" : "remove"
    "path" : "stores/1"
  }
]
查看更多
何必那么认真
5楼-- · 2019-04-21 16:16

Based on the code in Jersey 2.18 version, The class JerseyInvocation use a predefined HashMap to validate HTTP method and its Entity as below:

map.put("DELETE", EntityPresence.MUST_BE_NULL);
map.put("GET", EntityPresence.MUST_BE_NULL);
...

That's why we got this error "Entity must be null for http method DELETE".

While, please note that it also provide a Jersey client configuration property ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION to determine whether to stop the rest execution or not, so here we can use this property to suppress validation in order to continue to send a DELETE request with Entity. e.g.

    ClientConfig config = new ClientConfig();
    config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
    Client client = ClientBuilder.newClient(config);
    ...
查看更多
登录 后发表回答