layout:decorate is not working in thymeleaf - spring

I am trying to introduce a layout(as here) in my application using thymeleaf but couldn't get it working. I have already checked this post.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
...
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
This is my MvcConfig
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
...
#Bean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
}
layout.html as given here. No changes. Added xmlns:th="http://www.thymeleaf.org on checking some article.
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Layout page</title>
</head>
<body>
<header>
<h1>My website</h1>
</header>
<div layout:fragment="content">
<p>Page content goes here</p>
</div>
<footer>
<p>My footer</p>
<p layout:fragment="custom-footer">Custom footer here</p>
</footer>
</body>
</html>
I'm trying to replace the contents fragment as shown below in login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.thymeleaf.org"
layout:decorate="~{layout}">
<head>
<title>Application Login</title>
</head>
<body>
<div layout:fragment="content">
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="#{/login}" method="post">
<div><label> User Name : <input type="text" name="username" value=""/> </label></div>
<div><label> Password: <input type="password" name="password" value=""/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</div>
</body>
</html>
Am I missing anything?

The following worked for me.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
...
<!--<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>-->
<properties>
...
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
</properties>

for works with thymeleaf and extend a view, you must(Spring boot):
Verify dependencies thymeleaft for spring boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
This is for use directives authenticated in thymeleaf (example: sec:authorize)
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
This is important, for add dependencies dialect
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>2.3.0</version>
</dependency>
now, we need to create the LayoutDialect bean in a #Configuration annotated class.
#Bean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
By last:
mvn clean install
and run server.

Related

Thymeleaf decorator problem after upgrading spring boot to greater than 2.5.4

I have a MVC application based on spring-boot:2.5.4.
After migrating from spring-boot 2.5.4, to 2.5.14-2.6.7 Thymeleaf layout does'nt import header (header tag is empty) and leaves blank other inserted elements( like layouts/sidebar :: sidebar, layouts/footer :: footer) from the decorator.
I have upgraded my libs to:
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Main layout:
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<!-- JS/ CSS-->
</head>
<body id="page-top">
<div th:replace="layouts/sidebar :: sidebar"></div>
<div id="content-wrapper" class="d-flex flex-column">
<div id="content">
<div layout:fragment="content"></div>
</div>
<footer class="sticky-footer bg-white">
<div th:replace="layouts/footer :: footer">
</div>
</footer>
</div>
</div>
and Page uwing this layout:
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layouts/base_layout"
xmlns:th="http://www.thymeleaf.org">
<body>
<section layout:fragment="content">
some content
</section>
</body>
</html>
Has there been a change in spring-boot thymeleaf compability? When I define header a sa fragment, I can import header to the pages, but this is missing the point of having a layout class, when I have to import every element manually.
I was albe to fix my issue by reading migration notes for Thymeleaf.
The section:
This was deprecated back in 2.0 (thymeleaf-layout-dialect/issues/95)
in favour of decorate as the naming was misleading, and has now been
deleted.
So after replacing
layout:decorator
with
layout:decorate
Everything works fine.

Error occuring template parsing. (Spring Boot + Thymeleaf) with layout and static

