Not able to invoke an @DELETE web service in REST/JERSEY

37,202

Solution 1

For me it helped to remove input parameter from delete() method on client

ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).delete(ClientResponse.class);

and send it over @pathParam instead:

public String delete(@PathParam("input") String input){...}

Solution 2

It's a java's bug in the implementation of the HTTPUrlConnection class:

http://bugs.sun.com/view_bug.do?bug_id=7157360

It should be solved in java 8.....

Meanwhile, in the real word, to send a json to a REST service you must send path parameter(s) like @Micer says or make your own HttpUrlConnection setting the requestmethod to POST and overriding it with the "X-HTTP_method-Override" to say that you want a DELETE doing something like this:

  public static void remove(String dflowname) throws IOException, ParseException {
    String jsonResponse = "";

    URL url = new URL(deleteuri);
    HttpURLConnection connection = null;
    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("POST");
    // We have to override the post method so we can send data
    connection.setRequestProperty("X-HTTP-Method-Override", "DELETE");
    connection.setDoOutput(true);

    // Send request
    OutputStreamWriter wr = new OutputStreamWriter(
      connection.getOutputStream());
    wr.write(dflowname);
    wr.flush();

    // Get Response
    BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String line;
    while ((line = rd.readLine()) != null) {
      jsonResponse = jsonResponse.concat(line);
    }
    wr.close();
    rd.close();

    JSONParser parser = new JSONParser();
    JSONObject obj = (JSONObject) parser.parse(jsonResponse);
    System.out.println(obj.get("status").toString());
  }

source: https://groups.google.com/a/openflowhub.org/forum/#!msg/floodlight-dev/imm_8drWOwU/Uu4h_u3H6HcJ

Solution 3

Delete with a payload works fine in Jersey clients 2.x.x.

Client code example below.

    public CalculateResult unoverrideSubscription(String partyId, String serviceCode) {


    CalculateResult svc = r.path("/party-subscriptions").path(partyId)
            .path(serviceCode)
            .path("price")
            .request(MediaType.APPLICATION_JSON).delete(CalculateResult.class);

    return svc;// toGenericResponse(sr);
}

Solution 4

This seem to be because of a bug (https://bugs.openjdk.java.net/browse/JDK-7157360) in Java 1.7 implementation of HttpURLConnection class. I tried using JDK1.8 and it worked like a charm.

Solution 5

Spent some time attempting to identify what will and won't currently work using WebLogic 12 & Sun / JRocket 1.6.

The error "ProtocolException: HTTP method DELETE doesn't support output" seems to be a bit misleading. This error is caused not by returning output from the RS but attempting to pass in an object to be processed on a delete request.

You can receive an object when passing in keys/identifiers via @QueryParams...

@DELETE
@Path("deleteThis")
public Response deleteThis(@QueryParam("objectId") String objectId)

using

    ClientResponse response = webResource.path("deleteThis").queryParam("objectId", "1").delete(ClientResponse.class);

or via @PathParams...

@DELETE
@Path("deleteThis/{objectId}")
public ReturnedObject deleteThis(@PathParam("objectId") int objectId)

using

    ReturnedObject myReturnedObject = webResource.path("deleteThis").path("1").delete(ReturnedObject.class);

This error is produced when you are passing in an object to be used as an argument

@DELETE
@Path("deleteThis")
public Response deleteRuleSettingTest(ArgumentObject myObject)

using

ArgumentObject myArgumentObject = ...
ClientResponse response = webResource.path("deleteThis").delete(ClientResponse.class, myArgumentObject);

Additionally. Reviewed the source code for the sun.net.www.protocol.http.HttpURLConnection class. This error is produced when the method is not PUT or POST but only when the protocol is 'http'. Enabled and pointed my client to a secure port on my container and the last example (the one that causes the exception) works successfully. Makes me wonder if this is actually a java bug as some have suggested.

Share:
37,202
Chillax
Author by

Chillax

Updated on June 24, 2020

Comments

  • Chillax
    Chillax almost 4 years

    I am using Jersey Framework (JAX-RS implementation) for building RESTful Web Services.

    I'm not able to use the @DELETE REST method, since its throwing an exception when I try to invoke it.The following @DELETE method is used to delete an Employee:

    @Path("/employees")
    public class EmpResource {
    
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
    public Response deleteEmployee(JAXBElement<String> r) throws ClassNotFoundException, SQLException {
    
        String name = r.getValue();
        String response = DAOaccess.deleteEmp(name);
        return Response.noContent().build();    
    

    }

    And I'm using the following block of code to invoke the service:

    Client client = Client.create();
    WebResource webResource = client.resource("http://localhost:8080/RestApp/sample/employees");
    String input = "{\"name\":\"John\"}";
    ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).delete(ClientResponse.class,input);
    

    When I run my client, it throws the following exception:

    Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: java.net.ProtocolException: HTTP method DELETE doesn't support output
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:151)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.delete(WebResource.java:599)
    

    It would be great if someone could guide me on how to resolve it?