I'm using thymeleaf as a template engine but I cant get it to work properly.
I'm using websockets to push html to the web browser so I try to process the template with the context into a string. This string is then send to the browser to show.
My Controller class:
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
#Autowired
private SpringTemplateEngine springTemplateEngine;
private void send() {
Map<String, Object> params = new HashMap<>();
params.put("name", "Willem");
final IContext cts = new Context(Locale.ITALY, params);
String result = springTemplateEngine.process("hello", ctx);
simpMessagingTemplate.convertAndSend(destination, result);
}
My thymeleaf configuration:
#Configuration
public class ThymeleafConfig extends WebMvcConfigurerAdapter {
#Bean
public ClassLoaderTemplateResolver templateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("thymeleaf/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine( templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
}
And my hello.html template:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<body>
<h2>Hello ${name} - THYMELEAF</h2>
</body>
</html>
When I print the string result from the send method, I get this output:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h2>Hello ${name} - THYMELEAF</h2>
</body>
</html>
Whatever I try, I can't get the parameters to be passed to the template.
You try java code:
private void send() {
Context context = new Context();
context.setVariable("name", "hello");
String result = springTemplateEngine.process("hello", context);
simpMessagingTemplate.convertAndSend(destination, result);
}
Html: hello.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h2>Hello <b th:text="${name}"></b> - THYMELEAF</h2>
</body>
</html>
Related
I have a controller
#Controller
public class FirstController {
#GetMapping("/hello")
public String helloPage(#RequestParam("name") String name,
Model model){
model.addAttribute("message", name);
return "first/hello";
}
}
And view hello.html
<!doctype html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Hello world!</h1>
<p th:text="${message}"></p>
</body>
</html>
I enter the required parameters: http://localhost:8080/hello?name=Tom
But all that the page displays is "Hello world!"
P.S. I'm working with spring core and therefore I had to write the configs by hand, here's what is in the configs:
#Configuration
#ComponentScan("com.nosferat.springapp")
#EnableWebMvc
public class SpringConfig implements WebMvcConfigurer {
#Bean
public ViewResolver viewResolver() {
var viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".html");
return viewResolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Maybe it has something to do with the config
Why do you have a return "first/hello"? you should use return "hello", by the way this may be the answer to your question
i also highly suggest you to use Spring boot so your life will be easier
I am developing a site using Spring, Spring MVC, Thymeleaf and ran into the problem: css file with styles not being applied to my page.
The structure of the project is as follows:
java
com
tournament
config
MySpringMVCDispatcherServletInitialize.java
SpConfig.java
controllers
HomePageController.java
webapp
WEB-INF
views
css
style.css
home_page.html
style.css:
p{
font-size: 200%;
font-family: Verdana, Arial, Helvetica, sans-serif;
color: #336;
}
body{
background-color: red;
}
home_page.html:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" th:href="#{/css/style.css}" media="all">
</head>
<body>
<p>Hello</p>
</body>
</html>
in SpConfig there are this configs:
#Configuration
#ComponentScan("com.tournament")
#EnableWebMvc
public class SpConfig implements WebMvcConfigurer {
private final ApplicationContext applicationContext;
#Autowired
public SpringConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry {
registry.addResourceHandler("/css/**")
.addResourceLocations("/WEB-INF/css/");
}
In home_page.html place the cursor on th:href="#{/css/style.css}", it seems correct path to css file, but when starting the server on the page home_page.html no styles which contained in style.css. So how can I to apply this style?
Your directory structure shows that the css is in WEB-INF/views/css, but you configure /WEB-INF/css/ in addResourceLocations. According to https://www.baeldung.com/spring-mvc-static-resources, if you don't use the classpath: prefix in that string, then the path is relative to webapp/resources.
So or you need to move your CSS, or you will need to update the .addResourceLocations("/WEB-INF/css/") statement.
In admin.html I have tag th:text="${name}". It doesn't display value from the controller. Why?
Admin.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Admin page</title>
</head>
<body>
Dear <strong><p th:text="${name}"></p></strong>, Welcome to Admin Page.
Logout
</body>
</html>
and the controller is
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#ModelAttribute("userForm") User userForm, Model model) {
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
model.addAttribute("name",authentication.getName());
if (securityService.isAdmin(userForm.getUsername())) {
return "redirect:/admin";
}
} catch (RestException e) {
model.addAttribute("error", "User with username '"+userForm.getUsername()+"' not found");
}
return "redirect:/index";
}
My MVC configuration is
#Configuration
#EnableWebMvc
#ComponentScan({ "ru.dev.avtonomki" })
public class WebMVCConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver htmlViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine(jspTemplateResolver()));
resolver.setContentType("text/html");
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(1);
resolver.setViewNames(ArrayUtil.array("*.html"));
return resolver;
}
private TemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new LayoutDialect(new GroupingStrategy()));
engine.addDialect(new Java8TimeDialect());
engine.setTemplateResolver(templateResolver);
return engine;
}
private ITemplateResolver htmlTemplateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setCacheable(false);
resolver.setTemplateMode(TemplateMode.HTML5);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
Because from your "/admin" action you have to pass name not from login.
#RequestMapping(value = "/admin", method = RequestMethod.GET)
public String admin(Model model) {
Authentication authentication =SecurityContextHolder.getContext().getAuthentication();
model.addAttribute("name",authentication.getName());
retrun "admin" ;
}
Or you can set RedirectAttributes
When attempting to localize a static string the message is displayed surrounded with questionmarks "??"
e.g. ??ticket.type_en_US??
<p th:text="#{ticket.type}">Blah</p>
I am using SpringBoot 1.3.6.RELEASE
Thymeleaf: 3.0.0.RELEASE
thymeleaf-spring4 artifact
I have configured the basename of my messages in application.properties
and the contents of that messages.properties and messages_en_US.properties is:
ticket.type=BUGS!!!!
Config:
spring.messages.basename=messages
Output on startup:
2016-07-19 08:38:28.673 DEBUG 5175 --- [ main]
ationConfigEmbeddedWebApplicationContext : Using MessageSource
[org.springframework.context.support.ResourceBundleMessageSource:
basenames=[messages]]
I also tried programatically using the MessageResource in the code below. I placed the messages.properties file in the same folder as the application.properties file. src/main/resources/
#Configuration
#ComponentScan("controller")
public class WebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware{
private ApplicationContext applicationContext;
#Autowired
private MessageSource messageSource;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setMessageSource(messageSource);
return engine;
}
#Bean
public ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}
For completeness here is my application config (like others I had to exluse the Thymeleaf class):
#SpringBootApplication(exclude={org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
I have also verified that the message bundles are being loaded by pring out the contents on one of my REST end-point calls:
#Autowired
private MessageSource messageSource;
#GET
#Produces("application/json")
public List<MyData> getData() {
System.out.println("HERE 1 in Conversions");
System.out.println(messageSource.getMessage("ticket.type", null, Locale.US));
return getTheData();
}
This prints out the following so I know spring-boot is loading the resource bundles, but Thymeleaf is not picking them up somehow:
BUGS!!!!
Here is my full HTML page, perhaps there is an issue with it:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Kitchen Sink</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.4/css/bootstrap.min.css"
th:href="#{/webjars/bootstrap/3.3.4/css/bootstrap.min.css}"
rel="stylesheet" media="screen" />
<script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
th:src="#{/webjars/jquery/2.1.4/jquery.min.js}"></script>
<link href="../static/css/mike.css"
th:href="#{css/mike.css}" rel="stylesheet" media="screen"/>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Hello</h1>
<h2>Welcome to the Kitchen Sink!</h2>
<p th:text="#{ticket.type}">Blah</p>
<p th:text="#{test.type}">dssfgf</p>
</div>
</body>
</html>
ok, so I figured it out. Thanks #M.Deinum for poitning out that I should just let spring-boot and Thymeleaf do what they are supposed to do.
I had to set the:
engine.setMessageSource(messageSource);
and also add the:
#Bean
to the 2 other functions. This allowed the MessageSource to be passed into the engine and resolve the properties correctly.
I will update the question above with the correct source so people can use it for referene
Please add
#EnableAutoConfiguration
in your Spring boot startup its look like
#EnableAutoConfiguration
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
I had a similar problem, and code from your post didn't work for me. The source of my issue was, that I didn't have message.proprerties (without any language).
I had:
messages_en.properties
messages_de.properties
messages_es.properties
but it didn't work.
It started working only when I added
messages.properties
I have a string variable that I create in a controller class and I want to print it in a jsp page using this
${time}
My code works if I don't use a thymeleaf view resolver, but if I do use one it doesn't work.
Here is my controller class
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
String thetime = "the time";
model.addAttribute("time", thetime );
return "home.jsp";
}
And my .jsp page
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The time on the server is ${time}. </P>
</body>
</html>
My thymeleaf resolver configuration:
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setOrder(1);
resolver.setCacheable(false);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setMessageSource(messageSource());
return engine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
String[] vistas = {"*.html", "*.jsp"};
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(1);
resolver.setViewNames(vistas);
resolver.setCache(false);
return resolver;
}
#Bean
public SpringResourceTemplateResolver thymeleafSpringResource() {
SpringResourceTemplateResolver vista = new SpringResourceTemplateResolver();
vista.setTemplateMode("HTML5");
return vista;
}
Is there a special notation to do this with thymeleaf?
You have set your view resolver to be Thymeleaf but you trying to render JSP thats why it isn't working.
if you want that file converted to Thymeleaf format it needs to look like this (or approx) and the extension has to be .html not .jsp:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The time on the server is <div th:text=#{time}>TIME_PLACEHOLDER</div> </P>
</body>
</html>
Aesir's answer worked, but it wasn't necesary to change my .jsp page to a .html page. I just put this
<div th:text="${time}">TIME_PLACEHOLDER</div>
instead of just ${time}, and it worked without the HTML header that was suggested.