Why i am unable to launch Thymeleaf Template with springboot application? - spring-boot

I am using IntelliJ IDEA community Edition 2020.1.2 x64 and written a program using Spring DataJPA and Thymeleaf,there is no problem with my code and i am not getting error but when i am passing URL which i mapped in controller class i am unable to get desired result i.e the thymeleaf template which i have created is not displayed on browser.
I am posting the controller class,thymeleaf template and output which i am getting on browser to make you clear:-
controller class:
#RestController
#RequestMapping("/ecommerce")
public class EmployeeController {
#Autowired
private ProductService productService;
#GetMapping("/available")
public String ShowAllProducts(Model model)
{
model.addAttribute("listProducts",productService.getAllProducts());
return "availableProducts";
}
}
Thymeleaf template:-
<!DOCTYPE html>
<html xmlns:th="html://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>AvailableProducts</title>
</head>
<body>
<div align="center">
<h1>Product List</h1>
<table>
<thead>
<tr>
<th>p_id</th>
<th>ProductName</th>
<th>Productcost</th>
<th>QuantityAvailable</th>
</tr>
</thead>
<tbody>
<tr th:each="product : ${listProducts}">
<td th:text="${product.productId}"></td>
<td th:text="${product.productName}"></td>
<td th:text="${product.productCost}"></td>
<td th:text="${product.quanityAvailable}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Output on browser:-
Dependency added:-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
application.properties:-
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce
spring.datasource.username=root
spring.datasource.password=deep
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto= update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.thymeleaf.prefix=classpath*:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.mode=HTML5
At last when i am passing url http://hocalhost:8080/ecommerce/available what i am seeing in console is,hibernate is accessing the database every time.
Thanks in advance..
Please help i am stuck and don't know what i am doing wrong and not able to figure out on my own..

In your case seems like controller is just returning string "availableProducts" and its not resolving as thymleaf template. you can just return some dummy name("availableProductsTest") and you will see same(availableProductsTest) on the web page.
Did you referred to sample https://spring.io/guides/gs/serving-web-content/
Sample code is available here .. git clone https://github.com/spring-guides/gs-serving-web-content.git
if you just add your product class and modify the Greetings contoller like below then you can see its working!
#GetMapping("/greeting")
public String greeting(#RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
List<Products> productList= new ArrayList<>();
Products product = new Products("productId","ProductName", "ProductCost", "ProductQtyAvlb");
productList.add(product);
model.addAttribute("listProducts",productList);
return "greeting";
}
Also modify greetings template as below
<!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 th:text="'Hello, ' + ${name} + '!'" />
<div align="center">
<h1>Product List</h1>
<table>
<thead>
<tr>
<th>p_id</th>
<th>ProductName</th>
<th>Productcost</th>
<th>QuantityAvailable</th>
</tr>
</thead>
<tbody>
<tr th:each="product : ${listProducts}">
<td th:text="${product.productId}"></td>
<td th:text="${product.productName}"></td>
<td th:text="${product.productCost}"></td>
<td th:text="${product.quanityAvailable}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Hope this Helps! Happy Coding
Web reference: https://spring.io/guides/gs/serving-web-content/
Whenever you get Whitelabel Error Page you will have details about error listed on same page also same details can be seen in server logs or on console of the application.
For example if i use wrong template name in controller then i see below:
2020-07-28 22:35:51.031 ERROR 19572 --- [nio-8080-exec-1] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8080-exec-1] Exception processing template "greeting1": Error resolving template [greeting1], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [greeting1], template might not exist or might not be accessible by any of the configured Template Resolvers
at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:869) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:607) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]

Related

ModelAttribute Doesn't return any value from front end to back end

