Issue with kendo datepicker in Spring MVC - spring

I have a form for adding students. For the date of birth i want to use kendo ui datepicker, but i don't know how the controller is making the binding with the model. If the name attribute of the date picker matches the class element, then i get the following error: The request sent by the client was syntactically incorrect. If the name attribute of the date picker is different, then on save button clicked the student is inserted into the database, but with the field date of birth being null.
Below is the content of the jsp file, the controller and the Student class.
What i am doing wrong?
jsp file
<div id="addStudent" class="space">
<div class="page-title">Add student</div>
<form:form commandName="addForm" method="post">
<div class="editor-field">
<label for="firstName">First name</label> <input
class="input k-popup k-list-container k-group k-reset" type="text"
name="firstName" />
</div>
<div class="editor-field">
<label for="lastName">Last name</label> <input
class="input k-popup k-list-container k-group k-reset" type="text"
name="lastName" />
</div>
<div class="editor-field">
<label for="dateOfBirth">Date of birth</label>
<kendo:datePicker name="dateOfBirth"></kendo:datePicker> //name attribute
</div>
<div class="editor-field left form-actions">
<a href="http://localhost:8080/GasfProject/gasf/main/menu/students"
class="k-button">Cancel</a>
<input class="k-button" type="submit" name="add" value="Save">
</div>
</form:form>
</div>
Controller
#RequestMapping(value = "/menu/addStudent", method = RequestMethod.POST)
public String addStudent(#ModelAttribute("addForm") Student model) {
logger.debug("Received request in add student post");
// insert in database
StudentDatabaseAccess.addNewStudent(model);
return "redirect:students";
}
Student
public class Student {
private String firstName;
private String lastName;
private Date dateOfBirth;
//getters and setters
}

You can try adding a DateTimeFormat annotation on the dateOfBirth field
public class Student {
private String firstName;
private String lastName;
#DateTimeFormat(pattern = "yyyy/MM/dd")
private Date dateOfBirth;
//getters and setters
}
This will tell spring how to convert the data from Date to String and from String to Date.
Make sure the pattern you set in the annotation is the same as the one you probably set on the kendo datepicker field in javascript.

Related

How to iterate and save 2 objects with thymeleaf?