I am getting parsing error when I try to load localhost:8080/.
I can't find any errors in my template, so why have I this mistake?
The file static has folder css and picture with jQuery, js and bootstrap
Error : This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed May 22 13:02:18 CEST 2019
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/RHAjouterDeve.html]")
Code layout index.html:
<!DOCTYPE html>
<html lang="fr" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial- scale=1">
<link th:href="/webjars/bootstrap/4.3.1/css/bootstrap.css" rel="stylesheet" />
<link rel="icon" th:href="(images/favicon.ico)" type="image/ico" />
<title>Projet Pfa Spring BOOT </title>
<link rel="stylesheet" th:href="{build/css/bootstrap.min.css}" />
</head>
<body class="nav-md">
<div class="container body">
<div class="main_container">
<div class="col-md-3 left_col">
<div class="left_col scroll-view">
<div class="navbar nav_title" style="border: 0;">
</div>
<div class="clearfix"></div>
<div class="profile clearfix">
<div class="profile_pic">
</div>
</div>
<br />
<div id="sidebar-menu" class="main_menu_side hidden-print main_menu">
<div class="menu_section">
<br/>
<br/>
<br/>
<br/>
<br/>
<h3>Menu</h3>
<!-- <ul class="nav side-menu"> -->
<!-- <li><a><i class="fa fa-home"></i> Formation <span class="fa fa-chevron-down"></span></a> -->
<!-- <ul class="nav child_menu"> -->
<!-- <li>Demande Formation</li> -->
<!-- <li>Formation Traité</li> -->
<!-- <li>Formation Accepter</li> -->
<!-- <li>Formation En Cours</li> -->
<!-- <li>Formation Finis</li> -->
<!-- </ul> -->
<!-- </li> -->
<!-- <ul class="nav side-menu"> -->
<!-- <li><a><i class="fa fa-home"></i> Devellopeur <span class="fa fa-chevron-down"></span></a> -->
<!-- <ul class="nav child_menu"> -->
<!-- <li>La Liste Devellopeur</li> -->
<!-- </ul> -->
<!-- </li> -->
<!-- </ul>-->
</div>
</div>
</div>
</div>
<!-- top navigation -->
<div class="top_nav">
<div class="nav_menu">
<nav>
<div class="nav toggle">
<a id="menu_toggle"><i class="fa fa-bars"></i></a>
</div>
<ul class="nav navbar-nav navbar-right">
<li class="">
<a href="javascript:;" class="user-profile dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<img th:src="(images/img.jpg)" alt="">
<span class=" fa fa-angle-down"></span>
</a>
<ul class="dropdown-menu dropdown-usermenu pull-right">
<li>
</li>
<li><i class="fa fa-sign-out pull-right"></i> Log Out</li>
</ul>
</li>
<li role="presentation" class="dropdown">
<ul id="menu1" class="dropdown-menu list-unstyled msg_list" role="menu">
<li>
<a>
<span class="image"><img th:src="(images/img.jpg)" alt="Profile Image" /></span>
</a>
</li>
<li>
<a>
<span class="image"><img src="images/img.jpg" alt="Profile Image" /></span>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<a>
</a>
</li>
<li>
<div class="text-center">
</div>
</li>
</ul>
</li>
</ul>
</nav>
</div>
</div>
<!-- /top navigation -->
<!-- page content -->
<div class="right_col" role="main">
<!-- <div class="row tile_count"> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Formation en cours</span> -->
<!-- <div class="count">2500</div> -->
<!-- </div> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Formation Traité </span> -->
<!-- <div class="count">123.50</div> -->
<!-- <span class="count_bottom"><i class="green"> </i></span> -->
<!-- </div> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Total Finis</span> -->
<!-- <div class="count green">2,500</div> -->
<!-- <span class="count_bottom"><i class="green"></i> </i></span> -->
<!-- </div> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Total Formateur</span> -->
<!-- <div class="count">4,567</div> -->
<!-- <span class="count_bottom"><i class="red"></i> </i> </span> -->
<!-- </div> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Total Employé</span> -->
<!-- <div class="count">2,315</div> -->
<!-- <span class="count_bottom"><i class="green"> </span> -->
<!-- </div> -->
<!-- <div class="col-md-2 col-sm-4 col-xs-6 tile_stats_count"> -->
<!-- <span class="count_top"><i class="fa fa-user"></i> Total Chef Projet</span> -->
<!-- <div class="count">7,325</div> -->
<!-- <span class="count_bottom"><i class="green"> </span> -->
<!-- </div> -->
<!-- </div> -->
<section layout:fragment="content" class="container">
</section>
<!-- start of weather widget -->
<!-- end of weather widget -->
</div>
</div>
</div>
<!-- /page content -->
<!-- footer content -->
<!-- /footer content -->
<!-- Custom Theme Scripts -->
<script src="build/js/custom.min.js"></script>
<script src="/webjars/jquery/3.4.1/jquery.js"></script> <script src="/webjars/bootstrap/4.3.1/js/bootstrap.js">
</script>
</body>
</html>
</strike>
Fichier rhajouterdeve.html
<strike><!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout/default">
<body>
<section layout:fragment="content">
hello
</section>
</body>
</html>
</strike>
le code du controller :
package com.projetpfa.gestionrh.gestionrh.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/Devellopeur")
public class DeveControllers {
//#Autowired
//DeveService dvserv;
#GetMapping("/")
public String AllDeve( )
{
return"RHAjouterDeve";
}
}
mon fichier pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.projet.pfa</groupId>
<artifactId>projetpfa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>projetpfa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Error in logs:
____org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/RHAjouterDeve.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[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]
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) [thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) [thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1370) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1116) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) [tomcat-embed-core-9.0.17.jar:9.0.17]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) [spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.17.jar:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.17.jar:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar:9.0.17] _ __ _ _
have a Spring Boot for serving images. My Model is included in my ImageController.java. ImageService contains findPage method.
When running my Spring Boot Application I am getting an error.
I want to see me template DASHBOARD to begin my project
How can localhost:8585/Devellopeur find template with static file and layout view with no error,
First of all, you can not access localhost:8080/ because you do not have the right controller. You can access http://localhost:8090/Devellopeur/
package com.projetpfa.gestionrh.gestionrh.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/Devellopeur")
public class DeveControllers {
//#Autowired
//DeveService dvserv;
#GetMapping("/")
public String AllDeve( )
{
return"RHAjouterDeve";
}
}
In order to access http://localhost:8090/Devellopeur/ without no thymeleaf parsing errors, you have to create the web page default declared in your rhajouterdeve.html. In general, this file (default.html) is used to to reuse header and footer on all Thymeleaf templates.
<html xmlns:th="http://thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout/default">
Create it in templates package and declare it as follow:
<html xmlns:th="http://thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="default">
At last, you should delete the <strike> in your rhajouterdeve.html
Here an example of default page that you can use.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<header>
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="#">Jeutroll</a>
</div>
<div>
<ul class="nav navbar-nav">
<li class="active"><a th:href="#{/index}">Home</a></li>
</ul>
</div>
</nav>
</div>
</header>
<section layout:fragment="content"></section>
<footer>
<div class="navabar-fixed-bottom">
<small>adress</small>
</div>
</footer>
</body>
</html>

