Data not showing in my another Html table after submitting. I am using spring mvc with thymeleaf, what might be the reason - spring

I added thymeleaf object and variable expressions in html and written #Getmapping and #postmapping methods and separate pojo class. after submitting the data using form.html file it going to another grades.html file but data is not showing what might be the issue.
controller program
#Controller
public class piperscontroller {
List<piedpiper> addGrades= new ArrayList<>();
#GetMapping("/")
public String submitForm(Model model){
model.addAttribute("grades",new piedpiper());
return "form";
}
#PostMapping("/handleSubmit")
public String grademeth(piedpiper grades){
addGrades.add(grades);
return "redirect:/grades";
}
#GetMapping("/grades")
public String finalButton(Model model){
model.addAttribute("grades",addGrades);
return "grades";
}
}
<!DOCTYPE HTML>
<html>
<head>
<title>Form</title>
<link th:href="#{/css/form.css} " rel="stylesheet">
</head>
<body>
<div class="topnav">
<a>Form</a>
<a>Grades</a>
</div>
<div class="container">
<h2> Grade Portal </h2>
<form method="post" th:object="${grades}" th:action="#{/handleSubmit}">
<input type="text" placeholder="Name" th:field="*{name}" >
<input type="text" placeholder="Score" th:field="*{score}">
<input type="text" placeholder="Subject" th:field="*{subject}">
<br><br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>

Related

View and controller data exchange

I'm using form tag to get information of title and content.
But I can't get any information from form tag.
It happens to me several time. I don't know what is the problem..
this is the controller code
#Slf4j
#Controller
#RequiredArgsConstructor
public class PostController {
private final PostRepository postRepository;
private final MemberService memberService;
#GetMapping("/board/upload")
public String moveToUploadPage(Model model) {
model.addAttribute("uploadPostForm", new UploadPostForm());
return "board/uploadForm";
}
#PostMapping("/board/upload")
public String updateBoard(#ModelAttribute UploadPostForm uploadPostForm, Authentication authentication, Model model) {
log.info("uploadPostForm.title = {}", uploadPostForm.getTitle());
Member member = findMember(authentication);
Post post = new Post(member, uploadPostForm.getTitle(), uploadPostForm.getContent());
postRepository.save(post);
return "/board/board";
}
}
this is html code
<!DOCTYPE html>
<html lang="kr" xmlns:th="http://www.thymeleaf.org">
<head th:insert="~{fragment/header :: header}">
<meta charset="utf-8">
</head>
<body>
<div th:replace="~{fragment/navbar :: nav}"></div>
<!-- Form Tag -->
<form th:action th:object="${uploadPostForm}" method="post" class="container-md">
<div class="m-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" th:field="*{title}">
</div>
<div class="m-3">
<label for="content" class="form-label">Text Area</label>
<textarea class="form-control" id="content" rows="10" th:field="*{content}"></textarea>
</div>
<div class="container" style="text-align: right">
<span class="m-3" th:text="|writer: | + ${#authentication.getName()}"></span>
<button type="submit" class="btn btn-primary">upload</button>
</div>
</form>
</body>

Cannot connect Thymeleaf HTML webpage to my Spring Boot API/DB

