Thymeleaf didn't see objects from Spring - java

My template do not see objects, passed from Spring.
My code:
public class PublicModelAndView extends ModelAndView {
#Autowired
TemplateModulesHandler templateModulesHandler;
public void init() {
setViewName("index");
CSSProcessor cSSProcessor = new CSSProcessor();
cSSProcessor.setSiteRegion("public");
super.addObject("CSSProcessor", cSSProcessor);
JSProcessor jSProcessor = new JSProcessor();
super.addObject("JSProcessor", jSProcessor);
templateModulesHandler.setPublicModelAndView(this);
}
}
Contoller's code:
#SpringBootApplication
#Controller
public class IndexPage {
#Autowired
PublicModelAndView publicModelAndView;
#Autowired
OurServicesBean ourServicesBean;
#Autowired
PortfolioBean portfolioBean;
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView indexPage() {
publicModelAndView.setTemplate("publicSiteIndexPage");
publicModelAndView.addObject("pageTitle", "TITLE!!!!!!!!!!!!!!");
publicModelAndView.addObject("ourServices", ourServicesBean.getMenu());
publicModelAndView.addObject("portfolioWorkTypes", portfolioBean.getWorkTypes());
publicModelAndView.addObject("portfolioWorks", portfolioBean.getWorks());
return publicModelAndView;
}
}
Main template's code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
>
<head th:include="headerAndFooter/fragments/header :: publicSiteHeader">
<title></title>
</head>
<body>
hello!
</body>
</html>
Fragment's code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head th:fragment="publicSiteHeader">
<title>${pageTitle}</title>
<!--[if lte IE 8]>
<script src="<?= SITE_TEMPLATE_PATH ?>/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
</body>
</html>
As result I do not see value of the object pageTitle, but I see in page output code like
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>${pageTitle}</title>
Why thymeleaf didn't paste value of the pageTitle to between title tag's open and close?
The same code works good with JSP, but do not work with thymeleaf.

Thymeleaf is not JSP, so that's why your template does not work as you expect.
Look here http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#using-texts and use something like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<title th:text="#{pageTitle}">page title</title>
Edited - my solution is for localised texts which is good practice anyway. if you want to use content of variable than use $.

Related

Parsing string into an HTML file and recovering it with a #GetMapping

I've created a project with a Spring Initilizr. I'm trying to parse a string into a "code.html" file and recover it with a #GetMapping. Here's the file:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Code</title>
</head>
<body>
<pre>
<p th:text="${code}">
</pre>
</body>
</html>
And here's the method:
#GetMapping("/code")
public ModelAndView getHTML(HttpServletResponse response) {
response.addHeader("Content-Type", "text/html");
ModelAndView model = new ModelAndView();
model.addObject("code", code.getCode());
model.setViewName("code.html");
return model;
}
(I have a seperate class for the code so code.getCode() just returns a string.)
Unfortunately, http://localhost:8080/code returns an empty screen. What am I doing wrong? Maybe there's an easier way to achieve the task?
i work with springboot and thymeleaft
maybe you need send only the view in the code
like this
#GetMapping("/code")
public ModelAndView getHTML(HttpServletResponse response,Model model) {
model.addAtributte("key", "code");
return new ModelAndView ("templates/code");
}
the model is shipped with the view
in the html try this
<p th:text="${key}">
or you can try the <th:block>
check thymeleaf documentation

How to get data from data model via constant

