Using ftl display list from POST method - java

Sorry for my english!
I am new to Spring and FTL.
I want to display firstName and lastName using <#list template, but I could not recognize any sequences in my POST method, could some one please explain to me. Again I am a newbie and please don't judge me if I don't understand what I should. I am using CUBA STUDIO 6.8 and IDEA. Also I'm working on this task in portal module
This is how I add firstName and lastName to database using my ftl form and Portal Controller:
#GetMapping("/add")
public String add(Model model){
PersonPojo personPojo = new PersonPojo();
model.addAttribute("personPojo", personPojo);
return "add";
}
#PostMapping("/add")
public String save(Model model, #ModelAttribute("personPojo") PersonPojo personPojo){
String firstName = personPojo.getFirstName();
String lastName = personPojo.getLastName();
PersonPojo newPerson = new PersonPojo(firstName, lastName);
Person standardEntity = metadata.create(Person.class);
standardEntity.setFirtName(newPerson.getFirstName());
standardEntity.setLastName(newPerson.getLastName());
dataManager.commit(standardEntity);
return "redirect:/allPersons";
}
My ftl form:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" name="person">
First Name: <input type="text" name="firstName"> <br>
Last Name: <input type="text" name="lastName"> <br>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
<input type="submit" value="Create">
</form></body>
</html>
Thank you!

So, If someone is interested i will post my solution here:
#RequestMapping(value = "/allPersons", method = RequestMethod.GET)
public String getPersons(Model model) {
LoadContext loadJohn = new LoadContext(John.class);
loadJohn.setQueryString("select u from test6$John u");
model.addAttribute("users", dataService.loadList(loadJohn));
return "list";
}
And the ftl should look like this:
The problem i faced next was I did not know I have to check list for null. !"" does that
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>Person List</h3>
Add Person
<br><br>
<div>
<table border="1">
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<#list users as show>
<tr>
<td>${show.firstName!""}</td>
<td>${show.lastName!""}</td>
</tr>
</#list>
</table>
</div>
</body>
</html>
I hope this will help to people like me.
Also, If someone knows how to delete and update data please share.
Thanks!

Related

How do i pass two th:object in a single form

I'm new to thymeleaf and couldn't found a way to pass two th:objects in a single HTML form. how can I pass two different entity objects.in this case, my entities are Patient and Doctor. My form is given below.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<title>LOG IN PAGE</title>
</head>
<body>
<div class="container">
<form th:action="#{/loggedProfile}" th:object="${patient,doctor}"
method="get">
<div class="form-group">
<label for="patientEmail">Email address</label> <input type="email"
class="form-control" placeholder="Enter Your email"
th:field="*{eMail}"> <small id="emailHelp"
class="form-text text-muted">We'll never share your email
with anyone else.</small>
</div>
<div class="form-group">
<label for="patientPassword">Password</label> <input type="password"
class="form-control" placeholder="Enter Your Password"
th:field="*{password}">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</body>
<div th:insert="Header-Footer/common_header_footer"></div>
</html>
Here is my controller, its raw.
#GetMapping("/logIn")
public String logIn(Model model) {
Patient patient = new Patient();
model.addAttribute("patient", patient);
Doctor doctor = new Doctor();
model.addAttribute("doctor", doctor);
return "UI-Pages/LogIn_Page";
}
#GetMapping("/loggedProfile")
public String loggedProfile(#ModelAttribute Doctor doctor,#ModelAttribute Patient patient,Model model) {
doctor = docRep.findByeMailAndPassword(doctor.geteMail(), doctor.getPassword());
patient = patRep.findByeMailAndPassword(patient.geteMail(), patient.getPassword());
model.addAttribute("doctor", doctor);
model.addAttribute("patient", patient);
return "Profile-Pages/Patient_Profile";
}
Thanks.
You create a new object that contains a Patient and a Doctor.
public class LoginForm {
private Patient patient;
private Doctor doctor;
// getters and setters
}
Then access the fields like this:
<form th:action="#{/loggedProfile}" th:object="${form}"
th:field="*{patient.eMail}"
....
th:field="*{doctor.password}"
</form>
Etc...
It is probably better to use a dedicated Data Transfer Object that maps to the fields in the form data:
public class LoginFormData {
private String email;
private String password;
}
Then transform from the Patient or Doctor entity into LoginFormData and back in your controller.
Side note:
Use th:method="post" in the form with a #PostMapping in the controller if it is the intention to use the form to change data
Having a method findByeMailAndPassword is not something that you should have. Passwords should be in the database in plain text, and it would be strange to try to find a certain user with its plain text password.