I have a Spring Boot application for a school records management system. My API is working perfectly when using Insomnia but I cannot get my hTML webpage to interact with the API. Here are the relevant bits of my Staff entity/controller/repository/service. Any help appreciated!
Entity class:
#Entity
#Data
#Embeddable
#NoArgsConstructor
#AllArgsConstructor
#Builder
#ToString
public class Staff {
#Id
#SequenceGenerator(
name = "STAFF_SEQ",
sequenceName = "STAFF_SEQ",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "STAFF_SEQ"
)
private Long staffId;
private String firstName;
private String lastName;
private String staffEmail;
#ManyToOne(targetEntity = Department.class)
private Long departmentId;
private String address;
private String contactNumber;
private char gender;
}
...
}
Controller Class
#RestController
public class StaffController {
#Autowired
private StaffService staffService;
#RequestMapping(value = "/saveStaff")
public Staff saveStaff(Staff staff) {
return staffService.saveStaff(staff);
}
...
}
Repository Class
#Repository
public interface StaffRepository extends JpaRepository<Staff, Long> {
Staff findByFirstNameAndLastName(String firstName, String lastName);
}
Service Interface
public interface StaffService {
public Staff saveStaff(Staff staff);
...
}
ServiceImpl
#Service
public class StaffServiceImpl implements StaffService{
#Autowired
StaffRepository staffRepository;
#Override
public Staff saveStaff(Staff staff) {
return staffRepository.save(staff);
}
...
}
HTML file
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<h2>Add Staff</h2>
<form action = "#" method="post" th:action ="#{/saveStaff}" th:object = "${staff}">
<fieldset>
<legend>Staff</legend>
<label for="firstName">First name:</label><br>
<input type="text" th:field ="*{firstName}" class="form-control" id="firstName" name="firstName"><br><br>
<label for="lastName">Last name:</label><br>
<input type="text" th:field ="*{lastName}" class="form-control" id="lastName" name="lastname"><br><br>
<label for="staffEmail">Staff email:</label><br>
<input type="staffEmail" th:field ="*{staffEmail}" class="form-control" id="staffEmail" name="staffEmail"> <br><br>
<label for="address">Address</label><br>
<input type="text" th:field ="*{address}" class="form-control" id="address" name="address"><br><br>
<label for="contactNumber"> Contact number</label><br>
<input type="text" th:field ="*{contactNumber}" class="form-control" id="contactNumber" name="contactNumber"><br><br>
<label for="gender">Gender:</label>
<select th:field ="*{gender}" class="form-control" id="gender" name="gender">
<option value="f">F</option>
<option value="m">M</option>
</select><br><br>
<label for="departmentId"> Department Id</label><br>
<input type="number" th:field ="*{departmentId}" class="form-control" id="departmentId" name="departmentId"><br><br>
<input type="submit" value="Submit">
<input type="reset">
</fieldset>
</form>
</body>
</html>
Your controller class is a #RestController. From view page you need to call the rest controller by using XmlHttpRequest or we can say, Ajax request or fetch API. For your ease, you can try jQuery. If you really want to submit your form the Thymeleaf way, then your controller needs to be a MVC Controller. Long story short, you should replace the annotation #RestController with #Controller. Also remove the action attribute and keep only th:action.
Your Controller class
#Controller
#RequestMapping("/course")
public class CourseController {
#Autowired
CourseService courseService;
#GetMapping("/add")
public String get_saveCourseForm(Model model) {
Course course = new Course();
model.addAttribute("course", course);
return "saveCourse";
}
#PostMapping("/save")
public String post_saveCourseForm(#ModelAttribute("course") Course course, Model model) {
courseService.saveCourse(course);
var courses = courseService.fetchCourseList();
model.addAttribute("courses", courses);
return "displayCourses";
}
}
Replaced #RestController with #Controller annotation
Add MVC methods and return view page names from the MVC methods. Also notice the request mappings. We will view the form by calling /course/add and the form will be submitted to /course/save.
Your Form Page
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<h2>Add Course</h2>
<form method="post" th:action ="#{/course/save}" th:object = "${course}">
<fieldset>
<legend>Staff</legend>
<label for="courseName">Course name:</label><br>
<input type="text" th:field ="*{courseName}" class="form-control" id="courseName" name="courseName"><br><br>
<label for="courseCode">Course code:</label><br>
<input type="text" th:field ="*{courseCode}" class="form-control" id="courseCode" name="courseCode"><br><br>
<label for="departmentId"> Department Id</label><br>
<input type="number" th:field ="*{departmentId}" class="form-control" id="departmentId" name="departmentId"><br><br>
<input type="submit" value="Submit">
<input type="reset">
</fieldset>
</form>
</body>
</html>
Check the form action.
The page will look like below.
When the form will be submitted, it will return the result page. the HTML code is as follows.
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Display Courses</title>
</head>
<body>
<table>
<tr>
<th>Course ID</th>
<th>Course Name</th>
<th>Course Code</th>
</tr>
<tr th:each="course : ${courses}">
<td><span th:text="${course.courseId}"></span></td>
<td><span th:text="${course.courseName}"></span></td>
<td><span th:text="${course.courseCode}"></span></td>
</tr>
</table>
</body>
</html>
The page will look as follows.

How to fill List<string> field in Thymeleaf + Spring