Thyme template engine (layout:decorate) doesn't load the template file in Spring Boot

I am struggling with making Thymeleaf load prepared Template fragments in Spring Boot into target webpage.
The index.html file doesn't load the template through decorate, even although I can include them directly via th:replace. I was following a tutorial but wasn't able to find a solution. I believe that the default template location should be resources/templates, which I am using. The html code is following:
index.html
<th:block layout:decorate="layout/layout" layout:fragment="content">
<!-- PAGE CONTENT -->
<div class="container" id="homePage">
<div>
<h1>Headline</h1>
bla <br />
<!--<span th:text="${article.title}" /><br />
<span th:text="${article.title}" /><br />-->
</div>
<div class="row">
<div class="col-lg-12">
<h2>This is Home Page</h2>
<div class="well">
I am inside a bootstrap well.
</div>
</div>
</div>
</div>
<!-- /.container -->
</th:block>
layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<th:block th:replace="layout/fragments/head"></th:block>
</head>
<body>
<th:block th:replace="layout/fragments/nav"></th:block>
<!-- Page Content -->
<div layout:fragment="content" />
<!-- /.container -->
<th:block th:replace="layout/fragments/footer"></th:block>
</body>
</html>
head.html
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Spring Thymeleaf Dialect Configuration</title>
<!-- Bootstrap Core CSS -->
<link th:href="#{/resources/css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom CSS -->
<link th:href="#{/resources/css/logo-nav.css}" rel="stylesheet">
<script th:inline="javascript"> var contextRoot = /*[[#{/}]]*/ ''; </script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
Folder Structure:
Maven project structure
Here are Maven dependencies:
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>com.faire</groupId>
<artifactId>thyme2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>thyme2</name>
<description>Demo project for Spring Boot Thyme</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Bootstrap -->
<!-- https://mvnrepository.com/artifact/org.webjars/bootstrap -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.webjars.bower/jquery -->
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<!--<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
HTML output of index.html:
<!-- PAGE CONTENT -->
<div class="container" id="homePage">
<div>
<h1>Headline</h1>
bla <br />
<!--<span th:text="${article.title}" /><br />
<span th:text="${article.title}" /><br />-->
</div>
<div class="row">
<div class="col-lg-12">
<h2>This is Home Page</h2>
<div class="well">
I am inside a bootstrap well.
</div>
</div>
</div>
</div>
<!-- /.container -->
What am I missing?
Adding Layout Dialect resolved the problem:
<dependency>
<groupId> nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
I believed it is a part of spring-boot-starter-thymeleaf, but it seems the other way around.
The html output after including dependency:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Spring Thymeleaf Dialect Configuration</title>
<!-- Bootstrap Core CSS -->
<link href="/resources/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="/resources/css/logo-nav.css" rel="stylesheet">
<script> var contextRoot = "\/"; </script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- navigation --> <!-- inverse = white on black color schema, fixed top = always on the top (sticky would unhide when
scrolling down -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<!-- data-toggle - collapses target -->
<button type="button" class="navbar-toggle" data-toggle="collapse" date-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
Spring ThymeLeaf
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li>
Demo Page 1
</li>
<li>
Demo Page 2
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<!-- PAGE CONTENT -->
<div class="container" id="homePage">
<div>
<h1>This is headline!</h1>
bla <br />
<!--<span th:text="${article.title}" /><br />
<span th:text="${article.title}" /><br />-->
</div>
<div class="row">
<div class="col-lg-12">
<h2>This is Home Page</h2>
<div class="well">
I am inside a bootstrap well.
</div>
</div>
</div>
</div>
<!-- /.container -->
<!-- /.container -->
<div>
© 2018 Faire
<!-- jQuery -->
<script src="/resources/js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/resources/js/bootstrap.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/resources/js/custom.js"></script>
</div>
</body>
</html>
<div>
© 2018 Faire
<!-- jQuery -->
<script src="/resources/js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/resources/js/bootstrap.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="/resources/js/custom.js"></script>
</div>

Bootstrap not working with spring-boot?

I am attempting to install bootstrap for use in my spring boot project, which uses thymeleaf. I am getting this error with the template (index.html, shown below):
Malformed markup: Attribute "class" appears more than once in element
I assume this is because bootstrap isn't installed properly. Below I have an image of the files also.
I am pretty sure all the dependencies are right.
INDEX HTML:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css"/>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<!-- <link rel="stylesheet" type="text/css"
th:href="#{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" th:href="#{/css/main.css}" />
<script
src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js">
</script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script> -->
<title>Home</title>
<style></style>
</head>
<body>
<div class="navbar navbar-default" role="navigation" id="topnavbar">
<div class="container">
<div class="navbar-header">
<button class="navbar-toggle" type="button" data-
toggle="collapse" data-target="#navbar-main">
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse" id="navbar-main">
<ul class="nav navbar-nav">
<li><span class="glyphicon glyphicon-home"></span>Profile</li>
<li>
<a href="/competition">
<span class="glyphicon glyphicon-star"></span> Competitions
</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/logout"> <span class="glyphicon glyphicon-user"></span>
<strong>Log out</strong>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="container" class="row">
<div class="page-header" id="banner">
<div class="row">
<div class="col-lg-8 col-md-7 col-sm-6">
<img src="ban.png">
</div>
<div class="col-lg-4 col-md-5 col-sm-6">
<div class="sponsor"></div>
</div>
</div>
</div>
</div>
<div class="container"></div>
</body>
<script th:inline="javascript">
$(document).ready(function () {
var panels = $('.user-infos');
var panelsButton = $('.dropdown-user');
panels.hide();
//Click dropdown
panelsButton.click(function () {
//get data-for attribute
var dataFor = $(this).attr('data-for');
var idFor = $(dataFor);
//current button
var currentButton = $(this);
idFor.slideToggle(400, function () {
//Completed slidetoggle
if (idFor.is(':visible')) {
currentButton.html('<i class="glyphicon glyphicon-
chevron - up
text - muted
"></i>');
}
else {
currentButton.html('<i class="glyphicon glyphicon-
chevron - down
text - muted
"></i>');
}
})
});
$('[data-toggle="tooltip"]').tooltip();
$('button').click(function (e) {
e.preventDefault();
alert("This is a demo.\n :-)");
});
});
</script>
</html>
POM file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.finalYearProject</groupId>
<artifactId>student-life</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>student-life</name>
<description>Jill's Student Life Final Year Project</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8
</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!-- upgrade to thymeleaf version 3 -->
<thymeleaf.version>3.0.8.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-
dialect.version>
<thymeleaf-extras-springsecurity4.version>3.0.2.RELEASE</thymeleaf-
extras-springsecurity4.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap-datepicker</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency> -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId1>spring-session</artifactId>
<version>1.2.2.RELEASE</version>
</dependency> -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Project structure:
The exception will give the line # in the html where the error is occurring... in any case, the actual problem is here:
<div class="container" class="row">
Thymeleaf won't allow an element to have two attributes with the same name (Attribute "class" appears more than once in element). Just change it to:
<div class="container row">

Spring Boot and Thymeleaf: Can't find HTML templates

I am trying to create a Spring Boot-based application with Thymeleaf. I am using the PetClinic sample as a starting point.
My application can't find some of the templates.
My project is set up in the standard way:
/src
/main
/java
/com.example
MyWebApplication.java
HomeController.java
/resources
/static
/css
/templates
/fragments
layout.html
home.html
application.properties
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
MyWebApplication.java
#SpringBootApplication
public class MyWebApplication {
public static void main(String[] args) {
SpringApplication.run(MyWebApplication.class, args);
}
}
HomeController.java
#Controller
public class HomeController {
#RequestMapping("/")
public String home() {
return "home";
}
}
home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
th:replace="~{fragments/layout :: layout (~{::body},'home')}">
<body>
<h2 th:text="#{welcome}">Welcome</h2>
<div class="row">
</div>
</body>
</html>
layout.html
<!DOCTYPE html>
<!--
The main layout fragment that defines the overall layout
Sets up the navigation bar
The page contents are replaced in the main div
-->
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
th:fragment="layout (template, menu)">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="shortcut icon" type="image/x-icon" th:href="#{/images/favicon.png}"> -->
<title>Web Interface</title>
<link rel="stylesheet" th:href="#{/css/bootstrap.min.css}" />
</head>
<body>
<!-- Navigation Bar -->
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand glyphicon glyphicon-home" th:href="#{/}"></a>
<!-- Collapse the menu bar on small windows -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- The Navbar items -->
<div class="navbar-collapse collapse" id="main-navbar">
<ul class="nav navbar-nav navbar-right">
<!-- Define a fragment for each menu item -->
<li th:fragment="menuItem (path, active, title, glyph, text)" th:class="${active==menu ? 'active' : ''}">
<a th:href="#{__${path}__}" th:title=${title}>
<span th:class="'glyphicon glyphicon-'+${glyph}" class="glyphicon glyphicon-home" aria-hidden="true"></span>
<span th:text="${text}">Template</span>
</a>
</li>
<!-- Replace with the fragment -->
<li th:replace="::menuItem ('/', 'home', 'home page', 'home', 'Home')">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
<span> Home</span>
</li>
</ul>
</div>
</div>
</nav>
<!-- Main body -->
<div class="container-fluid">
<div class="container xd-container">
<div th:replace="${template}"></div>
</div>
</div>
<script th:src="#{/js/bootstrap.min.js}" type="text/javascript"></script>
</body>
</html>
application.properties is empty.
When I navigate to http://localhost:8080 I get the error:
Error resolving template "~{fragments/layout", template might not
exist or might not be accessible by any of the configured Template
Resolvers (home:5)
If I remove the 'th:replace' attribute from home.html, it will display the welcome message.
Browsing similar questions (e.g. this one), I see other people create ThymeleafViewResolver bean.
Questions:
Why can't it find my templates?
Do I need to create a template resolver? If so, how come the pet clinic sample doesn't? Where does its template resolver come from?
As far as I can see it's set up the same way as the pet clinic sample, so what's the difference?
Spring boot does some internal works automagically for you, but to do that automagical work you need to configure it properly. This is the answer for your question 2, spring automagically provides the view resolver if configuration is right. Ok, now lets move to question 1.
If you compare your pom.xml with that of petclinic, You'll see some key differences.
At first, According to spring official doc http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-build-systems.html#using-boot-maven, Maven users can inherit from the spring-boot-starter-parent project to obtain sensible defaults. The parent project provides some features. To configure your project to inherit from the spring-boot-starter-parent simply set the parent in your pom.xml.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
With that setup, you can also override individual dependencies by overriding a property in your own project. For instance, in petclinic pom.xml, they specified the thymeleaf version which is missing in yours.
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
Now to properly setup Thymeleaf and Thymeleaf layout dialect version with compatibility between them you need to exclude thymeleaf-layout-dialect from spring-boot-starter-thymeleaf, bcz of setting thymeleaf version to 3.0.2.RELEASE version.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<exclusions>
<exclusion>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</exclusion>
</exclusions>
</dependency>

Resources