Error 405: Method not Allowed on DELETE and PUT

Viewed 4000

I followed this spring tutorial and everything worked fine. After this, I decided to add delete and modify funcionalities. I've implemented them, but when I try to use them, I got the following error:

{"status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/demo/delete"}

{"status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/demo/modify"}

The commands that I'm executing:

curl localhost:8080/demo/delete -d name=First

curl localhost:8080/demo/modify -d name=First -d email=abc@gmail.com

//if the name doesn't exist in both methods, it will return "Nonexistent user!"

Below are the following code of:

MainController.java

package com.example.accessingdatamysql;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller 
@RequestMapping(path="/demo") 
public class MainController {
    @Autowired 
    private UserRepository userRepository;

    @PostMapping(path="/add") 
    public @ResponseBody String addNewUser (@RequestParam String name, 
           @RequestParam String email) {

        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "Saved\n";
    }

    @GetMapping(path="/all")
    public @ResponseBody Iterable<User> getAllUsers() {
        return userRepository.findAll();
    }

    /* ----------------- NEW METHODS THAT I'VE CREATED ----------------- */

    @DeleteMapping(path="/delete")
    public String delete(@RequestParam String name) throws Exception {
        if(userRepository.findByName(name).equals(null)) {
            System.out.println("Nonexistent user!\n");
        }
        userRepository.deleteByName(name);
        return "User successfully deleted!\n";
    }

    @PutMapping(path="/modify")
    public String modify(@RequestParam String name, @RequestParam String email) throws Exception {
        if(userRepository.findByName(name).equals(null)) {
            System.out.println("Nonexistent user!\n");
        }

        userRepository.deleteByName(name);
        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "User successfully modified!\n";
    }
}

User.java

package com.example.accessingdatamysql;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    private String email;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

UserRepository.java

package com.example.accessingdatamysql;

import org.springframework.data.repository.CrudRepository;

import com.example.accessingdatamysql.User;

public interface UserRepository extends CrudRepository<User, Integer> {

    public User findByName(String name);
    public void deleteByName(String name);
}

I've no idea what's happening here. I've searched for other similar questions like that with the same error but none of them solved my problem.

3 Answers

You are executing the calls with the method POST rather than DELETE for /demo/delete and PUT for /demo/modify.

{"status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/demo/delete"}

{"status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/demo/modify"}

You are not showing how are you executing those failing calls, but for example, if you are using a GUI client such Postman to simulate the calls, check that you are selecting the proper HTTP method. And if you are using the curl library in the terminal pay attention to the method set:

curl -X "DELETE" http://your.url/demo/delete ...
curl -X "PUT" http://your.url/demo/modify ...

After following @Dez's answer, the problem was solved but I was getting other error:

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

I solved it by adding @Transactional on DELETE and PUT methods in MainController class:

@DeleteMapping(path="/delete")
@Transactional //added
public void delete(@RequestParam String name) throws Exception { (...) }

@PutMapping(path="/modify")
@Transactional //added
public void modify(@RequestParam String name, @RequestParam String email) throws Exception { (...) }

And modified the exception throwing condition, that was always returning false:

if(userRepository.findByName(name).equals(null)) {
     throw new Exception("Nonexistent user!");
}

to

if(userRepository.findByName(name) == null) {
     throw new Exception("Nonexistent user!");
}

This is how @DeleteMapping and @PutMapping work. These annotations are shortcuts to @RequestMapping with method attribute fixed to DELETE or PUT correspondingly. To allow multiple HTTP methods for an endpoint you should list them explicitly:

@RequestMapping(path = "/modify", method = { RequestMethod.DELETE, RequestMethod.POST })
public String modify(...){
   ...
}

Related