here is my form
<!--destinationList List-->
<div class="form-group">
<div class="col-sm-3">
<label for="Destination">Destination</label>
</div>
<div class="col-sm-9">
<input type="text" class="form-control" th:field="*{destinationList[0]}" />
<input type="text" class="form-control" th:field="*{destinationList[1]}" />
<input type="text" class="form-control" th:field="*{destinationList[2]}" />
<input type="text" class="form-control" th:field="*{destinationList[3]}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-9">
<button type="submit" class="btn btn-primary btn-block">Calculate</button>
</div>
</div>
</form>
And I'm going to fill following model
public class PriceSearchDTO {
private List<String> destinationList;
public List<String> getDestinationList() {
return destinationList;
}
public void setDestinationList(List<String> destinationList) {
this.destinationList = destinationList;
}
}
I can do this. But I hard coded number of input fields in the list as above in the view. I need to genarate them dynamically and make the number of element in the list is airbitary.
Try this:
<div class="col-sm-9">
<input type="text" class="form-control" th:each="destination : ${destinationList}" th:field="*{destination}" />
</div>
You are using Iteration in Thymeleaf. In fact, there is a quite complete set of objects that are considered iterable by a th:each attribute.
Like this :
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all"
href="../../../css/gtvg.css" th:href="#{/css/gtvg.css}" />
</head>
<body>
<h1>Product list</h1>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="destination: ${destinations}">
<td th:text="${destination}">Onions</td>
</tr>
</table>
<p>
Return to home
</p>
</body>
</html>
And Controller in Spring framework.
#RequestMapping(value = "/")
public ModelAndView showView(ModelAndView mav) {
List<String> destinations = new ArrayList<String>();
destinations.add("elementA");
destinations.add("elementB");
destinations.add("elementC");
mav.addObject("destinations", destinations);
mav.setViewName("/viewName");
return mav;
}

Spring MVC with Spring Boot: form tag error - equal symbol expected

