List doesn't show up on front end - java

I'm working on a problem where I have a program to manage course. I have to create a lesson with a teacher & student, although when I have added a lesson to the DB & want it to show up on the frontend website, although it's not happening.
Student & Teacher are working fine, after adding a new Student/Teacher it redirects to the main page & the new list is available.
Data is visible in SQL Workbench & I can see the records adding.
Could you advise why the list is not showing up in front end?
LessonController class:
#Controller
#RequiredArgsConstructor
#RequestMapping("/lessons")
public class LessonController {
private final LessonService lessonService;
private final TeacherService teacherService;
private final StudentService studentService;
#GetMapping
public String getLessonList(Model model){
model.addAttribute("lessons",lessonService.findAll());
return "lesson/list";
}
#GetMapping("/create")
public String getLessonCreateForm(Model model){
model.addAttribute("teachers", teacherService.findAll());
model.addAttribute("students", studentService.findAll());
return "lesson/form";
}
#PostMapping("/create")
public String createLesson(Lesson lesson,
#RequestParam("studentId") int studentId,
#RequestParam("teacherId") int teacherId) {
lessonService.save(lesson,studentId,teacherId);
return "redirect:/lessons";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lekcje</title>
</head>
<body>
<h1>Lekcje</h1>
</br>
<p2>dodaj</p2>
</br>
</br>
<table>
<thead>
<tr>
<th>ID</th>
<th>Student</th>
<th>Nauczyciel</th>
</tr>
</thead>
<tbody>
<tr th:each="lesson : ${lesson}">
<td th:text="${lesson.id}"></td>
<td th:text="${student.firstName} + ' ' + ${student.lastName}"></td>
<td th:text="${teacher.firstName} + ' ' + ${teacher.lastName}"></td>
</tr>
</tbody>
</table>
</body>
</html>
This is the desired output for the lessons front end is to display the lessons from the DB. Here is a screenshot of the students front end:

Try to add URL to #GetMapping annotation above getLessonList method, I believe it should be #GetMapping("lesson/list") or #GetMapping("lessons")

Related

Pass an instance of an object in each loop from thymeleaf html file to Spring controller

I have a problem with passing an instance of "threads" in each loop from thymeleaf to Spring controller using a submit button. I'm trying to solve this by using the annotation #ModelAttribute, but one more instance of MessageThread is creating.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" xmlns:form="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>Форум</title>
</head>
<body>
<form method="post">
<input type="text" name="header">
<input type="text" name="text">
<button name="newThread" type="submit">Создать тред</button>
</form>
<table>
<thead>
<tr>
<th> Тред </th>
<th> ОП пост </th>
</tr>
</thead>
<tbody>
<tr th:if="${threads.isEmpty()}">
<td colspan="2"> Нет доступных тредов </td>
</tr>
<div>
<th:block th:each="thread : ${threads}">
<td th:type="id"><span th:text="${thread.getId()}"></span></td>
<td><span th:text="${thread.getHeader()}"> Title </span></td>
<td><span th:text="${thread.getText()}"> Title </span></td>
<form th:object="${thread}" th:method="post">
<td><button name="inThread" type="submit">В тред</button></td>
</form>
</th:block>
</div>
</tbody>
</table>
</body>
</html>
I can't find a way to pass an instance of "threads" from thymeleaf. All that I want is to press Submit button and pass the ${thread} to "toThread" method.
My controller:
#Controller
public class ThreadController {
private final MessageService messageService;
#Autowired
public ThreadController(MessageService messageService) {
this.messageService = messageService;
}
#GetMapping("/")
public String showThreads(Model model)
{
model.addAttribute("threads", messageService.getThreads());
return "threads-view";
}
#PostMapping(value = "/", params = "newThread")
public String addThread(Model model,
#RequestParam("header") String header,
#RequestParam("text") String text)
{
model.addAttribute("threads", messageService.getThreads());
messageService.addThread(header, text);
return "redirect:/";
}
#PostMapping(value = "/", params = "inThread")
public String toThread(#ModelAttribute("thread") MessageThread thread) {
System.out.println(thread.getId() + " " + thread.getHeader());
return "redirect:/thread:";
}
}
MessageThread class:
package com.project.imageboard.model;
import java.util.ArrayList;
import java.util.List;
public class MessageThread {
private String header;
private String text;
private int id;
private List<Message> messages = new ArrayList<>();
public MessageThread(String header, String text) {
this.header = header;
messages.add(new Message(text));
this.text = text;
this.id = messages.get(0).getId();
}
public int getId() {
return id;
}
public String getText() {
return text;
}
public String getHeader() {
return header;
}
public List<Message> getMessages() {
return messages;
}
public void insertMessage(Message message){
messages.add(message);
}
}
I would be grateful for any help.
your controller seems to be ok, you are mapping a post request to "/" and expecting to receive a MessageThread object which has to be built from the content of the request, the problem is in the template: you are not sending the data in the request from the client to the server, so spring has no way to assign the correct values to a new instance of MessageThread.
If we take this block from your template:
<th:block th:each="thread : ${threads}">
<td th:type="id"><span th:text="${thread.getId()}"></span></td>
<td><span th:text="${thread.getHeader()}"> Title </span></td>
<td><span th:text="${thread.getText()}"> Title </span></td>
<form th:object="${thread}" th:method="post">
<td><button name="inThread" type="submit">В тред</button></td>
</form>
</th:block>
1) The form tag is missing the action attribute, try adding something like th:action="#{/}" to target your request mapping on the server side.
2) You are not sending the actual content of the thread object to the server, for this you have to add input tags with the name of the imput matching the name of the field in the MessageThread object you want to populate. Something like the following:
<input type="hidden" th:field="*{header}" />
<input type="hidden" th:field="*{text}" />
In this example th:field is creating the name and value attributes for the input tags so you don't need to do it manually.
To sum up, there is no way to pass an actual "instance" of an object from the html running in the client to the java app running on the server, you can only send data using HTTP and parse that data on the server. The ModelAttribute annotation is instructing Spring to inspect an object (MessageThread in this case) and find in the data sent through the request the matching values to populate the object.
Hope this helps.

Using ftl display list from POST method

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!

Spring mvc - How to use or send the same object in different controller?

Problem solved, thanks guys ;) I EDITED THE CODE, LOOK AT THE BOTTOM
I am a Spring newbie and I am a little bit confused about using an object I already created through different controller in Spring MVC. I wrote a simple project that allow user to insert some car's details(brand, model and license plate number) and to see the list of submitted records (plus a reset all action and a selective delete of a single record). Now I also want to edit the values of a record but things get tough for me..
VeicoloController.java
#Controller
#RequestMapping("/veicolo")
#SessionAttributes("veicoli")
public class VeicoloController {
#Autowired VeicoloValidator veicoloValidator;
#GetMapping({"", "lista"})
public String lista() {
return "/veicolo/lista_veicoli";
}
#GetMapping("inserisci_veicolo")
public ModelAndView inserisci(){
return new ModelAndView("veicolo/inserisci_veicolo", "modelVeicolo", new Veicolo());
}
#PostMapping("save")
public ModelAndView salvaVeicolo(#ModelAttribute("modelVeicolo") Veicolo veicolo, BindingResult bindingResult,Model model)
{
System.out.println("Veicolo = " + veicolo);
veicoloValidator.validate(veicolo, bindingResult);
if (bindingResult.hasErrors()){
return new ModelAndView("veicolo/inserisci_veicolo");
}
else{
Set<Veicolo> veicoli;
if (!model.containsAttribute("veicoli")){
veicoli = new HashSet<>();
model.addAttribute("veicoli", veicoli);
}
else{
veicoli = (Set<Veicolo>) model.asMap().get("veicoli");
}
veicoli.add(veicolo);
return new ModelAndView("veicolo/lista_veicoli");
}
}
Now, here there are my problematic Controllers:
I use this controller to edit the row, using the license plate number as unique element to retrieve that particular vehicle object and passing it by querystring from the jsp(i'll show it later). In this way i can show the vehicle attribute in the edit forms (and hiding the license plate number form that cannot be modified)
#GetMapping("modifica")
public ModelAndView modificaVeicolo(#RequestParam("targa")String targa, Model model){
Set<Veicolo> veicoli = (Set<Veicolo>)model.asMap().get("veicoli");
Veicolo veicoloMod = null;
for(Veicolo v:veicoli){
if(v.getTarga().equalsIgnoreCase(targa)){
veicoloMod = v;
break;
}
model.addAttribute(veicoloMod);
}
return new ModelAndView("veicolo/modifica_veicolo", "modelVeicolo", veicoloMod);
}
This is how I tried to do the update Controller, I really don't know how to use the object I got in the previous controller that give me (i suppose) all the information I need of the car
#PostMapping("update")
public ModelAndView updateVeicolo(#ModelAttribute("modelVeicolo")Veicolo veicolo, BindingResult bindingResult,Model model)
{
// Veicolo veicoloToUpdate = (Veicolo)model.asMap().get("veicoli");
veicoloValidator.validate(veicolo, bindingResult);
if (bindingResult.hasErrors())
{
return new ModelAndView("veicolo/modifica_veicolo");
}
else
{
Set<Veicolo> veicoli =(Set<Veicolo>)model.asMap().get("veicoli");
veicoli.add(veicolo);
}
return new ModelAndView("veicolo/lista_veicoli");
}
modifica_veicolo.jsp
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Modifica il veicolo</title>
</head>
<body>
<h1>Modifica il veicolo</h1>
<br>
<br>
<form:form method="POST" action="${pageContext.request.contextPath}/veicolo/update" commandName="modelVeicolo" ModelAttribute="modelVeicolo">
<table>
<tr>
<p class="errorLine">
<form:errors path="marca" cssStyle="color: #ff0000"/>
</p>
<td><form:label path="marca">Marca</form:label></td>
<td><form:input path="marca" /></td>
</tr>
<tr>
<p class="errorLine">
<form:errors path="modello" cssStyle="color: #ff0000"/>
</p>
<td><form:label path="modello">Modello</form:label></td>
<td><form:input path="modello"/></td>
</tr>
<td><form:input type="hidden" path="targa" value="${veicolo.targa}" /></td>
<tr>
<td colspan="3">
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
<br>
<br>
Torna alla Home
</body>
</html>
and lista_veicoli.jsp (from the list you can edit the record)
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lista veicoli</title>
</head>
<body>
<h1>Lista Veicoli</h1>
<br>
<br>
<c:if test="${veicoli == null || veicoli.isEmpty()}">
Nessun veicolo registrato.
</c:if>
<div> </div>
<table>
<thead>
<tr>
<th>| Marca </th>
<th>| Modello |</th>
<th> Targa |</th>
</tr>
</thead>
<c:forEach var="veicolo" items="${veicoli}">
<tr>
<td>
${veicolo.marca}
</td>
<td>
${veicolo.modello}
</td>
<td>
${veicolo.targa}
</td>
<td>
<a href="${pageContext.request.contextPath}/veicolo/modifica?targa=${veicolo.targa}" > modifica </a>
</td>
<td>
<a href="${pageContext.request.contextPath}/veicolo/rimuovi?targa=${veicolo.targa}" > elimina </a>
</td>
</tr>
</c:forEach>
</table>
<br>
<br>
<p>Torna alla Home |</p>
<p>Cancella Lista |</p>
<p>Inserisci un altro veicolo |</p>
</body>
</html>
I am stuck now, if I click on the update button nothing happen and I doubt that things can be done way too better than this. I need your help :'(
Also, sorry for the long post!
EDIT:
ok, i changed this controller and it seems to work, but only for the first record inserted!
#PostMapping("update")
public ModelAndView updateVeicolo(#ModelAttribute("modelVeicolo")Veicolo veicolo,
BindingResult bindingResult,Model model)
{
veicoloValidatorNoTarga.validate(veicolo, bindingResult);
if (bindingResult.hasErrors())
{
return new ModelAndView("veicolo/modifica_veicolo");
}
else
{
Set<Veicolo> veicoli =(Set<Veicolo>)model.asMap().get("veicoli");
Veicolo daInserire = veicolo;
Veicolo daRimuovere = null;
for(Veicolo v : veicoli)
{
if(v.getTarga().equalsIgnoreCase(veicolo.getTarga())){
daRimuovere = v;
break;
}
}
veicoli.remove(daRimuovere);
veicoli.add(daInserire);
}
return new ModelAndView("veicolo/lista_veicoli");
}
If i want to edit the second or more element of the set an exception occurs. It says "HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException: Model object must not be null".
In fact in the modificaVeicolo Controller at the line
for(Veicolo v:veicoli){
if(v.getTarga().equalsIgnoreCase(targa)){
veicoloMod = v;
break;
}
targa value is the correct value of the second or third(etc) car, but v has the value of the first car's license plate! In theory it should have the value of the selected car
...any suggestions?
Key Point::If you choose to use HashSet storing Objects,the Class has to override equals and hashcode!
1.Veicolo.java
Override equlas and hashcode
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Veicolo veicolo = (Veicolo) o;
return targa.equals(veicolo.getTarga());
}
#Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + getTarga().hashCode();
return result;
}
2.VeicoloController.updateVeicolo()
Update object By deleting and adding
#PostMapping("update")
public ModelAndView updateVeicolo(#ModelAttribute("modelVeicolo") Veicolo veicolo, BindingResult bindingResult,
Model model) {
// Veicolo veicoloToUpdate = (Veicolo)model.asMap().get("veicoli");
veicoloValidator.validate(veicolo, bindingResult);
if (bindingResult.hasErrors()) {
return new ModelAndView("veicolo/modifica_veicolo");
} else {
Set<Veicolo> veicoli = (Set<Veicolo>) model.asMap().get("veicoli");
if (veicoli.contains(veicolo)) {
veicoli.remove(veicolo);
veicoli.add(veicolo);
}
}
return new ModelAndView("veicolo/lista_veicoli");
}
3.VeicoloController.modificaVeicolo()
Move the model.addAttribute into the loop
#GetMapping("modifica")
public ModelAndView modificaVeicolo(#RequestParam("targa") String targa, Model model) {
Set<Veicolo> veicoli = (Set<Veicolo>) model.asMap().get("veicoli");
Veicolo veicoloMod = null;
for (Veicolo v : veicoli) {
if (v.getTarga().equalsIgnoreCase(targa)) {
veicoloMod = v;
model.addAttribute(veicoloMod);
break;
}
}
return new ModelAndView("veicolo/modifica_veicolo", "modelVeicolo", veicoloMod);
}

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.

How to populate a simple table with thymeleaf in spring mvc

I have a list of objects and I want to display the values of those objects in a table using thymeleaf, this is what I have so far:
Here is my controller class that adds my list of objects:
#RequestMapping(value = "/showTableWithValues", method = RequestMethod.GET)
public String showTableWithValues(Model model)
{
//list with Persons
ArrayList<Persons> personsList=
new ArrayList<Persons>();
personsList= this.getListOfPersons();
model.addAttribute("list", personsList);
return "showTableWithValues";
}
This is my .html file where i want to show my values:
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>
Show Values
</h1>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Cost</th>
<th>Mins to prepare</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr th:each="persons : ${list}">
</tr>
</tbody>
</table>
</body>
</html>
And my Person.java class:
public class Person {
private String name;
private String last_name;
private String nickname;
.....get,setters and constructor
}
You are missing your <TD> tags providing the template which fields to print where. See the Iteration Basics of the documentation
Add <td> tags under <th> and then use the <td th:text="${persons.ID}"></td> respectively to display the relevant data in the table.

Categories

Resources