Chillax
Chillax

Reputation: 4728

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

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?

Upvotes: 2

Views: 38118

Answers (10)

inigoD
inigoD

Reputation: 1741

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

https://bugs.java.com/bugdatabase/view_bug?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

Upvotes: 12

Matthew Payne
Matthew Payne

Reputation: 3056

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);
}

Upvotes: 2

Yatender Singh
Yatender Singh

Reputation: 3322

You have to create one filter for all types of requests

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.origins</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.methods</param-name>
        <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Upvotes: 1

Dhanraj Goud
Dhanraj Goud

Reputation: 13

i did come across the same issue with Java 1.7.it works in JDK1.8

Upvotes: 0

Al Rosine
Al Rosine

Reputation: 31

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.

Upvotes: 1

Kamal.J
Kamal.J

Reputation: 11

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.

Upvotes: 1

Azee
Azee

Reputation: 1829

I usually use DELETE like void:

@DELETE
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/")
public void deleteSomeBean(@QueryParam("id") String id) throws Exception

and in client:

webResource.path(SERVICE_PATH).queryParam("id", someBean.getId()).delete();gith

Like here: TemplateRestService

and here: TemplateServiceRestTest

Upvotes: 0

Micer
Micer

Reputation: 8979

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){...}

Upvotes: 4

basiljames
basiljames

Reputation: 4847

The return type of @DELETE method should be void. You cannot return any thing. On success the reponse status will be can be 200 or 204

Upvotes: 0

user647772
user647772

Reputation:

As the error says,

HTTP method DELETE doesn't support output

So you must change the signature of your method to

public Response deleteEmployee(...)

In the method don't return a String but for example

return Response.noContent().build();

Upvotes: 0

Related Questions