I am trying to fill a form with values provided by the controller using tags in an app built with spring boot. But I get an error:
org.apache.jasper.JasperException: /WEB-INF/jsp/index.jsp (line: 52, column: 102) equal symbol expected
related part of index.jsp:
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<title><spring:message code="title.main" /></title>
</head>
<body>
<%#include file="include/navbar.jsp" %>
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-sm-offset-0 col-md-8 col-md-offset-2 main">
<div class="panel panel-default">
<div class="panel-body">
<form:form method="get" id="indexForm" commandName="indexForm" action="<c:url value="index_search" />" role="form">
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label for="city_out"><spring:message code="label.index.0" /></label>
<input:input type="text" class="form-control" id="city_out" path="city_out" />
</div>
<div class="form-group">
<label for="city_in"><spring:message code="label.index.1" /></label>
<form:input type="text" class="form-control" id="city_in" path="city_in" />
</div>
<div class="form-group">
<label for="company"><spring:message code="label.index.2" /></label>
<form:input type="text" class="form-control" id="company" path="company" />
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="date0"><spring:message code="label.index.3" /></label>
<form:input type="datetime" class="form-control" placeholder="dd.MM.yyyy [HH:mm]" id="date0" path="date0" />
</div>
<div class="form-group">
<label for="date1"><spring:message code="label.index.4" /></label>
<form:input type="text" class="form-control" placeholder="dd.MM.yyyy [HH:mm]" id="date1" path="date1" />
</div>
<div class="form-group" align="right">
<br />
<button type="submit" id="search_btn" data-loading-text="Loading..." class="btn btn-primary">Search</button>
</div>
</div>
</div>
</form:form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
I have created a class to match form fields:
public class IndexForm {
private String city_out;
private String city_in;
private String company;
private String date0;
private String date1;
// getters, setters
}
And created a bean in main class (I hope so):
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Bean
public static IndexForm indexForm() {
return new IndexForm();
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Controller contains this method:
#RequestMapping("/index")
public String index(#RequestParam(value="e", required=false) List<Integer> errors, Map<String, Object> model) {
model.put("indexForm", new IndexForm());
if (errors != null)
model.put("errors", errors);
return "index";
}
I don't see any differences from examples I have seen, so I would be happy if someone pointed at my mistake.
some newbies do a mistake by making the field as required in order to validate the field is filled or not
e.g in normal html -
input type="text" name="name" required
in spring - form:input path="firstName" required .... here required will not work and so same type of error "equal symbol expected".
Oh. It seems, including jsp tags one in another doesn't work. So, I changed
action="<c:url value="index_search" />"
for
action="index_search"
and received my page without errors.

Spring ModelAttribute nullPointerException

these are my controllers:
#RequestMapping(value="/requestBooking", method = RequestMethod.GET)
#ModelAttribute("booking")
public ModelAndView requestBooking(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ModelAndView view = new ModelAndView("requestBooking");
OAuthAuthenticationToken token = (OAuthAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if(token.getUserProfile().getAttributes().get("email").toString().matches(".*#nisum.com")==false){
SecurityContextHolder.clearContext();
return new ModelAndView("redirect:/j_spring_security_logout?redirectTo=/rejected");
}
VacationBooking booking=new VacationBooking();
String email=token.getUserProfile().getAttributes().get("email").toString();
User user=userImp.getUserByMail(email);
booking.setUser(user); //setting user
System.out.println(booking.getBookingId() + " - " + booking.getUser().getUserId());
view.addObject("booking", booking);
view.addObject("user", token.getUserProfile().getAttributes().get("email"));
return view;
}
#RequestMapping(value="/requestBooking/process", method=RequestMethod.POST)
public ModelAndView addBooking(#ModelAttribute("booking") VacationBooking booking , BindingResult result) {
/* val.validate(booking, result);*/
/* if(result.hasErrors()){
System.out.println("Error!!!!");
ModelAndView modelAndView = new ModelAndView("requestBooking");
return modelAndView;
}else{ */
SimpleMailMessage email2 = new SimpleMailMessage();
SimpleMailMessage emailPm = new SimpleMailMessage();
emailPm.setTo(booking.getUser().getMail()); //error here null value
email2.setTo(booking.getUser().getManager().getMail()); //error here, null value
email2.setSubject("Vacation Request");
emailPm.setSubject("Vacation Request");
emailPm.setText("<h3>Vacation Request<h3>\nThe employee has requested Vacation days between for leave. \n \n Please take action to approve or reject this request. \n \n To review, approve or reject the request, log into SaS, click Vacation Booking and click in Pending Approval link. \n \nNOTE: This is an Automated E-mail generated from the SaS mail process. Please do not reply to this E-mail. Vacation days Request Pending Approval");
email2.setText("<h3>Vacation Request<h3>\nYour vacation days request has been routed to your manager for approval. \n \nNote: If these dates should change, it is your responsibility to notify the appropriate people or withdraw your request in case you won't take those days.\n \nTo review, withdraw or modify your request, log into SaS, click Vacation Booking and check the current status or your Request. \n \nNOTE: This is an Automated E-mail generated from the SaS mail process. Please do not reply to this E-mail. Vacation days Request Routed for Approval");
mailSender.send(email2);
mailSender.send(emailPm);
System.out.println(booking.getFromDate());
bookingService.saveVacationBooking(booking);
ModelAndView modelAndView = new ModelAndView("myBookings");
String message = "the vacation booking was added!";
modelAndView.addObject("message", message);
return modelAndView;
}
and this is my view:
<!doctype html>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html class="no-js" lang="en">
<head>
<title>Vacation booking</title>
<link href="/vacation/resources/bootstrap-3.0.3/css/bootstrap.min.css" rel="stylesheet"/>
</head>
<!--Booking Form-->
<body>
<jsp:include page="../../templates/PageHeader.jsp" />
<form:form method="POST" style="width:800px;" commandName="booking" action="${pageContext.request.contextPath}/requestBooking/process" class="form-horizontal">
<div class="container">
<div class="row">
<div clas="col-md-12"><h4>Vacation Booking Form</h4></div>
<hr>
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">From:</label>
<div class="col-sm-6">
<form:input type="date" path="fromDate" class="form-control"></form:input>
<form:hidden path="user.userId" class="form-control"/>
<form:hidden path="bookingId" class="form-control"/>
<!--<input type="date" class="form-control"/> -->
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">To:</label>
<div class="col-sm-6">
<form:input type="date" path="toDate" class="form-control"></form:input>
<!-- <input type="date" class="form-control"/> -->
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Comments:</label>
<div class="col-sm-6">
<form:textarea path="comments" rows="4" class="form-control" placeholder="Fill this field if you have any comments related to your request"/>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-sm-6">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
</div>
</form:form>
<jsp:include page="../../templates/PageFooter.jsp" />
<script src="/vacation/resources/js/jquery-2.0.3.min.js" type="text/javascript"></script>
<script src="/vacation/resources/bootstrap-3.0.3/js/bootstrap.min.js" type="text/javascript"></script>
</body>
</html>
When I try to do booking.getUser().getMail() I get null. It is like my "booking" object is null in my post method. Any idea of how I can get my booking with the user object inside in my post controller, so I can call the getUser() method?

Resources