Missing values between GET and POST method - spring

I'm learning Spring Boot and I have a problem. I'm creating an Order in one form and then adding the user's details in the second. The second form's GET method has the parameter NewOrder and it's received well (checked using a debugger). Then in this form I'm creating OrderDetails, in which is saved NewOrder and some Strings. Then I'm passing it to the repository using POST method, but in created OrderDetails, there're only Strings and NewOrder is null. How could I resolve it?
First POST method (from the first controller):
#PostMapping
public String processOrder( #ModelAttribute NewOrder order, final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("order", order);
ordersProxy.addOrder(order);
return "redirect:/sendOrder";
}
Second controller (POST and GET):
#GetMapping
public String showSendOrderForm(Model model, #ModelAttribute("order") NewOrder order) {
model.addAttribute("details", new OrderDetails(order) );
model.addAttribute("companies", companyProxy.getCompanies());
return "orderDetails";
}
#PostMapping
public String processTaco( OrderDetails details) {
detailsProxy.addOrderDetails(details);
return "orderDetails";
}
And here, the OrderDetails details in Post Order is null.
orderDetails.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
<link rel="stylesheet" th:href="#{/styles.css}" />
</head>
<body>
<form method="POST" th:object="${details}">
<a th:href="#{/design}" id="another">Order</a><br/>
<h3>Deliver to...</h3>
<label for="name">Name: </label>
<input type="text" th:field="*{name}"/>
<br/>
<label for="surname">Surname: </label>
<input type="text" th:field="*{surname}"/>
<br/>
<label for="room">Room: </label>
<input type="text" th:field="*{room}"/>
<br/>
<br/>
<h2>Please, choose your company:</h2>
<select th:field="*{company}">
<option th:each="i : ${companies}" th:value="${i.id}" th:text="${i.name}">
</option>
</select>
</div>
</div>
<input type="submit" value="Submit Order"/>
</form>
</body>
</html>
OderDetails class:
#Data
#Entity
#RequiredArgsConstructor
#NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
public class OrderDetails {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String surname;
private String room;
#OneToOne
private final NewOrder order;
#ManyToOne
private Company company;
}
I have also tried to pass NewOrder directly to POSTmethod and there add order to details, but it was still null.

Adding #RequestBody should work for null OrderDetails. Check out this for more about it: https://www.baeldung.com/spring-request-response-body
#PostMapping
public String processTaco(#RequestBody OrderDetails details) {
detailsProxy.addOrderDetails(details);
return "orderDetails";
}

Related

How to send list of items from JSP back to Controller in Spring boot?

