Home > Blockchain >  Request method 'POST' not supported, but the method for creating objects works
Request method 'POST' not supported, but the method for creating objects works

Time:11-02

I create a CRUD application using SpringBoot. I use PostgreSQL as a database. My application also uses SpringSecurity. The methods of displaying and creating objects work perfectly. But for some reason, updating and deleting the same objects gives an error:

2022-11-01 08:51:14.602 WARN 12149 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]

I think the problem is in the html code. I use Thymeleaf.

**My Student Controller: **

package ru.connor.FirstSecurityApp.controllers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import ru.connor.FirstSecurityApp.model.Student;
import ru.connor.FirstSecurityApp.services.StudentService;

import javax.validation.Valid;
import java.util.Optional;

@Controller
@RequestMapping("/students")
@RequiredArgsConstructor
public class StudentController {
    private final StudentService studentService;

    @GetMapping()
    public String showAllClasses(Model model) {
        model.addAttribute("students", studentService.showAllStudent());
        return "main/AllClasses";
    }


    @GetMapping("/{id}")
    public String showById(@PathVariable("id") int id, Model model){
        Optional<Student> student = Optional.ofNullable(studentService.showStudentById(id));
        if (student.isEmpty()){
            return "main/students/errorPage";
        }else model.addAttribute("student", student);
        return "main/students/index";
    }

    @GetMapping("/add")
    public String addStudent(@ModelAttribute("student") Student student) {
        return "main/students/new";
    }

    @PostMapping()
    public String create(@ModelAttribute("student") @Valid Student student,
                         BindingResult bindingResult) {
        if (bindingResult.hasErrors())
            return "main/students/new";

        studentService.addStudent(student);
        return "redirect:/students";
    }

    @GetMapping("/{id}/edit")
    public String edit(Model model, @PathVariable("id") int id) {
        model.addAttribute("student", studentService.showStudentById(id));
        return "main/students/edit";
    }

    @PatchMapping("/{id}")
    public String update(@ModelAttribute("student") @Valid Student student, BindingResult bindingResult, @PathVariable("id") int id) {
        if (bindingResult.hasErrors()){
            return "main/students/edit";}
        studentService.update(id, student);
        return "redirect:/students";
    }

    @DeleteMapping("/{id}")
    public String delete(@PathVariable("id") int id){
        Optional<Student> student = Optional.ofNullable(studentService.showStudentById(id));
        if (student.isPresent()){
            studentService.delete(id);
            return "redirect:/students";
        }
        return "main/students/index";
    }
}

Student Service:

package ru.connor.FirstSecurityApp.services;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.connor.FirstSecurityApp.model.Student;
import ru.connor.FirstSecurityApp.repository.StudentsRepository;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@SuppressWarnings("unused")
@Transactional(readOnly = true)
public class StudentService {
    private final StudentsRepository studentsRepository;

    public List<Student> showAllStudent(){
        return studentsRepository.findAll();
    }

    public Student showStudentById(int id){
        Optional<Student> foundPerson = studentsRepository.findById(id);

        return foundPerson.orElse(null);
    }

    @Transactional
    public void addStudent(Student student){
        studentsRepository.save(student);
    }

    @Transactional
    public void update(int id, Student person){
        person.setId(id);
        studentsRepository.save(person);
    }

    @Transactional
    public boolean delete(int id){
        if (studentsRepository.findById(id).isPresent()){
            studentsRepository.deleteById(id);
            return true;
        }
        return false;
    }


}

**HTML view where the delete form is specified: **

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Student</title>
</head>
<body>
<h1 th:text="${student.get().getFullStudentName()}"></h1>
<hr>
<form method="post" th:action="@{/students/{id}(id=${student.get().getId()})}">
    <input type="submit" value="Delete">
</form>
</body>
</html>

CodePudding user response:

As you have mentioned @PatchMapping for updates then you need the HTTP PATCH method instead of POST. The same goes for delete you have used @DeleteMapping, so you need to use the HTTP DELETE method instead of POST.

Create -> POST
Read   -> GET
Update -> PUT/PATCH
Delete -> DELETE

With form submit I don't think PATCH/PUT/DELETE will work so in that case you need to change @PatchMapping/@DeleteMapping to @PostMapping and update the URL so it will be unique for update/delete.

PUT/PATCH/DELETE will work with REST API only.

  • Related