I'm using spring boot and thymeleaf to create a form to collect the data from front-end and update the database at back-end. I'm having trouble to pass the object value by using ModelAttribute. I can almost guaranty my repository and my bean work fine because I have written Junit test case against it and I can see the update from DB. I tried to use th:field at the html page, but it doesn't give me any default value in the field, so I have to use th:value. The print out statements in the controller just keep return 0. It feels like (#ModelAttribute("city") CityBean city) just never pass any data into the variable city. I can't really tell where the problem is after hours of the debugging. I will attach my code here. Thank you very much for helping.
My bean:
public class CityBean {
int cityID;
int population;
String cityName;
String state;
My Repository/DAO:
public int updatePopulation(CityBean city) {
String sql = "UPDATE CITY SET population = ? WHERE cityID = ?";
Object[] args = {city.getPopulation(), city.getCityID()};
int[] types = {Types.VARCHAR, Types.INTEGER};
return jdbcTemplate.update(sql, args, types);
}
My controller:
#RequestMapping(value = "/action", method = RequestMethod.POST)
public String updatePopulation(#ModelAttribute("city") CityBean city) {
System.out.println("This is city ID " + city.getCityID());
System.out.println("This is city population " + city.getPopulation());
cityRepository.updatePopulation(city);
return "redirect:/cityInfo";
}
My Front-end HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>CS6400 Fall 2020 Team 017 Project</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
<h1 style="text-align:center">City Population Update Form</h1>
<br>
<form action="#" th:action="#{/action}" th:object="${city}" method="post" modelAttribute="city">
>
<table class="table">
<thead>
<tr>
<th scope="col">City ID</th>
<th scope="col">City Name</th>
<th scope="col">State</th>
<th scope="col">Population</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr >
<td><input type="text=" th:value="*{cityID}" readonly="readonly"></td>
<td><input type="text=" th:value="*{cityName}" readonly="readonly"></td>
<td><input type="text=" th:value="*{state}" readonly="readonly"></td>
<td><input type="text=" th:value="*{population}" ></td>
<td>
<button type="submit" class="btn btn-primary">Update Population</button>
</td>
</tr>
</tbody>
</table>
</form>
</body>
</html>
Problem solved, I added name="pramName" in the input tag then everything works fine.

How to Load Data From a Json Using Thymeleaf Template

I have a rest api returns a Json value as a Output of the service call.
eg:- https://localhost:8080/getEmployees/loadAll
this returns following json values
eg:-
{
"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]
}
I need to load the following json values to my thymeleaf table.
In normal way returning values in controller using modal in spring can retun values as list like following.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee List</title>
</head>
<body>
<h1>Welcome</h1>
<br>
<h3>Employee List</h3>
<br />
<table border="1">
<tr>
<td>Employee First Name</td>
<td>Employee Last Name</td>
</tr>
<tr th:each="emp : ${empList}">
<td th:text="${emp.firstName}">First Name</td>
<td th:text="${emp.name}">Last Name</td>
</tr>
</table>
</body>
</html>
is there a way to accomplish this using above json using thymeleaf?
You can do something like that using the following structure.
When you call the service
https://localhost:8080/getEmployees/loadAll
you will need to pass the employees data using model.addAttribute.
For instance, let's say you have the following method:
#RequestMapping(value="/getEmployees/loadAll")
String getAllEmployees(Model model) {
model.addAttribute("empList", <your service here that generates the data>);
return "pagenamehere";
}
The above method, will only be executed when you make a call using the following url: https://localhost:8080/getEmployees/loadAll
and it will add your empList data as an attribute. Then, the return string indicates the name of the page that will load. You will need to use your own page with the thymeleaf code.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee List</title>
</head>
<body>
<h1>Welcome</h1>
<br>
<h3>Employee List</h3>
<br />
<table border="1">
<tr>
<td>Employee First Name</td>
<td>Employee Last Name</td>
</tr>
<tr th:each="emp : ${empList}">
<td th:text="${emp.firstName}">First Name</td>
<td th:text="${emp.lastNname}">Last Name</td>
</tr>
</table>
</body>
</html>
Now, thymeleaf will be able to display the given data.
I think that you are a little confused. Thymeleaf templates are compiled on server side generating html code. Then, no thymeleaf code found on client side.
The json data got of the api response is generated on client side.
One way is use javascript to load the api response data into a html table.
Another way can you take is modify the controller that calls to the thymeleaf template to get the JSon value. If you store this response (on an object List named empList on your example) yo can add the object into the Controller response (Model or ModelAndView objects) as a template attribute.

Why is <c:forEach> not working with Ajax request in JSP Spring?

I am fetching some data with a Ajax request in my main JSP page.
Snippet of main.jsp
function gu(){
$.get('/admin/getAllUsers', {}, function(data) {
console.log(data); // see below
$("#allUsersData").html(data);
});
}
In my Spring controller I add all the users to a different JSP page.
Snippet of MainController.java
#RequestMapping(value = "/admin/getAllUsers", method = RequestMethod.GET)
public String getAllUsers(Model model){
List<User> users = userRepository.findAll();
System.out.println(users.size()); // output: 3
model.addAttribute("allUsers", users);
return "data/all-users";
}
Now in all-users.jsp I have a <c:forEach> which is supposed to load all users in a html table:
<table class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<c:if test="${not empty allUsers}">
<c:forEach items="${allUsers}" var="usr">
<tr>
<td>${usr.firstName}</td>
<td>${usr.lastName}</td>
<td>${usr.username}</td>
<td>${usr.creationDate}</td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
However, when I add the html coming from the request to my main JSP page, an empty table is shown. When I log the result of the Ajax request I find that the user data is inserted in the all-users.jsp:
<c:if test="true">
<c:forEach items="[User{id=1, username='username1', firstName='John', lastName='Doe', roles=[Role{id=1, name='ROLE_USER'}], creationDate=2018-02-19T08:58:13.333}, User{id=2, username='username2', firstName='John2', lastName='Doe2', roles=[Role{id=3, name='ROLE_USER'}], creationDate=2018-02-19T08:58:13.471}]" var="usr">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</c:forEach>
</c:if>
Why is it happening that the data is loaded into the data JSP page, but not shown when appending it to the main JSP page?
Can you check, maybe you haven't included the core tag library in your JSP file.
You will do this by inserting the following Line at the top of your file.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Howto integrate Jasper HTML Report in Spring View (Conceptional)

Howto integrate Jasper HTML Report in Spring View (Conceptional)
I would like to create a kind of dashboard in my Spring framework Application.
I have a view (jsp) and would like to include Jasper Report HTML/Pie Chart Image Output ( in my html sample) in a specific part of my produced HTML Page.
Is this possible to do ? If yes. Will the report be generated in the controller and sent to the view by ModelView ?
My View (dashboard.jsp) looks like this (sample):
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Key Figures</h2>
<table border=1 width=700>
<tbody>
<tr> <Navigation Items like Buttons and Tabs> </tr>
<tr height=200>
<td><c:forEach var="listValue" items="${lists}">
<li>${listValue}</li>
</c:forEach>
</td>
<td>Other Content from the Model</td>
</tr>
<tr height=200>
<td><My Pie Chart 1></td>
<td><My Pie Chart 2></td>
</tr>
</tbody>
</table>
</body>
</html>

recaptcha integration with Spring MVC

I am trying to integrate recaptcha into my spring mvc application. Below is the code.
#RequestMapping(value="home.htm", method=RequestMethod.POST)
public String processEmailLogin(
#ModelAttribute("examLoginForm") ExamLoginDetails examLoginDetails,
BindingResult result,
Model model,
#RequestParam("recaptcha_challenge_field") String challangeField,
#RequestParam("recaptcha_response_field") String responseField,
HttpServletRequest request, SessionStatus sessionStatus) {
ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
reCaptcha.setPrivateKey("6LcWOOsSAAAAAM48WFr4PfE0Y1LdTJHKC_BxILwl");
/*String challenge = request.getParameter("recaptcha_challenge_field");
String response = request.getParameter("recaptcha_response_field");*/
String remoteAddr = request.getRemoteAddr();
logger.info("Remote machine IP address is : "+remoteAddr);
String emailIdForm = request.getParameter("email");
ReCaptchaResponse reCaptchaResponse = reCaptchaService.checkAnswer(remoteAddr, challangeField, responseField);
logger.info("Shown captcha is : "+challangeField);
logger.info("Entered captcha is : "+responseField);
logger.info("The validated recaptcha response is : "+reCaptchaResponse.isValid());
boolean correctAnswer = false;
correctAnswer = challangeField.equalsIgnoreCase(responseField);
logger.info("Correct answer : "+correctAnswer);
logger.info(":::::: LOADED Login Form CONTROLLER ::::::");
if(!reCaptchaResponse.isValid()) {
model.addAttribute("message", "wrong captcha");
logger.info("Incorrect captcha");
return "login/login";
}
else {
logger.info("::::: Checking captcha response to validate :::::");
model.addAttribute("message", "correct captcha");
LoginService loginService = (LoginService) ctx.getBean("loginService");
examLoginDetails = loginService.performLogin(emailIdForm);
logger.info("Email id is ::::::::::: "+examLoginDetails.getEmailId());
return "home/home";
}
}
My JSP form is as follows:
<%# page import="net.tanesha.recaptcha.ReCaptcha" %>
<%# page import="net.tanesha.recaptcha.ReCaptchaFactory" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="./jsp/scripts/jquery-1.9.1.js"></script>
<script type="text/javascript" src="./jsp/scripts/jquery-ui-1.10.3.custom.min.js"></script>
<link rel="stylesheet" type="text/css" href="./jsp/styles/jquery-ui-1.10.3.custom.min.css" />
<link rel="stylesheet" type="text/css" href="./jsp/styles/page-style.css" />
<link rel="stylesheet" type="text/css" href="./jsp/styles/tooltip.css" />
</head>
<body>
<form action="home.htm" method="post" name="examLoginForm">
<fieldset class="ui-widget ui-widget-content ui-corner-all">
<legend class="ui-widget-header ui-corner-all">Online Examination</legend>
<table class="ui-widget ui-helper-clearfix">
<tr>
<td><label for="email">Please enter your Email Id : </label></td>
<td><input class="ui-widget-content ui-corner-all" type="text" id="emailId" name="email" title="Please provide the email id you used to register with us to take the exam." ></td>
</tr>
<tr>
<td></td>
<td>
<script type="text/javascript" src="http://www.google.com/recaptcha/api/challenge?k=PUBLIC_KEY"></script>
<noscript>
<iframe src="http://www.google.com/recaptcha/api/noscript?k=PUBLIC_KEY" height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge">
</noscript>
<%-- <%
ReCaptcha c = ReCaptchaFactory.newReCaptcha("PUBLIC_KEY","PRIVATE_KEY", false);
out.print(c.createRecaptchaHtml(null, null));
%> --%>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td><span id="LoginBtn"><input class="ui-helper-clearfix ui-corner-all ui-button ui-button-text ui-state-default ui-state-focus ui-state-active ui-state-hover" type="submit" id="login" value="Take Exam" /></span></td>
<td></td>
</tr>
</table>
</fieldset>
</form>
<div id="dialog" title="Confirm Your Email ID">
<p><span class="ui-widget ui-widget-content ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>Are you sure that this is the Email Id you have used to register yourself with us?</p>
</div>
</body>
</html>
The bean configuration in the spring application context is :
<bean id="reCaptchaService" class="net.tanesha.recaptcha.ReCaptchaImpl">
<property name="privateKey" value="PRIVATE_KEY" />
</bean>
The output i see on my console is :
13:12:56,875 INFO LoginFormController:58 - Remote machine IP address is : 10.129.75.57
13:12:57,078 INFO LoginFormController:63 - Shown captcha is : 03AHJ_VuuVrDXTjd0tBEkuONNedE6Bk214GxuOj7DT0o927e5HNgS_IKX7Efuc79liUvsH8VbKbZ7aZ8iElpJog6YqjsvThFu3BuULzPGEPHZKiIk_hnix6N_IXC3aDQaEcBDTPgooOuqs_CwriWe8PuxrzfbzDS2QdnhLuiWqIVqlX2KnZT9BZYo
13:12:57,078 INFO LoginFormController:64 - Entered captcha is : 44642526 2154
13:12:57,079 INFO LoginFormController:65 - The validated recaptcha response is : false
13:12:57,079 INFO LoginFormController:70 - Correct answer : false
13:12:57,079 INFO LoginFormController:71 - :::::: LOADED Login Form CONTROLLER ::::::
13:12:57,079 INFO LoginFormController:79 - ::::: Checking captcha response to validate :::::
What i see from the console output is that the recaptcha_challange_field contains the captcha question in some encripted form and the recaptcha_response_field contains the response for the captcha question in plain text form. So, is it the reason that the recaptcha checkAnswer(remoteAddr, challange, response) method is always evaluating to false?.
Please help me as i am stuck with this problem from a long time now.
For me recaptcha-spring-boot-starter was very helpful and reduces your code a lot:
https://github.com/mkopylec/recaptcha-spring-boot-starter-samples

Resources