Access Multiple beans using thymeleaf and springboot MVC - java

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>

Related

How to configure the modal to display the retrieved data from a table in springboot?

Customer.java
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String relative;
private String address;
private Long aadhar;
private Long contact;
private String townname;
public Long getAadhar() {
return aadhar;
}
public void setAadhar(Long aadhar) {
this.aadhar = aadhar;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRelative() {
return relative;
}
public void setRelative(String relative) {
this.relative = relative;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Long getContact() {
return contact;
}
public void setContact(Long contact) {
this.contact = contact;
}
public String getTownname() {
return townname;
}
public void setTownname(String townname) {
this.townname = townname;
}
CustomerController.java
#Controller
public class CustomerController {
#Autowired
private CustomerService customerService;
#Autowired
private TownService townService;
#GetMapping("/customer")
public String findAllCustomers(Model model) {
model.addAttribute("customers", customerService.findAllCustomers());
model.addAttribute("towns", townService.findAllTown());
return "customer";
}
#PostMapping("/customer/addnew")
public String addNew(Customer customer) {
customerService.saveCustomer(customer);
return "redirect:/customer";
}
#RequestMapping(value="/customer/findCustomerById/",method = RequestMethod.GET)
#ResponseBody
public Optional<Customer> findCustomerById(Long id) {
return customerService.getCustomerById(id);
}
}
CustomerService.java
#Service
public class CustomerService {
#Autowired private CustomerRepository customerRepository;
public List<Customer> findAllCustomers() {
return customerRepository.findAll();
}
public void saveCustomer(Customer customer) {
customerRepository.save(customer);
}
public Optional<Customer> getCustomerById(Long id) {
return customerRepository.findById(id);
}
}
customer.html
<a th:href="#{/customer/findCustomerById/(id=${customer.id})}"
type="button" class="btn btn-primary "
data-toggle="modal" data-target=".bd-edit-modal-lg">
<span class="material-icons" >edit</span></a>
<form class="row g-3">
<div class="col-md-8">
<label for="customername" class="form-label">Customer ID</label>
<input type="text" class="form-control" id="nameEdit" name="id"
onKeyup="this.value = this.value.toUpperCase()" readonly>
</div>
<div class="col-md-4">
<label for="aadhar" class="form-label">Aadhar No.</label>
<input type="number" min="0" max="999999999999" class="form-control" id="aadhar"
name="aadhar">
</div>
<div class="col-md-8">
<label for="customername" class="form-label">Customer Name</label>
<input type="text" class="form-control" id="nameEdit" name="name"
onKeyup="this.value = this.value.toUpperCase()" required>
</div>
<div class="col-md-6">
<label for="relative" class="form-label">S/O,D/O,C/O</label>
<input type="text"class="form-control" id="relativeEdit" name="relative"
onKeyup="this.value = this.value.toUpperCase()" required>
</div>
<div class="col-md-6">
<label for="contact" class="form-label">Contact No.</label>
<input type="number" minlength="10" max="9999999999" class="form-control"
id="contactEdit" name="contact">
</div>
<div class="col-12">
<label for="inputAddress5" class="form-label">Address</label>
<input type="text"class="form-control" id="addressEdit" name="address"
onKeyup="this.value = this.value.toUpperCase()" placeholder="1234 Main St" required>
</div>
<div class="col-md-4">
<label for="inputTown" class="form-label" id="selecttown">Town/Area</label>
<select class="form-control" id="selecttownEdit" name="townname" required>
<option selected>Choose...</option>
<option th:each="town:${towns}" th:value="${town.townname}"
th:text="${town.townname}">...
</option>
</select>
</div>
<div class="text-center" style="margin-bottom:10px">
<button type="submit" class="btn btn-primary mx-1 my-1">Submit</button>
<button type="reset" class="btn btn-secondary mx-1 my-1">Reset</button>
</div>
</form><!-- End Multi Columns Form -->
I checked my responsebody in postman,works fine.But i am stuck at how to populate this data to the form.anything i tried my html page becames blank
My Json Response Body:
{
"id": 1,
"name": "M",
"relative": "U",
"address": "130",
"aadhar": 8891,
"contact": 90,
"townname": "DAR"
}

Null fields in Thymeleaf form using Spring Boot, other fields fine

I'm relatively new to Spring Boot. Currently, I'm making a Spring Boot application with user registration system but I've run into an issue. Some of the fields in a form are registering as ‘null’ on the back end, despite the request being posted correctly.
I have a HTML/ Thymeleaf form which submits 8 fields to create a 'User' object. This is the form:
<form th:action="#{/users/register_attempt}" th:object="${user}"
method="post" style="max-width: 600px; margin: 0 auto;">
<div class="m-3">
<div class="form-group row">
<label class="col-4 col-form-label">DOB: </label>
<div class="col-8">
<input type="text" th:field="*{dob}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">First Name: </label>
<div class="col-8">
<input type="text" th:field="*{name}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Surname: </label>
<div class="col-8">
<input type="text" th:field="*{surname}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">PPSN: </label>
<div class="col-8">
<input type="text" th:field="*{ppsn}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Address: </label>
<div class="col-8">
<input type="text" th:field="*{address}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Phone Number: </label>
<div class="col-8">
<input type="number" th:field="*{phone}" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">E-mail: </label>
<div class="col-8">
<input type="email" th:field="*{email}" class="form-control" th:required="required" />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Password: </label>
<div class="col-8">
<input type="password" th:field="*{password}" class="form-control"
required minlength="6" maxlength="10" th:required="required"/>
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Sign Up</button>
</div>
</div>
</form>
And here is the model that the form code is meant to mimic:
public class User {
#Id
#GeneratedValue
private Long id;
#NotBlank
private String dob;
#NotBlank
private String name;
#NotBlank
private String surname;
#NotBlank
private String ppsn;
#NotBlank
private String address;
#NotBlank
private String phone;
#NotBlank
#Column(unique = true)
private String email;
private String nextApptId;
private String dose1Date;
private String dose2Date;
private String lastLogin;
#NotBlank
private String password;
public User() {
super();
}
public User(String dob, String name, String surname, String ppsn, String address, String phone, String email, String password) {
super();
this.dob = dob;
this.name = name;
this.surname = surname;
this.ppsn = ppsn;
this.address = address;
this.phone = phone;
this.email = email;
this.password = password;
}
public Long getId() {
return id;
}
public String getDob() {
return dob;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public String getPpsn() {
return ppsn;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNextApptId() {
return nextApptId;
}
public void setNextApptId(String apptId) {
this.nextApptId = apptId;
}
public String getDose1Date() {
return dose1Date;
}
public void setDose1Date(String dose1Date) {
this.dose1Date = dose1Date;
}
public String getDose2Date() {
return dose2Date;
}
public void setDose2Date(String dose2Date) {
this.dose2Date = dose2Date;
}
public String getLastLogin() {
return lastLogin;
}
public void setLastLogin(String lastLogin) {
this.lastLogin = lastLogin;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
But for some reason I can't figure out, the first four fields - i.e. Dob (date of birth), Name, Surname, and PPSN, are producing a null error when instantiating the user object on the server side, e.g.:
`Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 4 errors<EOL>
Field error in object 'user' on field 'dob': rejected value [null]; codes [NotBlank.user.dob,NotBlank.dob,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.dob,dob]; arguments []; default message [dob]]; default message [must not be blank] `.
The other four fields, Address, Phone, Email, and Password appear to be working just fine.
As far as I can make out, there it isn't a typo issue (forgive me if that ends up being the case). I have intercepted the Post request using Burp to check that the contents of the fields were making it out of the form and into the request, with the right names for the fields in my User class, and indeed they are all there as intended.
I imagine this means that the issue is coming from how the back end controller code is interpreting this post request based on the model, but I have no real idea of how or where to start. Here is the current controller:
#GetMapping("/register")
public String startRegistration(Model model) {
model.addAttribute("user", new User());
return "register";
}
#PostMapping("/register_attempt")
public String registerAttempt(#Valid User newUser) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(newUser.getPassword());
newUser.setPassword(encodedPassword);
userRepository.save(newUser);
return "registered_successfully";
}
EDIT: Further debugging & clarification with issue persisting
Removing the #Valid annotation from the Post Mapping and using old fashioned print statements shows the same results - that the first four fields are null, for no obvious reason.
#PostMapping("/register_attempt")
public String registerAttempt(#ModelAttribute("user") User newUser) {
System.out.println("Saving user ");
System.out.println("Name " + newUser.getName());
System.out.println("Last Name " + newUser.getSurname());
System.out.println("PPSN " +newUser.getPpsn());
System.out.println("DOB " +newUser.getDob());
System.out.println("email " +newUser.getEmail());
System.out.println("address " +newUser.getAddress());
System.out.println("encrypted password " +newUser.getPassword());
System.out.println("Phone num " +newUser.getPhone());
userRepository.save(newUser);
System.out.println("User saved");
return "registered_successfully";
}
Using the following dummy data:
Which sends this Post Request to the back end:
Results in these print statements:
Saving user
name null
last Name null
ppsn null
dob null
email foo#bar.com
address Here and there
password password
Phone num 987654321
And these error messages:
javax.validation.ConstraintViolationException: Validation failed for classes [app.model.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=surname, rootBeanClass=class app.model.User, messageTemplate='{javax.validation.constraints.NotBlank.message}'}
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=dob, rootBeanClass=class app.model.User, messageTemplate='{javax.validation.constraints.NotBlank.message}'}
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=name, rootBeanClass=class app.model.User, messageTemplate='{javax.validation.constraints.NotBlank.message}'}
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=ppsn, rootBeanClass=class app.model.User, messageTemplate='{javax.validation.constraints.NotBlank.message}'}
]
If you have any insight into why this might be happening, I would very much appreciate it.
You have th:object="${user}" in your Thymeleaf template, so I have to assume that you #GetMapping method in your controller has added an instance of User to the Model using addAttribute.
In your #PostMapping, you should also use #ModelAttribute:
#PostMapping("/register_attempt")
public String registerAttempt(#Valid #ModelAttribute("user") User newUser) {
...
You also need to have setters for each field. I see that User has no setName(String name), no setDob(String dob), ...
Some other tips:
Do not create BCryptPasswordEncoder instances in your controller method itself. When you use Spring Boot, this should be an application wide singleton (Called a bean in Spring lingo). Add a class to your application e.g. ReservationSystemApplicationConfiguration which declares this:
#Configuration
public class ReservationSystemApplicationConfiguration {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Then in your controller, inject the password encoder:
#Controller
#RequestMapping("...")
public class MyController {
private final PasswordEncoder passwordEncoder;
public MyController(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#PostMapping("/register_attempt")
public String registerAttempt(#Valid #ModelAttribute("user") User newUser) {
String encodedPassword = passwordEncoder.encode(newUser.getPassword());
newUser.setPassword(encodedPassword);
userRepository.save(newUser);
return "registered_successfully";
}
}
A Controller should not directly call the Repository, but use a Service in between.
It is better to use different objects for mapping the form data and for storing the data into the database. See Form Handling with Thymeleaf for more information on how to do that.

Cannot print in HTML ArrayList using Spring MVC

I am facing problem trying print at the same time a form and array in the same HTML.
Here is my usuario class:
public class usuario {
private String user_id;
private String createdAt;
private String address;
private String latitude;
private String longitude;
private String birthday;
private String email;
private String user_idp;
private ArrayList pedido;
private String phoneNunmber;
private Integer edad;
public String nombre;
private String confirmationCode;
private String promotions;
public String ciudad;
public String getCiudad() {
return ciudad;
}
public void setCiudad(String ciudad) {
this.ciudad = ciudad;
}
public String getPromotions() {
return promotions;
}
public void setPromotions(String promotions) {
this.promotions = promotions;
}
public String getConfirmationCode() {
return confirmationCode;
}
public void setConfirmationCode(String confirmationCode) {
this.confirmationCode = confirmationCode;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public Integer getEdad() {
return edad;
}
public void setEdad(Integer edad) {
this.edad = edad;
}
public String getPhoneNunmber() {
return phoneNunmber;
}
public void setPhoneNunmber(String phoneNunmber) {
this.phoneNunmber = phoneNunmber;
}
public String getUser_idp() {
return user_idp;
}
public void setUser_idp(String user_idp) {
this.user_idp = user_idp;
}
public ArrayList getPedido() {
return pedido;
}
public void setPedido(ArrayList pedido) {
this.pedido = pedido;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}
Here is my Controller code:
#Controller
public class GreetingController {
#GetMapping("/allusers")
public String greetingForm(Model model) throws ParseException{
tablausuario tu = new tablausuario();
ArrayList<usuario> user = tu.listausuarios();
Collections.sort(user, (o1, o2) -> o2.getCreatedAt().compareTo(o1.getCreatedAt())); //tabla ordenada
model.addAttribute("TodosLosUsuarios", user);
return "greeting";
}
#PostMapping("/allusers")
public String greetingSubmit(Model model, HttpServletRequest request, #ModelAttribute usuario users) {
String ciudad = request.getParameter("ciudad");
tablausuariofilterbycity tufc = new tablausuariofilterbycity();
ArrayList<usuario> userbycity = tufc.listausuariosfiltradosporciudad(ciudad);
model.addAttribute("TodosLosUsuarios", userbycity);
return "result";
}
}
And here is my HTML "greeting"
<div class="container">
<h2>Listado de usuarios </h2>
<p th:text=" ${TodosLosUsuarios.size()} "></p>
<div id="capa"> </div>
<h1>Form</h1>
<form action="#" th:action="#{/allusers}" th:object="${TodosLosUsuarios}" method="post">
<p>Message: <input type="text" th:field="*{ciudad}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Buscar por ciudad..">
<table id="myTable" class="table table-bordered">
<thead>
<tr>
<th>Nombre</th>
<th>Email</th>
<th>Teléfono</th>
<th>Día creado</th>
<th>Edad</th>
<th>Confirmado</th>
<th>Promocion</th>
<th>Direccion</th>
</tr>
</thead>
<tbody th:each="usuariosTotales: ${TodosLosUsuarios}" >
<tr>
<td th:text=" ${usuariosTotales.getNombre()} " ></td>
<td th:text=" ${usuariosTotales.getEmail()} " ></td>
<td th:text=" ${usuariosTotales.getPhoneNunmber()} " ></td>
<td th:text=" ${usuariosTotales.getCreatedAt()} " ></td>
<td th:text=" ${usuariosTotales.getEdad()} " ></td>
<td th:text=" ${usuariosTotales.getConfirmationCode()} " ></td>
<td th:text=" ${usuariosTotales.getPromotions()} " ></td>
<td th:text=" ${usuariosTotales.getAddress()} " ></td>
</tr>
</tbody>
</table>
</div>
</div>
I am sure that the problem is in the form:
<form action="#" th:action="#{/allusers}" th:object="${TodosLosUsuarios}" method="post">
<p>Message: <input type="text" th:field="*{ciudad}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
If instead of "user" I use "new usuario"
model.addAttribute("TodosLosUsuarios", user);
I use
model.addAttribute("TodosLosUsuarios", new usuario());
the form works but I am not able to read the ArrayList, and I get this error:
Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "greeting" - line 10, col 40)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 48 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "greeting" - line 10, col 40)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918)
at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleStandaloneElementEnd(TemplateHandlerAdapterMarkupHandler.java:260)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:256)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleStandaloneElementEnd(OutputExpressionInlinePreProcessorHandler.java:169)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:104)
at org.attoparser.HtmlElement.handleStandaloneElementEnd(HtmlElement.java:79)
at org.attoparser.HtmlMarkupHandler.handleStandaloneElementEnd(HtmlMarkupHandler.java:241)
at org.attoparser.MarkupEventProcessorHandler.handleStandaloneElementEnd(MarkupEventProcessorHandler.java:327)
at org.attoparser.ParsingElementMarkupUtil.parseStandaloneElement(ParsingElementMarkupUtil.java:96)
at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:706)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
... 50 more
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'ciudad' of bean class [java.util.ArrayList]: Bean property 'ciudad' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:622)
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:612)
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:158)
at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903)
at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:253)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227)
at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
... 63 more
I think the problem is your are using plain HTML (ie tag form) instead of the Spring JSP Form
<form:form method="POST" action="/todoslosusuarios"
modelAttribute="TodosLosUsuarios">
I think you are missing the proper tags for action in Thymeleaf and also the "post" method declaration.
<form action="#" th:action="#{/todoslosusuarios}" method="post">
this link covers the process end to end.
https://spring.io/guides/gs/handling-form-submission/