Bind a list of radio buttons with Spring and Thymeleaf

my problem is that I need to get the radio buttons that are selected in HTML file and use it in the PostMapping.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Do Test Excercise</title>
<script language="javascript">
</script>
</head>
<body>
<h1>Do Test Exercise</h1>
<form method="POST">
<span align="left" th:each="question : ${exercise.getQuestions()}">
<p valign="top" th:text="${question.text}">Text</p>
<tr align="left" th:each="solution : ${question.getSolutions()}">
<input width="5%" type="radio" th:name="${question.question_ID}" th:text="${solution.text}"
th:value="${solution.text}"/><BR>
</tr>
</span>
<input type="submit" value="Submit">
</form>
</body>
</html>
However I don't know how to get that values for the radio buttons and save it in a array of String
#GetMapping("doTest/{post}/{exercise}")
public String doTest(Model model, #PathVariable String exercise) {
model.addAttribute("exercise", exercisesDAO.getExerciseByType(exercise, "Test"));
return "exercise/doTestExercise";
}
#PostMapping("doTest/{post}/{exercise}")
public String doTest(#RequestParam(value = "solution") String[] solution, #PathVariable String post, #PathVariable String exercise, RedirectAttributes redirectAttributes) {
exercisesDAO.solve(exercise, solution, "admin", "Test");
redirectAttributes.addAttribute("post", post);
redirectAttributes.addAttribute("exercise", exercise);
return "redirect:/showMark/{post}/{exercise}";
}
Thanks
You need to change the name of your inputs from th:name="${question.question_ID}", to th:name="${'solution['+ question.question_ID + ']'}". After that, you need to change your controller, so that instead of an array of Strings, it will receive a HashMap, where you will get for each id, the chosen solution.
Form
<form method="POST" th:action="#{doTest/${post.id}/${exercise.id}}">
<span align="left" th:each="question : ${exercise.getQuestions()}">
<p valign="top" th:text="${question.text}">Text</p>
<tr align="left" th:each="solution : ${question.getSolutions()}">
<input width="5%" type="radio" th:name="${'solution['+ question.question_ID + ']'}" th:text="${solution.text}" th:value="${solution.text}"/><BR>
</tr>
</span>
<input type="submit" value="Submit">
</form>
Controller
#PostMapping("doTest/{post}/{exercise}")
public String doTest(#RequestParam(value = "solution") HashMap<String, String> solutions, #PathVariable String post, #PathVariable String exercise, RedirectAttributes redirectAttributes) { ... }

Not able to bind values from Thymeleaf based UI form to a controller in Spring Boot

My application is not able to bind a form value from an Thymeleaf + HTML based UI to a Spring Boot controller.
I am getting that value as null when I do a System.out.println into the controller.
index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<p>Get your greeting here</p>
<form action="/publishMessage" method="post">
<table>
<tr>
<th>CHARGE</th>
</tr>
<tr>
<td>
<textarea th:field="*{messageBody}" name="" cols="90" rows="40">
{
"firstname": "Jose",
"lastname": "Long"
}
</textarea>
</td>
</tr>
<tr>
<td><input type="submit" name="btnSubmit" value="Publish CHARGE message"></td>
</tr>
</table>
</form>
</body>
</html>
PublishMessageController.java
#Controller
public class PublishMessageController {
#PostMapping("/publishMessage")
public String publishMessage(Message message, BindingResult bindingResult, Model model) {
System.out.println("into the publishMessage method..........");
String messageBody = message.getMessageBody();
System.out.println("messageBody: " + messageBody);
return "result";
}
}
Message.java
import lombok.*;
#Data
#Getter
#Setter
#NoArgsConstructor
public class Message {
private String messageBody;
}
Output:
into the publishMessage method..........
messageBody: null
Your message never gets put into the model, so you can't use it as variable in your controller.
Spring model attributes
Handling the command object
BTW: The method shouldn't return "result" but the String of the message body.
Put your messageBody to model where you show your form:
#RequestMapping(value = "/showForm", method=RequestMethod.GET)
public String showForm(Model model) {
...
String messageBody = ...
model.addAttribute("messageBody", messageBody);
...
}
To use this in your view, add th:action and th:object to your form:
<form action="#" th:action="#{/publishMessage}" th:object="${messageBody}" method="post">
...
</form>
Now you're able to use it in your controller method via annotation in the parameters:
#PostMapping("/publishMessage")
public String publishMessage(#ModelAttribute(value="messageBody") String messageBody, BindingResult bindingResult, Model model) {
...
return messageBody;
}
You could do this with the whole message instead of the body, of course.
Based on the above input from SHEIX made some changes and it worked.
ShowFormController.java
#Controller
public class ShowFormController {
#RequestMapping(value = "/showForm", method = RequestMethod.GET)
public String showForm(Model model) {
model.addAttribute("message", new Message());
return "show";
}
}
show.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>
Go Back
</h3>
<form action="#" th:action="#{/publishMessage}" th:object="${message}" method="post">
<table>
<tr>
<th>CHARGE</th>
</tr>
<tr>
<td>
<textarea th:field="*{messageBody}" name="" cols="90" rows="40" style="background-color: beige">
</textarea>
</td>
</tr>
<tr>
<td><input type="submit" name="btnSubmit" value="Publish CHARGE message"></td>
</tr>
</table>
</form>
</body>
</html>
Message.java
import lombok.*;
#Data
#Getter
#Setter
#NoArgsConstructor
public class Message {
private String messageBody = "{\n" +
"\t\t\t\t\t\t\"name\": \"John\"\n" +
" }";
}
PublishMessageController.java
#PostMapping("/publishMessage")
public String publishMessage(#ModelAttribute(value = "messageBody") String messageBody, BindingResult bindingResult, Model model) {
System.out.println("into the publishMessage method..........");
System.out.println("messageBody: " + messageBody);
return "result";
result.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>
Thanks !!!
Go Back
</h3>
</body>
</html>

Why am I getting null object after submitting form in Spring?

I am new to Spring and yesterday I created a simple app. I type book's title, author and genre and it saves it to List<Book>. Book.java contains private fields (title, author, genre).
So creating books and saving them to list works fine. Also I can view all books I have added. So it works fine. But now I want to create and delete them. So I have BookService.java that can add and delete books.
BookService.java
private List<Book> allBooks = new ArrayList<>();
public List<Book> getAllBooks() {
return allBooks;
}
public void addBook(String title, String author, String genre) {
allBooks.add(new Book(title, author, genre));
}
public void deleteBook(Book book) {
allBooks.remove(book);
}
This is stuff in my controller to delete books
#GetMapping("/books/delete")
public String deleteBook(Model model) {
model.addAttribute("BookList", bookService.getAllBooks()); // Works fine
return "delete";
}
#PostMapping("/books/delete")
public String deletedBook(#ModelAttribute Book book, Model model) {
System.out.println(book.getTitle()); // null
bookService.deleteBook(book); // can't delete null so nothing happens to the list
model.addAttribute("deletedBook", book);
return "deletedBookResult";
}
delete.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<h2>Delete page</h2>
<div th:each="bookObj : ${BookList}"> <!-- BookList - all books I add using submit form -->
<form action="#" th:action="#{/books/delete}" th:object="${bookObj}" method="post"> <!-- I SEND bookObj -->
<input type="submit" th:value="${bookObj.title}"/> <!-- WORKS. I GET BOOK'S NAME ON THIS BUTTON-->
</form>
</div>
</body>
</html>
I use th:each="bookObj : ${BookList}". So bookObj is every book I add. That's why I use th:object=${bookObj}. There is a form for each book I added later. And it display's it's title on the button. But when I press it, I get null to IDEA's console and on webpage. Why?
Thank you in advance.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<h2 th:text=" 'You have just deleted' + ${deletedBook.title}"></h2>
<!-- You have just deleted null -->
</body>
</html>
You are not sending anything in your form. Add some hidden fields:
<div th:each="bookObj : ${BookList}">
<form action="#" th:action="#{/books/delete}" method="post">
<input type="hidden" th:name="genre" th:value="${bookObj.genre}"/>
<input type="hidden" th:name="author" th:value="${bookObj.author}"/>
<input type="hidden" th:name="title" th:value="${bookObj.title}"/>
<input type="submit" th:value="${bookObj.title}"/>
</form>
</div>
Or if you don't want to expose your data in html, you can try to use some sort of session objects instead (Probably an overkill, but sometimes can be useful):
#GetMapping("/books/delete")
public String deleteBook(Model model, HttpSession session) {
session.setAttribute("BookList", new Book[]{
new Book("Title", "Tom","genre"),
new Book("Title 2", "Jerry","genre2")}
);
return "delete";
}
#PostMapping("/books/delete")
public String deletedBook(HttpSession session, Integer id, Model model) {
Book[] books = (Book[]) session.getAttribute("BookList");
Book book = books[id];
System.out.println(book);
model.addAttribute("deletedBook", book);
return "deletedBookResult";
}
And use it like:
<div th:each="bookObj, iter : ${session.BookList}">
<form action="#" th:action="#{/books/delete}" method="post">
<input type="hidden" th:name="id" th:value="${iter.index}"/>
<input type="submit" th:value="${bookObj.title}"/>
</form>
</div>

JSP Display User Details not working at all

<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
<head>
<title>Mail Registration</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="newcss.css">
<link rel="text/javascript" href="validateForm.js">
</head>
<body>
<div id="container">
<div id="header">
<h1>Online Book Store Mailing Registration</h1>
</div>
<div id="content">
<div id ="leftSide">
<p>Welcome to the Online Book Store Registration.
In order to join our mailing list you must complete the form. Then press the Submit button.</p>
</div>
<div id="rightSide">
<h2>Thanks for joining our email list</h2>
<h3>Here is the information that you entered:</h3>
<%# page import="user.User" %>
<% User user = (User) request.getAttribute("User");%>
<table cellspacing="5" cellpadding="5" border="1">
<tr>
<th align="right">First Name:</th>
<th>${user.getFirstName}</th>
</tr>
<tr>
<th align="right">Last Name:</th>
<th>${user.getLastName}</th>
</tr>
<tr>
<th align="right">Town:</th>
<th>${user.getTown}</th>
</tr>
<tr>
<th align="right">Country:</th>
<th>${user.getCountry}</th>
</tr>
<tr>
<th align="right">Email Address:</th>
<th>${user.getEmailAddress}</th>
</tr>
</table>
</form>
<br />
</div>
</div>
<div id="footer">
<h2>xxx</h2>
</div>
</div>
</body>
</html>
This is my first time working with JSP, I have to display user details that have been added to database. I have been looking for some time now at other questions asked here about displaying details and I have not found an answer yet.
I have java class called User.java in user Package.
If anyone could point me where I went wrong I would be thankful.
I have this in my servlet
String firstName = request.getParameter("firstName");
String lastName = request.getParameter("lastName");
String town = request.getParameter("town");
String country = request.getParameter("country");
String emailAddress = request.getParameter("emailAddress");
// create the User object
User User = new User();
User.setFirstName(firstName);
User.setLastName(lastName);
User.setTown(town);
User.setCountry(country);
User.setEmailAddress(emailAddress);
MailDB.insert(User);
request.setAttribute("User", User);
String url = "/return_user_details.jsp";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(url);
dispatcher.forward(request, response);
I suppose that your User class is like this :
Class User {
private String firstName;
private String lastName;
private String country;
.
.
.
/*generating getters & setters*/
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
}
So the problem you're having is here ${user.getFirstName} this will never work unless your attribute is named getFirstName which I don't think you did so to solve this issue you simply have to :
replace
${user.getFirstName} with ${user.firstName} , generally use the attribute name and not the getters and setters methods name.

Categories

Resources