1

I want to edit data from database via form "bookUpdate.html", that I can open from page "bookList.html" with the list of all rows from the table. I created a controller and form, that redirect me to the page with filled fields, that contain right data according the value "id", where object = "book". Button "Edit" redirect me to the page "/bookUpdate/1?", it is right. But when I try to confirm a new information via button on this page, this action redirect me to "bookUpdate.html" with an error 404, and new data were not saved in database. I can not find a mistake in this case.

bookUpdate.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="~{fragments/main_layout}">
<head>
<title>Book Form</title>
</head>
<body>
<div layout:fragment="content" class="container mySpace">

    <form th:action="@{/bookUpdate}" th:object="${book}" method="post">
        <div class="form-group">
            <label for="topic" class="form-control-label">Topic</label> <input
                type="text" class="form-control" th:value="${book.topic}"
                id="topic" />
        </div>

        <div class="form-group">
            <label for="description" class="form-control-label">Description</label>
            <textarea class="form-control" th:value="${book.description}"
                id="description" style="height: 95px"></textarea>
        </div>

        <div class="form-group">
            <label for="link" class="form-control-label">Link</label> <input
                type="text" class="form-control" th:value="${book.link}" id="link" />
        </div>

        <input type="submit" value="Submit" class="btn btn-primary" />
    </form>
</div>
</body>
</html>  

Contoller

@Controller
public class BookUpdateController {

@Autowired
private BookService service;

 @PostMapping("/bookUpdate/{id}")
public String editBook(@Valid BookDto book, @PathVariable (value = "id") Integer id, Model 
model) {
    Book oldBook = service.findById(id);
    oldBook.setDescription(book.getDescription());
    oldBook.setTopic(book.getTopic());
    oldBook.setLink(book.getLink());
    service.saveBook(oldBook);
    model.addAttribute("book", new BookDto());
    return "redirect:/bookList";
} 
}

@GetMapping("/bookUpdate/{id}")
public String bookListUpdate(@PathVariable (value = "id") Integer id, Model model) {
    model.addAttribute("book", service.findById(id));
    return "views/bookUpdate";
} 

bookList.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="~{fragments/main_layout}">
<head>
<title>Books</title>
</head>
<body>

<div layout:fragment="content" class="container mySpace">
    <form action="/bookList" class="form-inline">
        <div class="form-group mb-2" >
            <input type="text" class="form-control" name="name"
                placeholder="Search book" /> <input type="submit" value="Search"
                class="btn btn-primary" />
        </div>
    </form>
    <div class="card">
        <div class="card card-body">
            <ul th:each="books:${book}" style="list-style: none; padding-left: 10px;">
                <li><b>Topic:</b> <span th:text="${books.topic}"></span></li>
                <li><b>Description:</b><p th:text="${books.description}"></p></li>
                <li><b>Link:</b> <span th:text="${books.link}"></span></li>
                <br>
                 <form class="form-inline my-2 my-lg-0" 
th:action="@{'/bookUpdate/'+${books.id}}" th:object="${books}" method="get">
                    <input class="form-control mr-sm-2" type="hidden" />
                    <button class="btn btn-secondary my-2 my-sm-0" type="submit" 
>Edit</button>
                </form> 
                <hr>
            </ul>
        </div>
    </div>
</div>
</body>
</html>
Anastasia
  • 23
  • 5

1 Answers1

1

In your bookUpdate.html file, the action property is not set correctly. Your form after posting send information to @{/bookUpdate} but in related controller, defined PostMapping required @PostMapping("/bookUpdate/{id}") and they are mismach.

Change your form action property to :

<form th:action="@{'/bookUpdate/'+${book.id}}" th:object="${book}" method="post">
Mehdi Rahimi
  • 1,453
  • 5
  • 20
  • 31
  • 1
    Thank you, but unfortunately I got an error, and it does not work too org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/views/bookUpdate.html]") – Anastasia Jul 17 '22 at 17:29
  • 1
    @Anastasia Change the **action** section as: `th:action="@{/bookUpdate/__${books.id}__}"` – Mehdi Rahimi Jul 17 '22 at 17:33
  • I changed it, thanks. But unfortunately, I still got this error and "org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'id' cannot be found on null" – Anastasia Jul 17 '22 at 18:01
  • 1
    @Anastasia Ok, just pass another variable from controller to html page and change action section as: th:action="@{/bookUpdate/__${book_id}__}". you should pass book_id as a model attribute in the controller: `model.addAttribute("book_id", THE_BOOK_ID_TO_EDIT);` – Mehdi Rahimi Jul 17 '22 at 18:06
  • 2
    The reply by Mehdi is correct and just has a typo which you should be able to catch from the exception. `th:action="@{/bookUpdate/__${book.id}__}"` just need to remove the s from books – Ralan Jul 18 '22 at 08:24
  • 1
    @Ralan That's right, I've updated my answer. – Mehdi Rahimi Jul 18 '22 at 08:38