6

I send my request using jquery ajax with type "DELETE". At server side I have approprite handle method that looks like this:

   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public String delete(@RequestParam("hotel") String hotelCode, @PathVariable Long id, Model model){
        //delete operation
        return "redirect:/HotelTaxesAndCharges?hotel="+hotelCode;
    }

and method to which I want to redirect my call after delete looks like this

@RequestMapping(method = RequestMethod.GET)
public String getAll(@RequestParam("hotel") String hotelCode, Model model){
    //logic
    return 'getAll';
}

so when i call delete method during execution I'm getting error "you can redirect to JSP using only GET PUT or HEAD methods". I found solution using HiddenHttpMethodFilter, but result code looks little messy and I need to send request using POST and adding additional parameter (_method) to requst with custom request type.

So my question is there any other solution for DELETE/REDIRECT/GET transformation.

SORRY FOR BAD ENGLISH

UPDATE enter image description here

so you can that it redirects using delete too. And if I change everything from delete to post I get this:

enter image description here

Aliaksei Bulhak
  • 6,078
  • 8
  • 45
  • 75
  • Where do you get the error? How exactly does the error message look? – axtavt Jun 23 '14 at 13:04
  • @axtavt, I get error during redirect and error message now looks like this "Request method 'DELETE' not supported". And I don't know how convert request type from delete to redirect. – Aliaksei Bulhak Jun 23 '14 at 13:18
  • If I you POST type instead of DELETE everything works fine – Aliaksei Bulhak Jun 23 '14 at 13:18
  • Could you spy the dialog between your browser and you server (wireshark is good at that) ? I tried a redirect in following method of a stripped down controller `@RequestMapping(value="/delete", method=RequestMethod.DELETE) public String delete(HttpServletRequest req) { return "redirect:/welcome"; }`, called it with a `DELETE` method and ... got a correct redirect response. I think the problem is not in spring-mvc (using spring 3.2.4 and tomcat 7) – Serge Ballesta Jun 23 '14 at 15:38
  • @SergeBallesta, I add two screenshots. During first you can see error during redirect process because result method request type = GET. At the second screenshot you can see that if I change delete to Post everything goes well and result method is GET – Aliaksei Bulhak Jun 23 '14 at 18:26
  • If you are using a DELETE request redirecting doesn't make any sense. Read my answer here for more info http://stackoverflow.com/questions/15996779/cannot-handle-302-redirect-in-ajax-and-why/15996968#15996968. It's not entirely the same but the same principle applies. – Bart Jun 23 '14 at 20:09

1 Answers1

8

What happens is normal even if it is not what you need :

  • you submit a DELETE request from ajax
  • Spring controller receives it and answers a "redirect:/.../Hotel..."
  • Spring ViewResolver sends a redirect response with code 302 and correct Location header
  • browser uses precedent method and new location (normal for 302) issuing a DELETE (when you expected a get)
  • Spring DispatcherServlet receives a DELETE /.../Hotel... when @RequestMapping is for method=GET
  • Spring DispatcherServlet correctly states that no controller is defined and issues an error

All that is confirmed by your wireshark traces

It works when you send a POST request, because for compatibility with HTTP 1.0, all major browsers use a GET for a redirection following a POST like if status was 303

There is an immediate workaround : allow your method for the redirected URL to accept DELETE in addition to GET. Not very expensive, but not very nice.

You could also manage the redirection on client side : simply send a 200 code that will received by ajax, and let ajax do the redirection

The last solution consist in using a 303 code that explicitely ask browser to issue a GET independently of what was previous method. You can hardcode it by having your controller request take the HttpServletResponse as paremeter and return a null. You then manually add Location header and 303 status code.

But you can also configure the InternalResourceViewResolver to return 303 codes instead of 302 by setting its redirectHttp10Compatible attribute to false. You simple declare a bean in your servlet application context and Spring will use it. But you loose compatibility with older browsers that would not support HTTP 1.1 and 303 status code.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252