I am using Spring boot and Thymeleaf as a template framework. I set a couple constants on the backend and I need to get data on the frontend via that constants.
I have the backend look like the following:
public class Constant {
public static final String MY_VAR = "test";
}
#Controller
public class MyController {
#GetMapping("/")
public String home(Model model) {
List<String> data = new ArrayList<>();
data.add("item1");
model.addAttribute(Constant.MY_VAR, data);
return "home";
}
}
and on the frontend I want to do like this:
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
...
</head>
<body>
<div class="container-fluid p-0">
<div th:unless="${not #lists.isEmpty(Constant.MY_VAR)}">
</div>
</div>
</body>
</html>
how can I get access to model data via constant from the backend?
You can use **ModelAndView ** to solve this problem
backend
#GetMapping("/")
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("home");
List<String> data = new ArrayList<>();
data.add("item1");
modelAndView.addObject("test", data);
return modelAndView;
}
frontend
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
...
</head>
<body>
<div class="container-fluid p-0">
<div th:if="${test.size() > 0}">
<li th:each="item:${test}">
<span th:text="${item}"></span>
</li>
</div>
</div>
</body>
</html>
if u want get static attribute in your view。
you can do that
${T(packageName.Constant).MY_VAR}
so u can change your code
${not #lists.isEmpty(Constant.MY_VAR)}
to
${not #lists.isEmpty(#ctx.getVariable(T(packageName.Constant).MY_VAR))}

Using hibernate and tapestry JAVA

I have problem with Tapestry 5. When i try to delete user from an table which have action link on cell it wont delete that user, it delete always last user that is on table... here is my code :
ViewAllUsers.java
public class ViewAllUsers {
#Inject
private Session session;
#Property
#SessionState
private User loginUser;
#Property
#Persist
private User user;
public List<User> getAllUsers() {
return session.createCriteria(User.class).list();
}
#CommitAfter
void onActionFromIzbrisi() {
session.delete(user);
}
}
ViewAllUsers.tml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title></title>
</head>
<body>
<t:Alerts />
<t:Grid t:source="allusers" t:add="Izbrisi,Edit" t:row="user">
<p:izbrisiCell>
<t:actionlink t:id="izbrisi" t:context="user">Delete</t:actionlink>
</p:izbrisiCell>
<p:editCell>
<t:PageLink t:page="EditUser" t:id="edit" t:context="user"> Edit </t:PageLink>
</p:editCell>
<p:deleteOptionCell>
</p:deleteOptionCell>
</t:Grid>
</body>
</html>
EDIT:
All i had to do here is to pass an parameter(Object or ID) in constructor of method for deleting files.
Just replaced
#CommitAfter
void onActionFromIzbrisi() {
session.delete(user);
}
with:
#CommitAfter
void onActionFromIzbrisi(User user) {
session.delete(user);
}
I don't think you can just pass your User instance in the t:context directly like that. A generic object instance cannot be passed between client and server directly. You will have to pass some kind of reference to your instance - usually an id - that your onActionFromIzbrisi() method can use to retrieve the actual object.
According to the doc for ActionLink the t:context attribute represents
The context for the link (optional parameter). This list of values
will be converted into strings and included in the URI.
That doc page also shows an example of how to pass an object.

PrintWriter output to jsp page inside body tag

This is the code to print to my jsp page. However I have other code in the page. When I call this function I want it to print the message right after where it is called. I can't check for sure because I am using xhtml negotiation, but I suspect it prints after the /html tag.
This is my function
public Print(HttpServletRequest request,HttpServletResponse response){
try{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<p>haha</p>");
}catch(IOException e){
e.printStackTrace();
}
}
};
This is where I call it
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Register</title>
</head>
<body>
<%# page import="com.otrocol.app.*" %>
<%
Print(request, response);
%>
</body>
</html>
This is what I think the result is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Register</title>
</head>
<body>
</body>
</html>
"haha"
This is what I want the response to be:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Register</title>
</head>
<body>
"haha"
</body>
</html>
This is the error I get:
The JSP uses its own PrintWriter, the JspWriter out. So pass this to the (static) function.
Otherwise you are taking a second writer, and with buffering everything goes haywire.
Also as output already did happen do not set the content type in the function.
At the top of the JSP is a nice location, also for the imports.
<%#page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
When having one writer the function would print at the correct spot in the body.
Nice intuition about the cause. BTW begin a function name with a small letter.
It's not a direct answer to your question but I believe what you're doing will cause you nothing but pain even if you get it to work. You're not using the right tool for the job; creating custom JSP tags is a better option for writing to JSP from Java code.
Code example:
register.jsp
<%# taglib prefix="custom" uri="/WEB-INF/custom-tags.tld" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Register</title>
</head>
<body>
<p>
<c:out value="${custom:printHaha()}" />
</p>
</body>
</html>
custom-tags.tld
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0"
xmlns="http://java.sun.com/xml/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<tlibversion>1.0</tlibversion>
<jspversion>2.0</jspversion>
<shortname>custom-taglib</shortname>
<uri>CustomTags</uri>
<function>
<name>printHaha</name>
<function-class>com.yourpackage.Tags</function-class>
<function-signature>
java.lang.String print()
</function-signature>
</function>
(...)
Tags.class
public class Tags {
public static String print() {
return "haha";
}
}
More info on Tags: official docs
I din't check your code ... you can't do a out.print again using get writer in a jsp page ... because the response for this request is already committed by rendering the jsp
now to print something on asp you can do this any number of ways
print by expression tag
use out (which is an object the server creates)
out.print("Blah...");
and more
to understand what happens to a jsp look into /work/catalina/blah.../
There are two pages. The first one is the Main Page. This one performs some
pseudo calcs.
Based on those calcs, either Success.jsp or Failure.jsp is returned.
This code will do what you wanted to have achieved.....
Even though as the others pointed out, there are more advanced techniques as of
late, still in order to dance, first you have to know the moves....
Primarily look at this
cObj.Print(request, response); in the 2nd jsp page.
JSP Page
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page import="java.util.*" %>
<%# page import="rustler.Beans.Beany" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>JSP and JavaBean</title>
<%-- create an instance of Customer class --%>
<jsp:useBean id="cObj" scope="request" class="rustler.Beans.Beany">
<%-- Set the value of attribute such as CustID --%>
<jsp:setProperty name="cObj" property="*" />
</jsp:useBean>
</head>
<body>
<%
int x=cObj.setStoreCust();
if(x>=1)
{
%>
<jsp:forward page="Success.jsp" />
<%
}
else
{
%>
<jsp:forward page="Failure.jsp" />
<%
}
%>
</body>
</html>
JSP Page
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page import="java.util.*" %>
<%# page import="rustler.Beans.Beany" %>
<%# page import="javax.servlet.http.HttpServletRequest" %>
<%# page import="javax.servlet.http.HttpServletResponse" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Failure!</title>
<%-- create an instance of Customer class --%>
<jsp:useBean id="cObj" scope="request" class="rustler.Beans.Beany">
<%-- Set the value of attribute such as CustID --%>
<jsp:setProperty name="cObj" property="*" />
</jsp:useBean>
</head>
<body>
<%cObj.Print(request, response);%>
</body>
</html>
Java Bean
package rustler.Beans;
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Beany implements Serializable
{
public Beany()
{
}
/**
*
*/
private static final long serialVersionUID = 1L;
private String custID;
private String custName;
private int qty;
private float price;
private float total;
private int storeCust;
public String getCustID() {
return custID;
}
public void setJunk(String sStr)
{
//System.out.println("What a punk!");
custName = sStr;//"What a punk!";
}
public void Print(HttpServletRequest request,HttpServletResponse response)
{
try{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<p>haha</p>");
}catch(IOException e){
e.printStackTrace();
}
}
public String prntJunk()
{
//System.out.println("What a punk!");
return custName;//"What a punk!";
}
public void setCustID(String custID) {
this.custID = custID;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public float getTotal() {
return total;
}
public void setTotal(float total) {
this.total = total;
}
public int setStoreCust()
{
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/usermaster","admin","password");
PreparedStatement pstmt=null;
String query=null;
query="insert into customer values(?,?,?,?,?)";
pstmt=con.prepareStatement(query);
pstmt.setString(1,custID);
pstmt.setString(2,custName);
pstmt.setInt(3,qty);
pstmt.setFloat(4,price);
pstmt.setFloat(5,total);
int i=pstmt.executeUpdate();
this.storeCust=i;
}
catch(Exception e)
{
}
return storeCust;
}
}

type mismatch with #helper

I'm trying to show a form with the values but it's not working.
my action:
public static Result login() {
User user = new User();
user.name = "Murilo";
Form<User> userForm = form(User.class);
return ok(login.render(userForm.fill(user)));
}
and my html:
#(myForm : play.data.Form[models.User])
<!DOCTYPE html>
<html>
<head>
</head>
<body>
#helper.inputText(myForm("name"))
</body>
</html>
but when I access it, the following error throws:
type mismatch; found : play.data.Form.Field required: play.api.data.Field
As a addition to nico_ekito's good answer: I usually do not use #helper.. because it is long and not/less readable if your form starts to grow (more fields). So I do the following:
#(editForm:Form[User]
#*** IMPORTS ****#
#import helper._
#form(routes.Tasks.save(), 'class -> "form-horizontal") {
#inputText(editForm:Form("description()").....)
#inputArea(editForm:Form("description()").....)
}
In your template, it should be:
#(myForm : Form[User])
<!DOCTYPE html>
<html>
<head>
</head>
<body>
#helper.inputText(myForm("name"))
</body>
</html>

Categories