Form validation error messages not appearing as expected

<td th:if="${#fields.hasErrors('description')}" th:errors="*{description}" class="red">You must provide a reason for your request.</td>
<td th:if="${#fields.hasErrors('selectedDate')}" th:errors="*{selectedDate}" class="red">You must select a date.</td>
Why are these td being populated by the following messages instead of the messages I have provided above? They also don't take on the css class I provided.
may not be empty may not be empty
Request Entity:
public class RequestModel {
private Long requestId;
#NotNull
#NotBlank
private String selectedDate;
private RequestStatus requestStatus;
#NotNull
#NotBlank
private String description;
private Boolean hasForced;
public String getSelectedDate() {
return selectedDate;
}
public void setSelectedDate(String selectedDate) {
this.selectedDate = selectedDate;
}
public Long getRequestId() {
return requestId;
}
public void setRequestId(Long requestId) {
this.requestId = requestId;
}
public RequestStatus getRequestStatus() {
return requestStatus;
}
public void setRequestStatus(RequestStatus requestStatus) {
this.requestStatus = requestStatus;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Boolean getHasForced() {
return hasForced;
}
public void setHasForced(Boolean hasForced) {
this.hasForced = hasForced;
}
}
Controller:
#RequestMapping(value = "/save", method = RequestMethod.POST)
String saveRequest(Principal principal, #Valid #ModelAttribute(value = "requestModel") RequestModel requestModel, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
// log.info("There are binding errors.");
return "send";
}
...
}
The full HTML form:
<form role="form" th:action="#{/request/save}" th:object="${requestModel}" method="post">
<input type="checkbox" th:field="*{hasForced}" th:checked="${false}" style="display: none;"/>
<p><input id="description" class="descriptionField" type="text" th:field="*{description}"
placeholder="Please provide a reason for your request"
style="width: 500px; border-radius: 4px; padding: 11px 11px 11px 11px;"/></p>
<input id="embeddedDateField" class="dateField" placeholder="YYYY-MM-DD" type="text" th:field="*{selectedDate}" readonly
style="border-radius: 4px; background: #eefdff; text-align: center;"/><br>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<div style="margin: 5px; width: 200px;"><input type="submit" value="Submit Request"
style="display: block;"></div>
<td th:if="${#fields.hasErrors('description')}" th:errors="*{description}" class="red">You must provide a reason for your request.</td>
<td th:if="${#fields.hasErrors('selectedDate')}" th:errors="*{selectedDate}" class="ed">You must select a date.</td>
</form>
What's going on here?
These messages are coming from validation annotation default values. To set your own you need to provide them like below or you can change from properties file using MessageSource.
#NotNull(message="You must select a date.")
#NotBlank(message="You must select a date.")
private String selectedDate;

Spring mvc #RequestBody String format

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) {

Categories

Resources