newbie
newbie

Reputation: 468

Spring Boot, Thymeleaf Form Error

I am trying to create a task creation page. There is a form where the user can enter the name, description and task status and save it. However, when I go to the page it shows me this error

There was an unexpected error (type=Internal Server Error, status=500).
Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor' (index)

I also have a delete task in my program and that seems to work perfectly fine.

This is what my mainController looks like

  @RequestMapping(value = "/save-task")
    public String saveTask(@ModelAttribute("task") Task task, BindingResult bindingResult, Model model) {
        task.setDateCreated(new Date());
        taskService.save(task);
        model.addAttribute("tasks", taskService.findAll());
        model.addAttribute("task", new Task());
        model.addAttribute("mode", "MODE_TASKS");
        return "index";
    }

@RequestMapping( value = "/delete-task")
    public String deleteTask(@RequestParam (required = false) int id, Model model){
        taskService.delete(id);
        model.addAttribute("tasks", taskService.findAll());
        model.addAttribute("mode", "MODE_TASKS");
        return "index";
    }

Here is the form

<div class="container text-center">
        <h3>Manage Task</h3>
        <hr/>
        <form class="form-horizontal" method="POST" th:action="@{/save-task}" th:object="${task}">
            <input type="hidden" name="id" th:field="*{id}"/>
            <div class="form-group">
                <label class="control-label col-md-3">Name</label>
                <div class="col-md-7">
                    <input type="text" class="form-control" name="name"   th:field="*{name}"/>
                </div>
            </div>
            <div class="form-group">
                <label class="control-label col-md-3">Description</label>
                <div class="col-md-7">
                    <input type="text" class="form-control" name="description" th:field="*{description}"/>
                </div>
            </div>
            <div class="form-group">
                <label class="control-label col-md-3">Finished</label>
                <div class="col-md-7">
                    <input type="radio" class="col-sm-1" th:name="finished"  value="true"/>
                    <div class="col-sm-1">Yes</div>
                    <input type="radio" class="col-sm-1" th:name="finished"  value="false"/>
                    <div class="col-sm-1">No</div>
                </div>

                <div class="form-group">
                    <input type="submit" class="btn btn-primary" value="Save"/>
                </div>
            </div>
        </form>
    </div>
</div>

Delete Task html

<tr th:each="task: ${tasks}">
                    <td th:text="${task.id}"></td>
                    <td th:text="${task.name}"></td>
                    <td th:text="${task.description}"></td>
                    <td th:text="${task.dateCreated}"></td>
                    <td th:text="${task.finished}"></td>
                    <td><a th:href="@{'delete-task?id=' + ${task.id}}"><span class="glyphicon glyphicon-trash"></span></a> </td>
                </tr>

Here is a part of my Task entity

    @Entity
    @Table(name = "T_TASKS")
    public class Task implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "ID")
        private int id;
        @Column(name = "NAME")
        private String name;
        @Column(name = "DESCRIPTION")
            private String description;
        @Column(name = "DATE_CREATED")
        @Temporal(TemporalType.TIMESTAMP)
        private Date dateCreated;
        @Column(name = "FINISHED")
        private boolean finished;

Here is the error in the slack trace

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'task' available as request attribute

Upvotes: 0

Views: 2807

Answers (2)

Tamas G.
Tamas G.

Reputation: 737

Add the following to your controller class:

@ModelAttribute("task")
public Task newTaskObject() {
    return new Task();
}

It will solve the binding problem. Also you need a post controller to handle the form submission.

Upvotes: 0

riddle_me_this
riddle_me_this

Reputation: 9145

Change your controller mapping to accept GET and POST requests. You're getting the error because Spring can't bind a bean to the form. So add a bean when GET is called.

@GetMapping("/save-task")
public String addTask(Model model) {
   Task task = new Task();
   task.setDateCreated(new Date();
   model.addAttribute("task", task);
   return "save-task"; //or whatever the page is called
}

Then do your processing:

@PostMapping("/save-task")
public String saveTask(@ModelAttribute("task") Task task, 
                       BindingResult bindingResult, 
                       Model model) {
    taskService.save(task);
    model.addAttribute("mode", "MODE_TASKS");
    return "index";
}

Your bean looks fine. I don't see that you use tasks in your HTML snippet, but that would go in the method mapped with @GetMapping if you're looking to just display all tasks.

Upvotes: 1

Related Questions