I'm trying to display list of questions on JSP page and using the check-box to select and submit them back to controller.
I can display them without any problem but when they're Posted back 'QuestionsListWrapper' is Null. Can someone point to me where I'm going wrong.
Entity Question
public class Questions implements Serializable {
#Id
#GeneratedValue
private Integer quesId;
#Transient
private boolean isSelected;
Wrapper class
public class QuestionsListWrapper {
private List<Questions> quesWrapperList;
public List<Questions> getQuesWrapperList() {
return quesWrapperList;
}
public void setQuesWrapperList(List<Questions> quesWrapperList) {
this.quesWrapperList = quesWrapperList;
}
Controller Get
#GetMapping("/group/{id}")
public String showForm(#PathVariable("id") Integer id, Model model) {
Assessments ass = as.getAssById(id);
List<Questions> qlist = qs.getQuesByAssessment(ass);
QuestionsListWrapper qlw = new QuestionsListWrapper();
qlw.setQuesWrapperList(qlist);
model.addAttribute("questions", qlw.getQuesWrapperList());
return "stuEssay";
Controller Post
#PostMapping("/saveSelectedQuestions")
//Here questions is null
public String saveSelectedQuestions(#ModelAttribute("questions") QuestionsListWrapper questions, Model model) {
List<Questions> selected = questions.getQuesWrapperList();
System.out.println(questions.toString());
System.out.println(questions.getQuesWrapperList());
return "redirect:/studentHome";
JSP
<form:form action="/saveSelectedQuestions" method="post" modelAttribute="questions">
<c:forEach items="${questions}" var="question" varStatus="count">
<input type="hidden" name="quesId" value="${question.quesId}">
<div class="form-group">
<textarea rows="3" >${question.quesText}</textarea>
<input type="checkbox" name="isSelected[${count.count}]"/>
</div>
</c:forEach><!-- End of question list -->
<div class="modal-footer">
<button type="submit" class="btn btn-primary" >Submit</button>
</div>
</form:form>

Pass a list of user defined object from input field using spring form handling

I have an Employee class that looks like this.
public class Employee {
private String Name;
private List<Address> address;
*****Getters and Setters****
}
And my Address class looks like this
public class Address {
private int addressid;
private Employee employee;
#NotNull(message="Field Cannot be Empty")
private String description;
*****Getters and Setters****
}
I want to bind List of addresses (Employee can have more than one address - 1:M) to the employee class with the data that is parsed through the form. Which looks like this.
I have 3 input address fields, one of the sample input fields look like this...
<div class="form-group">
<div class="row">
<label class="col-sm-3" for="exampleInputEmail1">Address
1</label>
<div class="col-sm-7">
<form:input class="form-control" placeholder="" path="" />
<form:errors path="" cssClass="error" />
</div>
</div>
</div>
Note that I have cut down many unnecessary form fields to demonstrate the problem more clearly. Please help me bind the list of input fields with the relevant class. Any advice for this design is also welcome.
You can use Thymeleaf for this as below.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>form|data</title>
</head>
<body>
<div class="starter-template">
<form th:action="#{employeeData}" method="post" th:object="${employee}">
<input th:field="*{name}" type="text" th:name="name" name="name" placeholder="name" class="input u-one-third js-get-form-data"/>
<th:block th:each="add,addStat:*{address}">
<input th:field="*{address[__${addStat.index}__].description}" type="text" th:name="add.description" name="description" placeholder="description" class="input u-one-third js-get-form-data"/>
</th:block>
<input type="submit" value="SEND"/>
</form>
</div>
</body>
</html>
Controller.
#RequestMapping(value = "/formData", method = RequestMethod.GET)
public String formData(Map<String, Object> model) {
Employee employee = new Employee();
Address address = new Address();
address.setDescription("TEST");
address.setEmployee(employee);
employee.getAddress().add(address);
model.put("employee",employee);
return "formData";
}
#RequestMapping(value = "/employeeData", method = RequestMethod.POST)
public void employeeData(#Valid Employee employeeData, BindingResult errors) {
System.out.println(employeeData.getName());
}
Please find the working commit here.

Spring/Hibernate not persisting all data submited from HTML Form

In my current spring pŕoject, I have a form like that:
<form role="form" class="form" id="form" method="post" action="/loja/pagina/insert" enctype="multipart/form-data">
<input class="form-control" type="hidden" name="id" />
<label>Title</label>
<input class="form-control" type="text" name="titulo" />
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
pt-BR
</li>
<li role="presentation">
es-ES</li>
<li role="presentation">en-US</li>
</ul>
<div class="tab-content">
<div role="tabpane1" class="tab-pane active" id="pt-BR">
<input type="hidden" name="textos.idioma" value="pt-BR" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
<div role="tabpane1" class="tab-pane" id="es-ES">
<input type="hidden" name="textos.idioma" value="es-ES" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
<div role="tabpane1" class="tab-pane" id="en-US">
<input type="hidden" name="textos.idioma" value="en-US" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
</div>
</form>
When I submit this form to this methods:
controller
#RequestMapping(value = "/insert", method=RequestMethod.POST)
#ResponseBody
#PreAuthorize("hasPermission(#user, 'insert_'+#this.this.name)")
public void insert(#Valid E object, BindingResult result) {
serv.insert(object);
}
service
#Transactional
public void insert(E object) {
dao.insert(object);
}
dao
#Transactional
public void insert(E object) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.persist(object);
tx.commit();
} catch (Exception e) {
if(tx != null)
tx.rollback();
} finally {
session.close();
}
}
Only the field titulo is persisted. the field textos , which is represented by this entity class (getters and setter omitted):
#Entity
public class Texto extends Model {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column
private String idioma;
#Column
private String conteudo;
}
is not saved on the database. Anyone can tell what's the right way to implement the form to properly store this data? I check the browser's developer tools, and the data is being submitted, it's only not being persisted in the database.
I assume, that your model class Texto has a #OneToMany relation to class E, so that one E references multiple instances of Texto. If this is what your model expresses, you have to use a different syntax for your textarea names to Spring being able to parse your request payload.
In your case Spring would search for a property textos.conteudo on your class E. As I assume, that textos will be a collection, Spring will ignore this.
Assuming, that textos will be modeled as an indexed based collection like List, try to rename your textareas names to name="textos[0].conteudo" and so on to tell Spring that textos is a List and Spring will be able to parse the POST payload.
With the hint given to me by the user #AnsgarSchulte in this question, I change the html code in the form for name="textos[0] and change my PropertyEditorSupport class to handle this array and return a Texto object with the property idioma being the first element of the vector and the property conteudo being all the elements left (concatenating all of them in one string).

Can not get the error message in the spring form

I am woring on an Spring Web application with the CURD operation for the Entity Department, this is the handler for processing the submit of a new Department:
#RequestMapping(value = "/", method = RequestMethod.POST)
public String addSubmit(#Valid Department department, BindingResult result,SessionStatus status) {
if (result.hasErrors()) {
return "department/add";
} else {
departmentService.save(department);
status.setComplete();
return "redirect:/departments/" + department.getId();
}
}
Model:
#Entity
public class Department extends BaseNamedEntity {
#NotNull
#NotEmpty
private String description;
...
}
And the form:
<form:form method="post" action="${fmURL}" class="form-horizontal" commandName="department">
<form:hidden path="id"/>
<spring:bind path="name">
<div class="control-group ${status.error ? 'error' : ''}">
<label class="control-label">Name</label>
<div class="controls">
<form:input path="name"/>
<span class="help-inline">${status.errorMessage}</span>
</div>
</div>
</spring:bind>
<form:form>
However, once I submit the form with empty field, normally, the errorMessage should be displayed and the related div should be add a class with error, however I can not found the error message.
What's going on?
BTW, the example is derive from Spring-petclinic project.

Spring MVC: #RequestParam validation

In my register form i'm using Bean Validator (JSR-303) for validate User object, and need to validate separately password confirmation, because it is not a member of User. I have a problem to assign error message for confirm field. How to do that ?
View:
<form:form modelAttribute="user" method="post" action="register.html">
<div class="fcell">
<div class="clabel"><spring:message code="label.password"/></div>
<div class="cdata"><form:password path="password"/></div>
<div class="cmsgs"><form:errors path="password" /></div>
</div>
<div class="fcell">
<div class="clabel"><spring:message code="label.confirm"/></div>
<div class="cdata"><input type="password" name="confirm"/></div>
<div class="cmsgs"></div>
</div>
</form:form>
Controller:
#RequestMapping("/register.html")
public String register(#RequestParam("confirm") String confirm, #ModelAttribute("user") #Valid User user, BindingResult result) {
if(!DigestUtils.sha256Hex(confirm).equals(user.getPassword())) {
/* Invalid property 'confirm' ... */
result.rejectValue("confirm", "text.passwords_not_equal");
}
return "register";
}
In this case confirmation can be considered a part of model object, like this:
public class RegistrationForm {
#Valid
private User user;
private String confirm;
...
}
...
public String register(#ModelAttribute("user") #Valid RegistrationForm user,
BindingResult result) { ... }
...
<div class="cdata">
<form:password path="confirm"/></div>
<div class="cmsgs"><form:errors path="confirm" />
</div>
...

Resources