Spring mvc #RequestBody String format - java

I have one Controller : personController.java
#Controller
public class personController {
private static final Logger LOG = LoggerFactory.getLogger(OcaController.class);
#RequestMapping(value = "/person", method = {RequestMethod.POST, RequestMethod.GET})
public String ocaContract(#RequestBody String requestPerson) {
return requestPerson;
}
1 JSP : person.jsp
<html>
<head>
</head>
<body>
<form class="form-horizontal" METHOD="POST" ACTION="webmvc/person" ENCTYPE="x-www-form-urlencoded">
<div class="controls">
<input type="text" name="name" id="name" value="" placeholder="">
</div>
<div class="controls">
<input type="text" name="surname" id="surname" value="" placeholder="">
</div>
<input type="submit" value="ok"/>
</form>
</body>
</html>
and one Object Class : Person.java
#XmlRootElement(name="Person")
public class Person {
#XmlElement(required = true)
protected String name;
#XmlElement(required = true, nillable = true)
protected String surname;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
} ...
When I populate the JSP and click on the input button, my controller return this "requestPerson" string :
name=&surname=
Is it a way to have this string as a POJO ? My final result must be at the XML format :
<person>
<name>Lisala</name>
<surname>Lili</surname></person>
I hope you ll can help me because i'm on it since 1 day now and i didn't find an easy way to accomplish this.

You can replace #RequestBody with #ModelAttribute and String to Person
public String ocaContract(#ModelAttribute Person requestPerson) {

Related

'Required request parameter 'id' for method parameter type Integer is present but converted to null'

I'm creating todo-app with spring-boot.
After adding a task, once I enter a check on checkbox provided next to each todo and then click the done-button, the error occurs.'Required request parameter 'id' for method parameter type Integer is present but converted to null' has occurs.
below is codes.
Todo.java
#Entity
#Data
#Table(name = "todos")
public class Todo {
#Id
#Nullable
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Nullable
#Column(name = "user_id", nullable = false)
private Integer userId;
#NotNull
#NotBlank
#Column(name = "title")
private String title;
#NotNull
#NotBlank
#Column(name = "description")
private String description;
#NotNull
#NotBlank
#Column(name = "due_date")
private String dueDate;
#Column(name = "priority")
private Integer priority;
#NotNull
#Column(name = "is_completed")
private Boolean isCompleted = false;
public Todo() {
}
public Todo(Integer userId, String title, String description, String dueDate, Integer priority, Boolean isCompleted) {
this.userId = userId;
this.title = title;
this.description = description;
this.dueDate = dueDate;
this.priority = priority;
this.isCompleted = isCompleted;
}
}
TodoController.java
#Controller
public class TodoController {
#Autowired
TodoRepository todoRepository;
#Autowired
TodoService todoService;
#GetMapping("/todo/{id}")
public String home(Model model, User user, Todo todo, #PathVariable("id")Integer id) {
Integer userId = user.getId();
if(userId == null) {
return "redirect:/todo/{id}";
}
List<Todo> list = todoRepository.find(userId);
model.addAttribute("list", list);
model.addAttribute("todo", new Todo(user.getId(), todo.getTitle(), todo.getDescription(), todo.getDueDate(), todo.getPriority(), todo.getIsCompleted()));
return "home";
}
#PostMapping("/todo/{id}")
public String createTodo(#Validated Todo todo,BindingResult result, User user) {
if(result.hasErrors()){
return "redirect:/todo/{id}";
}
Todo userTodo = new Todo(user.getId(), todo.getTitle(), todo.getDescription(), todo.getDueDate(), todo.getPriority(), todo.getIsCompleted());
todoService.addTodo(userTodo);
return "redirect:/todo/{id}";
}
#PostMapping("/todo/update/{id}")
public String doneTodo(#RequestParam(name="id")Integer todoId) {
Todo updateTodo = todoService.findById(todoId);
updateTodo.setIsCompleted(true);
todoService.addTodo(updateTodo);
return "redirect:/todo/{id}";
}
#PostMapping("/todo/edit/{id}")
public String editTodo() {
System.out.println("edit");
return "redirect:/todo/{id}";
}
}
TodoService.java
#Service
public class TodoService {
#Autowired
TodoRepository todoRepository;
public List<Todo> searchAll() {
return todoRepository.findAll();
}
public void addTodo(Todo todo) {
todoRepository.save(todo);
}
public Todo findById(Integer id) {
Optional<Todo> updateTodo = todoRepository.findById(id);
return updateTodo.orElseGet(updateTodo::get);
}
}
home.html
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link th:href="#{/css/home.css}" rel="stylesheet"/>
<title>Todo</title>
</head>
<body>
<h1>Todo</h1>
<div>
<form method="post" th:action="#{/todo/}+${id}" th:object="${todo}">
<p th:errors="*{title}" class="todo-error-message"></p>
<input th:field="*{title}" class="add-input" type="text" placeholder="title">
<input th:field="*{description}" class="add-input" type="text" placeholder="details">
<input th:field="*{dueDate}" class="add-input-third" type="date"><br/>
<div class="add-form">
<span>priority</span>
<input th:field="*{priority}" type="radio" name="priority" value="3" checked>3
<input th:field="*{priority}" type="radio" name="priority" value="2">2
<input th:field="*{priority}" type="radio" name="priority" value="1">1
</div>
<button type="submit" class="add-btn">add</button>
</form>
</div>
<h2>LIST</h2>
<form method="post" th:action="#{/todo/edit/}+${id}" th:each="list:${list}" th:object="${todo}">
<div th:if="${!todo.isCompleted}">
<input type="checkbox" th:id="${todo.id}" th:value="${todo.id}" th:field="*{isCompleted}" form="done-todo">
<input type="hidden" name="userId" th:value="${list.userId}">
<input type="text" name="title" th:value="${list.title}">
<input type="text" name="description" th:value="${list.description}">
<input type="date" name="dueDate" th:value="${list.dueDate}">
<input type="submit" value="update">
</div>
</form>
<form method="post" id="done-todo" th:action="#{/todo/update/}+${id}">
<input type="hidden" name="id" th:value="${todo.id}">
<input type="submit" value="done">
</form>
<div>
<button type="button" class="btn btn-primary p-3" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
show done todos
</button>
<div class="collapse" id="collapseExample">
<form class="border p-3" th:action="#{/todo/delete/}+${id}" th:each="todo:${todo}">
<div th:if="${todo.isCompleted}">
<input type="text" name="title" th:value="${todo.title}">
<input type="submit" value="delete">
</div>
</form>
</div>
</div>
<form th:action="#{/logout}" method="post">
<button class="logout-button" type="submit" value="logout">logout</button>
</form>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
</body>
</html>
What I want to do
I aim to change the value of added todo from false to true after entering a check on checkbox provided next to each todo and then click the done-button.
I aim to show todos of which value is true.(true means 'done')
Does anyone know how to fix this?
I couldn't find the way to fix this and I’m so badly stuck at this task.

Access Multiple beans using thymeleaf and springboot MVC

Trying to access multiple objects in the POST method using SpringBoot MVC and thymeleaf.
here is the controller.
#Controller
public class PatientController {
ObjectMapper Obj = new ObjectMapper();
#GetMapping("/patient")
public static String patientForm(Model model) {
model.addAttribute("patient", new PatientDataModel());
model.addAttribute("patient1", new PatientDataModel1());
return "patient";
}
#RequestMapping(value="/patient", method=RequestMethod.POST, params="action=Send data to MongoDB cluster")
public static String patientSubmit(#ModelAttribute("patient") PatientDataModel patient, #ModelAttribute("patient1") PatientDataModel patient1, Model model, Object obj ) throws JsonProcessingException {
model.addAttribute("patient", patient);
model.addAttribute("patient1", patient1);
return "result";
}
and here are the views:
patient.html
<form action="#" th:action="#{/patient}" th:object="${patient}" method="post">
<div th:object="${patient1}" >
<p>Patient Id: <input type="text" th:value="${patient.id}" /></p>
<p>Patient Name: <input type="text" th:value="${patient.name}" /></p>
<p>Message: <input type="text" th:value="${patient.content}" /></p>
<p>address: <input type="text" th:value="${patient1.address}" /></p>
</div>
<p><input type="submit" name="action" value="Send data to MongoDB cluster" />
<input type="reset" value="Reset" /></p>
</form>
</div>
and result.html
<div class="starter-template">
<h1>Result</h1>
<p th:text="'id: ' + ${patient.id}" />
<p th:text="'Name: ' + ${patient.name}" />
<p th:text="'content: ' + ${patient.content}" />
<p th:text="'address: ' + ${patient1.address}" />
Submit another message
</div>
and the bean classes are : PatientDataModel.java
public class PatientDataModel {
private long id;
private String content;
private String name;
public PatientDataModel()
{
}
public PatientDataModel(long id, String content, String name)
{
this.id = id;
this.content = content;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#Override
public String toString()
{
return "Patient [id=" + id + ", firstName=" + name + ", " +
"content=" + content + "]";
}
}
another bean :
public class PatientDataModel1 {
private String address;
#Override
public String toString() {
return "Patient1 [address=" + address + "]";
}
public PatientDataModel1()
{
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
now , the issue is , I need both the beans to be accessible in the GET and POST method.
when I am running the code , it is executing but the beans does not have values , all are null . pls suggest
It will be easiest to have 1 object to find to the form. Create a new class PatientFormData for example that contains all the fields from the 2 objects and convert from/to the objects you have in the get and post methods in your controller.
For example:
public class PatientFormData {
private long id;
private String content;
private String name;
private String address;
public static PatientFormData from(PatientDataModel model,
PatientDataModel1 model1) {
id = model.getId();
content = model.getContent();
name = model.getName();
address = model.getAddress();
}
public PatientDataModel createPatientDataModel() {
PatientDataModel result = new PatientDataModel();
result.setId(id);
result.setContent(content);
result.setName(name);
return result;
}
// getters and setters here
}
Use this in the controller:
#Controller
public class PatientController {
ObjectMapper Obj = new ObjectMapper();
#GetMapping("/patient")
public static String patientForm(Model model) {
PatientFormData formData = PatientFormData.from(new PatientDataModel(), new PatientDataModel1());
model.addAttribute("patientFormData", formData);
return "patient";
}
#RequestMapping(value="/patient", method=RequestMethod.POST, params="action=Send data to MongoDB cluster")
public static String patientSubmit(#ModelAttribute("patientFormData") PatientFormData formData, Model model, Object obj ) throws JsonProcessingException {
PatientDataModel model = formData.createPatientDataModel();
PatientDataModel1 model1 = formData.createPatientDataModel1();
// Do more processing with objects
return "result";
}
Also be sure to correctly use the field binding using *{..}:
<form action="#" th:action="#{/patient}" th:object="${patientFormData}" method="post">
<p>Patient Id: <input type="text" th:value="*{id}" /></p>
<p>Patient Name: <input type="text" th:value="*{name}" /></p>
<p>Message: <input type="text" th:value="*{content}" /></p>
<p>address: <input type="text" th:value="*{address}" /></p>
</div>
<p><input type="submit" name="action" value="Send data to MongoDB cluster" />
<input type="reset" value="Reset" /></p>
</form>
</div>

Error ID is null when should be auto-incremented

I'm trying to create a web form that allows a user to add an item to a database. Problem is when I submit said form I get the following error:
Field error in object 'products' on field 'id': rejected value [null]; codes [typeMismatch.products.id,typeMismatch.id,typeMismatch.int,typeMismatch]; arguments
Here's my jsp page:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Add Item Page</title>
</head>
<body>
<h1> Add an Item </h1>
<form action="/addItem" method="post">
<div class="form-group">
<label for="name">Name</label>
<input class="form-control" type = "text" id="name" name="name" required minlength="2" autocomplete="off">
</div>
<div class="form-group">
<label for="price">Price</label>
<input class="form-control" type = "text" id="price" name="price" required>
</div>
<div class="form-group">
<label for="quantity">Quantity</label>
<input class="form-control" type="number" id="quantity" name="quantity" required>
</div>
<div class="form-group">
<label for="foodGroup">Food Group</label>
<input class="form-control" type="text" id="foodGroup" name="foodgroup" required>
</div>
<button type="submit" class="btn btn-primary" value="submit">Add Product</button>
</form>
Home
</body>
Here's the relevant part of my Products class (the rest is typical getter/setter/toString. I also left out the package line at the top):
import javax.persistence.*;
#Entity
#Table(name="products")
public class Products
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
String name;
String foodgroup;
int quantity;
Float price;
String image;
private Products() {}
public Products(int id, String name, int quantity, float price, String foodgroup, String image)
{
this.id = id;
this.name = name;
this.quantity = quantity;
this.foodgroup = foodgroup;
this.price = price;
this.image = image;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
and finally the controller:
#Controller
public class MainController
{
#Autowired
private ProductsDAO productsDAO;
#GetMapping("/")
public ModelAndView showHome()
{
ModelAndView mav = new ModelAndView("index");
return mav;
}
#RequestMapping("/showProducts")
public ModelAndView showProducts()
{
List<Products> leListOfProducts = productsDAO.findAll();
ModelAndView mav = new ModelAndView("showProducts", "product", leListOfProducts);
return mav;
}
#RequestMapping("/addItem")
public ModelAndView showAddItemPage()
{
return new ModelAndView("addItem");
}
#PostMapping("/addItem")
public ModelAndView addProduct(Products product)
{
productsDAO.create(product);
return new ModelAndView("redirect:/index");
}
}
Here's a pic of the table columns and their settings.
I really appreciate any and all help ya'll can provide!
Best,
JBird
I suspect that your constructor is the issue there. Try removing the id in the constructor, as it is being generated by 3rd party means. Also, I don't think you will ever need the setId() method for any sane reason.

Thymeleaf select tag causes exception

I have a controller class and I have debugged it. I have added 2 lines as below in the controller class.
model.addAttribute("employees",employees);
model.addAttribute("visitorForm",visitorForm);
I have seen both the objects are present and populated properly.
When it comes to the page it is as below.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Enter Visitor Details</title>
</head>
<body>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div class="container"></div>
<form action="#" th:action="#{/enterVisitor}" th:object="${visitorForm}" method="post">
<p>Name: <input type="text" th:field="*{name}" required="required"/></p>
<p>Address: <input type="text" th:field="*{address}" required="required"/></p>
<p>Mobile: <input type="text" th:field="*{mobileNumber}" size="10" required="required" maxlength="10"/></p>
<p>Email: <input type="text" th:field="*{email}" /></p>
<p>Purpose: <input type="text" th:field="*{purposeOfvisit}" size="20" required="required"/></p>
<p>In Time:<input type="number" id="inTimee" name="inTimee" contenteditable="false" readonly="readonly"/></p>
<script type="text/javascript">document.getElementById("inTimee").value=new Date().getTime()</script>
<p>Employee to Meet:  <select th:field="${visitorForm.id}">
                         <!-- <option text=""><option> -->
                         <option th:each="emp:${employees}"
                            th:value="${emp.id}"
                            th:text="${emp.name}"/>
                  </select>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</div>
<script type="text/javascript">
function getDateTime(){
var x = document.getElementById("inTimee").value=new Date().getTime();
}
</script>
</body>
</html>
I am getting an exception saying.
org.thymeleaf.exceptions.TemplateProcessingException: Attribute "value" is required in "option" tags (template: "visitor/enterVisitor" - line 20, col 26)
at org.thymeleaf.spring5.processor.SpringOptionFieldTagProcessor.doProcess(SpringOptionFieldTagProcessor.java:63) ~[thymeleaf-spring5-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:187) ~[thymeleaf-spring5-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:282) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
Here is the visitor form class.
package com.ahmed.visitorapp.forms;
import java.util.ArrayList;
import java.util.List;
import com.ahmed.visitorapp.model.Employee;
public class VisitorForm {
String id;
String name;
String address;
String mobileNumber;
String email;
String purposeOfvisit;
List<Employee> employees;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPurposeOfvisit() {
return purposeOfvisit;
}
public void setPurposeOfvisit(String purposeOfvisit) {
this.purposeOfvisit = purposeOfvisit;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public void setEmployees(Iterable<Employee> employees) {
if(this.employees==null) {
this.employees = new ArrayList<>();
}
for(Employee emp:employees) {
this.employees.add(emp);
}
}
}
Employee class has fields name and Id. <select> tag causes the exception. How to fix it?
Add "value" attribute to your option like below :
<option th:each="emp:${employees}" th:value="${emp.id}" th:text="${emp.name}" value=""/>
For more detail refer this
Adding a more generic answer in a scenario where your <select> doesn't map to several fields in employees and maps to just one field, you will have to just add the "value" attribute.
There's no need for the th:value attribute
example :
<select th:field="*{employees}">
<option value="Name">Employee Name</option>
</select>

Parse input fields as a Array list to controller via #RequestMapping

I want to submit all textfields and radiobuttons from my input fields as an ArrayList and parse it to the controller but I don't know really how.
Any help is really appreciated.
Here's what I tried so far:
#RequestMapping(value = "/formdata", method = RequestMethod.POST)
public String formdata(HttpServletRequest req, #AuthenticationPrincipal User currentUser,
#ModelAttribute RegDatas regDatas, Model model) {
// get values as regDatas[0]?
}
Here's my HTML form:
<form method="post" th:action="#{/formdata}" th:object="${regDatas}">
<div class="col-sm-4">
<input th:field="*{regDatas[0].gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="*{regDatas[0].gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="*{regDatas[0].firstname}" placeholder="Max" disabled="disabled" />
</div>
<div class="col-sm-4">
<input th:field="*{regDatas[1].gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="*{regDatas[1].gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="*{regDatas[1].firstname}" placeholder="Max" disabled="disabled" />
<button type="submit">Speichern</button>
</div>
</form>
My wrapper class:
public class RegDatas {
private List<RegData> regDatas;
public List<RegData> getRegDatas() {
return regDatas;
}
public void setRegDatas(List<RegData> regDatas) {
this.regDatas = regDatas;
}
}
My class to store values:
public class RegData {
private String email;
private String firstname;
private Gender gender;
public String getEmail() {return email;}
public void setEmail(String email) {this.email = email;}
public String getFirstname() {return firstname;}
public void setFirstname(String firstname) {this.firstname = firstname;}
public Gender getGender() {return gender;}
public void setGender(Gender gender) {this.gender = gender;}
}
This is the error I see if I run it like this:
org.springframework.beans.NotReadablePropertyException: Invalid property 'RegDatas[0]' of bean class [de.ciss.aag.model.domain.RegData]: Bean property 'RegDatas[0]' is not readable or has an invalid getter method
From your comments, I think the problem is that your model is not populated with a RegDatas object. This Baeldung tutorial - Getting Started with Forms in Spring MVC, particularly section 4 is probably a good resource, if you haven't already seen it, but I think you need something like this (from the tutorial) in your controller:
#RequestMapping(value = "/employee", method = RequestMethod.GET)
public ModelAndView showForm() {
return new ModelAndView("employeeHome", "employee", new Employee());
}
But you'll need to add a populated RegDatas instance to your model, instead of the employee, so as a very basic example, this seems to work for me, with your code. There are other ways of populating the model, that I'd recommend researching, but this is probably the most straightforward.
#RequestMapping("/your-page-endpoint")
public ModelAndView get() {
return new ModelAndView("your-view-name", "regDatas", new RegDatas());
}

Categories

Resources