Abhijit Patil
Abhijit Patil

Reputation: 146

Jersey HTTP Delete,Put Response Status: 405 (Method Not Allowed)

Day 1: Added below rest endpoint for delete operation.

@Path("/company/v1/department")
@Component
public class ManageResource {

@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
                   @PathParam("identifier_value") final String identifierValue,
                   @QueryParam("age") final String age) {

 //delete operation
}
}

I was able to invoke DELETE endpoint using postman with below request:

DELETE: http://localhost:8080/company/v1/department/name/baner/employee?age=50

Day 2: Added below rest endpoint for the update operation in the same resource.

@Path("/company/v1/department")
@Component
public class ManageResource {

@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
                   @PathParam("identifier_value") final String identifierValue,
                   @QueryParam("age") final String age) {
   
//delete operation
}

@PUT
@Path("/empid/{value}/employee")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("value") final String identifierValue,
                   @RequestBody final EmployeeUpdateRequest request) {
   
//update operation
}
}

After adding this new endpoint, I am able to invoke PUT using postman with below request:

PUT: http://localhost:8080/company/v1/department/empid/epid-123/employee
{
//Json request body
}

But when I try to invoke Delete endpoint it is giving me 405 (Method Not Allowed) error. If I comment my new Put method, then the Delete method works fine. Also, if I replace Path for Put method to "/{identifier}/{identifier_value}/employee" then both Delete and Put method works fine.

I am using Jersey 1.19 with tomcat. Can someone help me with this?

Upvotes: 0

Views: 377

Answers (1)

Isidius
Isidius

Reputation: 21

Your Paths are in conflict with each other. Let me try to explain:

DELETE = /{identifier}/{identifier_value}/employee 
PUT = /empid/{value}/employee

That means when we evaluate the path from left to right, we can either have {identifier} which is anything or "empid" which is a fixed string

Jersey always tries to find the "most perfect" match for a REST endpoint. It does so by evaluating the path from left to right. Fixed strings always take precedence before random variables!

Basically that means when you want to call a DELETE, you cannot have the value "empid" for the variable "{identifier}" because then you are already out-of-scope

So the DELETE call to

http://localhost:8080/company/v1/department/empid/empid-123/employee

will not work as Jersey had to make a decision whether "empid" in the request matches "{identifier}" (DELETE) or "empid" (PUT). And as i tried to explain above, fixed strings take a higher priority. In contrast, any other DELETE request where

http://localhost:8080/company/v1/department/{identifier}/empid-123/employee

and

{identifier} != "empid"

works.

Possible solution:

make your rest endpoints resource-oriented

DELETE: /employee/{employee-id}

PUT: /employee/{employee-id}

Notice how the endpoints are identical, since other than the ID in most systems, no information is needed to identify an entity.

Upvotes: 1

Related Questions