Liam C
Liam C

Reputation: 315

How to pass form data with JerseyClientBuilder using HTTP DELETE

I'm currently writing unit tests against a DropWizard based REST API application. Among the endpoints that I am testing are 2 methods for adding and removing properties of an object. A POST call creates a property, and a DELETE call can remove it. I'm able to submit a POST request with the form data identifying the property. I'm having trouble submitting a DELETE request with form data identifying the property. To submit a POST, I use:

Client client = new JerseyClientBuilder(RULE.getEnvironment())
                                        .build(String.format("test client %d", _id));
_id++;

return client.target("http://localhost:5000/Object/12345/Property")
                     .request(MediaType.APPLICATION_JSON_TYPE)
                     .post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE), Response.class);

This works as expected. However, the DELETE related methods of the JerseyInvocation.Builder object seem to lack a way to pass the Entity object defining form parameters. If I try and use the lower level .method() function:

Client client = new JerseyClientBuilder(RULE.getEnvironment()).build(String.format("test client %d", _id));
_id++;

return client.target("http://localhost:5000/Object/12345/Property")
                     .request(MediaType.APPLICATION_JSON_TYPE)
                     .method("DELETE", 
                             Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE), 
                             Response.class);

I receive this thoroughly unhelpful exception:

java.lang.IllegalStateException: Entity must be null for http method DELETE.

My understanding of the HTTP specs (and stackoverflow's consensus: Is an entity body allowed for an HTTP DELETE request?) indicates that message bodies with DELETE are well within the standard, although some implementations arbitrarily decide to impede this. It appears that Jersey is one of those limited implementations. What would be the ideal minimal effort workaround for this problem? (Assume the DropWizard app is immutable, answers of "Just rewrite the REST API to not use DELETE or to use a different REST URI schema" are not helpful) I need to test against the existing implementation, NOT write a new implementation.

Upvotes: 2

Views: 2716

Answers (1)

Gokul
Gokul

Reputation: 941

From Jersey 2.18 version,The class JerseyInvocation use a HashMap to validate HTTP method and its Entity as below:

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

This is the reason why you getting error "Entity must be null for http method DELETE".

Note: You will have to tell jersey to stop the rest execution or not.Please provide a Jersey client configuration property ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION and add below given code to suppress validation in order to continue to send a DELETE request with Entity.

ClientConfig clientConfig = new ClientConfig();
clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Client client = ClientBuilder.newClient(clientConfig);

Upvotes: 6

Related Questions