I dont know how fix this error, i saw some articles about that but nothing works.
Error
Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errorsField error in object 'pupil' on field 'curse': rejected value [ModelCurse(id=2, name=PHP, division=2da, pupilList=[], teacherList=[])];
[Failed to convert property value of type 'java.lang.String' to required type 'com.example.administrator.administrator.model.ModelCurse' for property 'curse';
HTML
<form th:action="#{/pupilController/add}" th:object="${pupil}" method="post">
<div class="form-row">
<div class="form-group col-md-6">
<label>Name</label>
<input type="text" class="form-control" th:field="*{name}" placeholder="Name">
</div>
<div class="form-group col-md-6">
<label>Last Name</label>
<input type="text" class="form-control" th:field="*{lastName}" placeholder="Last Name">
</div>
<div class="form-group col-md-6">
<label>Age</label>
<input type="number" class="form-control" th:field="*{age}" placeholder="Age">
</div>
<div class="form-group col-md-6">
<label>Phone Number</label>
<input type="text" class="form-control" th:field="*{phoneNumber}" placeholder="Phone Number">
</div>
<div class="form-group col-md-6">
<select th:field="*{curse}" class="form-control">
<option th:each="curso : ${curses}"
th:value="${curso}"
th:text="${curso.name}"></option>
</select>
</div>
</div>
<input type="submit" name="btnInsert" class="btn btn-primary" value=AƱadir>
</form>
Controller
#GetMapping("/addPupil")
public ModelAndView login(Model model){
ModelAndView mav = new ModelAndView("addpupil");
List<ModelCurse> modelCurses = curseService.getAllCurses();
mav.addObject("pupil",new ModelPupil());
mav.addObject("curses",modelCurses);
return mav;
}
#PostMapping("/add")
public RedirectView addPupil(#ModelAttribute("pupil")ModelPupil modelPupil){
pupilService.addPupil(modelPupil);
return new RedirectView("/pupilController/pupilList");
}
DTO
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class ModelCurse {
private long id;
private String name;
private String division;
private List<ModelPupil> pupilList;
private List<ModelTeacher> teacherList;
}
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class ModelPupil {
private long id;
private String name;
private String lastName;
private int age;
private int phoneNumber;
private ModelCurse curse;
}
When we submit the form, the value of selected option is sent as Text or String in HTTP POST. So, if you are expecting that Spring would automatically convert that String value of curse to object of type ModelCurse, then your assumption is wrong. But Spring does provide us a way to do it using Java beans PropertyEditorSupport. Here you can extend this class, and provide your own implementation on how to convert that String to the required object.

Why Date field is not going to my Database column in spring boot?

I am trying to store name, a start date and end date in my database. But when I submit the form the database is only taking the name but no Date is showing on the database. It is showing null.
Model class:
private String name;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd/MM/YYYY")
private Date startdate;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd/MM/YYYY")
private Date targetdate;
Html form
<form th:action="#{/saveTodo}" th:object="${todo}" method="POST">
<input type="text" th:field="*{name}" placeholder="Todo" class="form-control mb-4 col-4">
<br>
<input type="Date" th:field="*{startdate}" placeholder="Start Date" class="form-control mb-4 col-4">
<br>
<input type="Date" th:field="*{targetdate}" placeholder="Target Date" class="form-control mb-4 col-
4">
<br>
<button type="submit" class="btn btn-info col-2">Save Todo</button>
</form>
Controller class:
#GetMapping("/showAddForm")
public String showAddForm(Model model) {
Todo todo = new Todo();
model.addAttribute("todo", todo);
return "AddTodo";
}
#PostMapping("/saveTodo")
public String saveTodo(#ModelAttribute("todo") Todo todo) {
ts.saveTodo(todo);
return "redirect:/index";
}

How to assign entity to another entity in a form using ThymeLeaf?

I am working on MVC Java project and am using Spring Boot with ThymeLeaf. The issue I have is, that when creating a Task, I want to select and save a User, that will be assign to the task. I managed to do the selection correctly, but am unable to save the selected user. It always saves without the User assigned.
Here is my Task entity class:
#Entity
public class Task extends BaseEntity {
private String name;
private String description;
private Date dateOfCreation;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dueDate;
#ManyToOne
private User assignee;
public Task() {
this.dateOfCreation = new Date(System.currentTimeMillis());
}
}
My User entity is as follows:
#Entity
public class User extends BaseEntity {
private String username;
private String password;
#OneToMany(mappedBy = "assignee")
private List<Task> assignedTasks;
}
Where BaseEntity contains
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Version
private Integer version;
My controller function, that is responsible for my taskform.html is:
#RequestMapping("/new")
public String newTask(Model model){
model.addAttribute("task", new Task());
model.addAttribute("users", userService.getAllUsers());
return "task/taskform";
}
And my taskform.html looks like this:
<form class="form-horizontal" th:object="${task}" th:action="#{/task}" method="post">
<input type="hidden" th:field="*{id}"/>
<input type="hidden" th:field="*{version}"/>
<div class="form-group">
<label class="col-sm-2 control-label">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{name}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Description:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{description}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Description:</label>
<div class="col-sm-10">
<input type="date" th:value="*{dueDate}" th:field="*{dueDate}" id="dueDate" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Select user:</label>
<div class="col-sm-10">
<select class="form-control">
<option th:field="*{assignee}" th:each="assignee : ${users}" th:value="${assignee}" th:text="${assignee.username}">
</option>
</select>
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-default">Submit</button>
</div>
I am trying to pass the object from users list as the value, but it does not work Any idea, how to do it?
Showing the users works as expected:
Working frontend
Null is being assigned to assignee column, where the user should be assigned.
Null in H2 Database
EDIT
Here is my POST method from Task Controller:
#RequestMapping(method = RequestMethod.POST)
public String saveOrUpdate(Task task){
taskService.persistTask(task);
return "redirect:/task/list";
}

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
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.
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.

Spring boot Mongodb Creating a nested document

can any one please tell me what I am missing ?
I am trying to create a Mongo collection using spring boot mongodb.
I want to create something like this
{
"_id":"123456"
"entity_name":"some name"
"entity_desc":"some description"
"events":[
{"title":"some title", "description":"some description"},
{"title":"title2", "description":"description2" }
]
}
but I am getting this
{
"_id":"123456"
"entity_name":"some name"
"entity_desc":"some description"
"events":[ ]
}
my Domain classes are
#Document
public class Entity {
#Id
private BigInteger id;
private String name, description;
private List<Event> events=new ArrayList<Event>();
/* GETTERS AND SETTERS */
}
public class Event {
private String titles;
private String descriptions;
/* GETTERS AND SETTERS */
}
and my repository is
public interface MyRepository extends MongoRepository<Entity, String>{
}
controller is
#Controller
public class RootController {
#Autowired
private MyRepository mr;
/* GET and other methods */
#RequestMapping(value="/", method=RequestMethod.POST)
public String helloPost(#ModelAttribute Entity entity){
mr.save(entity);
return "success";
}
}
and my jsp form is
<form:form modelAttribute="entity" role="form">
<div class="form-group">
Name <input type="text" id="name" name="name" /><br />
</div>
<div class="form-group">
Description <input type="text" id="description" name="description" /><br />
</div>
<div class="form-group">
event <input type="text" id="event" name="event" /><br />
</div>
<div class="form-group" >
title <input type="text" id="title" name="title" /><br />
</div>
<div class="form-group" >
description <input type="text" id="description" name="description" /><br />
</div>
<div>
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form:form>
Shouldn't it be something like below?
public class Event {
private String title;
private String description;
/* GETTERS AND SETTERS */
}
EDIT : Thanks for the jsp, clearly the way you are passing the values are not picked for child. Spring MVC doesn't support ONGL so it won't pick up child object with dot notation. But there are complex mechanism by setting path. Please look at this answer where it did pass child object list through form parameter. So it can be good starting point.

Resources