I'm using thymeleaf 3.0.7 nad Spring security and trying to make a webapp. Logging and creating accounts runs well but before logging (viewing page as anonymous) i'm getting errors as below:
2018-07-24 21:09:19.124 [http-bio-8090-exec-7] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][http-bio-8090-exec-7] Exception processing template "error/general": An error happened during template parsing (template: "ServletContext resource [/WEB-INF/views/error/general.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "ServletContext resource [/WEB-INF/views/error/general.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:355)
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:188)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1325)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1069)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1008)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:489)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:467)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:338)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:203)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#authorization.expression('isAuthenticated()')" (template: "fragments/layout" - line 34, col 21)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 34 common frames omitted
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('isAuthenticated()')" (template: "fragments/layout" - line 34, col 21)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:165)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.expression.NegationExpression.executeNegation(NegationExpression.java:149)
at org.thymeleaf.standard.expression.ComplexExpression.executeComplex(ComplexExpression.java:86)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:112)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:125)
at org.thymeleaf.standard.processor.StandardIfTagProcessor.isVisible(StandardIfTagProcessor.java:59)
at org.thymeleaf.standard.processor.AbstractStandardConditionalVisibilityTagProcessor.doProcess(AbstractStandardConditionalVisibilityTagProcessor.java:61)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314)
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205)
at org.thymeleaf.engine.Model.process(Model.java:282)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1587)
at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleOpenElementEnd(TemplateHandlerAdapterMarkupHandler.java:304)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleOpenElementEnd(OutputExpressionInlinePreProcessorHandler.java:186)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:124)
at org.attoparser.HtmlElement.handleOpenElementEnd(HtmlElement.java:109)
at org.attoparser.HtmlMarkupHandler.handleOpenElementEnd(HtmlMarkupHandler.java:297)
at org.attoparser.MarkupEventProcessorHandler.handleOpenElementEnd(MarkupEventProcessorHandler.java:402)
at org.attoparser.ParsingElementMarkupUtil.parseOpenElement(ParsingElementMarkupUtil.java:159)
at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:710)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
... 36 common frames omitted
Caused by: java.lang.IllegalArgumentException: Authentication object cannot be null
at org.springframework.security.access.expression.SecurityExpressionRoot.<init>(SecurityExpressionRoot.java:61)
at org.springframework.security.web.access.expression.WebSecurityExpressionRoot.<init>(WebSecurityExpressionRoot.java:36)
at org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler.createSecurityExpressionRoot(DefaultWebSecurityExpressionHandler.java:43)
at org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler.createSecurityExpressionRoot(DefaultWebSecurityExpressionHandler.java:33)
at org.springframework.security.access.expression.AbstractSecurityExpressionHandler.createEvaluationContext(AbstractSecurityExpressionHandler.java:66)
at org.thymeleaf.extras.springsecurity4.auth.AuthUtils.authorizeUsingAccessExpression(AuthUtils.java:194)
at org.thymeleaf.extras.springsecurity4.auth.Authorization.expression(Authorization.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:120)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:106)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:52)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:359)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:89)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:110)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:334)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263)
... 64 common frames omitted
Since it mentions /WEB-INF/views/error/general.html here it is:
<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<title>Error page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="#{/resources/css/bootstrap.min.css}"/>
<link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="#{/resources/css/core.css}"/>
</head>
<body>
<div class="container">
<div th:replace="fragments/layout :: header"></div>
<div th:replace="fragments/components :: alert (type='danger', message=${errorMessage})">Error: Error</div>
<div th:replace="fragments/layout :: footer"></div>
</div>
</body>
</html>
And layout.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head>
<link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="#{/resources/css/bootstrap.min.css}"/>
</head>
<body>
<!-- Header -->
<div class="navbar navbar-inverse navbar-fixed-top" th:fragment="header">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" th:href="#{/}">Demo project</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li th:classappend="${module == 'about' ? 'active' : ''}">
About
</li>
<li th:classappend="${module == 'calendar' ? 'active' : ''}">
Calendar
</li>
<li th:classappend="${module == 'event' ? 'active' : ''}"
sec:authorize="hasRole('ROLE_ADMIN')"
>
Formularz
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li th:if="not ${#authorization.expression('isAuthenticated()')}">
<a href="/signin" th:href="#{/signin}">
<span class="glyphicon glyphicon-log-in" aria-hidden="true"></span> Sign in
</a>
</li>
<li th:if="${#authorization.expression('isAuthenticated()')}">
<a href="/logout" th:href="#{#}" onclick="$('#form').submit();">
<span class="glyphicon glyphicon-log-out" aria-hidden="true"></span> Logout
</a>
<form style="visibility: hidden" id="form" method="post" action="#" th:action="#{/logout}"></form>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
<!-- Footer -->
<div th:fragment="footer" th:align="center">
© <span th:text="${#temporals.format(#temporals.createNow(), 'yyyy')}">2017</span>
Demo project <span th:text="${#environment.getProperty('app.version')}"></span>
</div>
</body>
</html>
It says that line
<li th:if="not ${#authorization.expression('isAuthenticated()')}">
is the problem and in fact when i change it to return false no errors are thrown. When i change it to use !isAuthenticated() or isAnonymous() instead of "not [...] isAuthenticated()" it throws errors. I have thymeleaf-extras-springsecurity4 dependency added in my pom.xml file as well.
My bet is that i have to work on the fact the authenticated object is null. But what else it could be when i'm checking the website as anonymous?
In general you should always have an authentication object on every page of secured application. Filter org.springframework.security.web.authentication.AnonymousAuthenticationFilter is responsible for setting AnonymousAuthenticationToken in the current security context when it (token) is missing. If this filter is not called it may indicate some problems in security configuration.
BTW try to use xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4" namespace in your Thymeleaf templates. It will shorten security checks a little bit: <div sec:authorize="isAuthenticated()">.
Related
I making the header of my website for an assignment and I wanted to be able to disply different things depending if they are logged in or not. Problem is sec:authorize is not working with no errors or warnings to indicate why.
Here is my header file where I am trying to dispaly login & register if they are not logged in and logout if they are. But all of them appear no matter what.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<header class="masthead mb-auto" th:fragment="header">
<div class="cover-container d-flex h-100 p-3 mx-auto flex-column">
<div class="inner">
<div class="Lucida_Handwriting">
<a class="Lg" href=".." >
<h3 class="logo-brand" id="Logo">Divorce app</h3>
</a>
</div>
<nav class="nav nav-masthead justify-content-center">
<a class="nav-link active" href="/" th:href="#{/}">Home</a>
<a sec:authorize="!isAuthenticated()" class="nav-link" href="/login" th:href="#{/login}">Login</a>
<a sec:authorize="isAuthenticated()" class="nav-link fw-bold py-1 px-0" href="/logout" th:href="#{/logout}">Logout</a>
<a sec:authorize="!isAuthenticated()" class="nav-link fw-bold py-1 px-0" href="/register" th:href="#{/register}">Register</a>
<a class="nav-link" href="/contact">Contact</a>
</nav>
</div>
</div>
</header>
</body>
</html>
Here are my dependecies among others. Version of spring-boot-starter-security & spring-boot-starter-thymeleaf is 3.0.1
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Also noticed that it gets passed in the html altho I think it should not do that
<a sec:authorize="!isAuthenticated()" class="nav-link" href="/login">Login</a>
<a sec:authorize="isAuthenticated()" class="nav-link fw-bold py-1 px-0" href="/logout">Logout</a>
<a sec:authorize="!isAuthenticated()" class="nav-link fw-bold py-1 px-0" href="/register">Register</a>
Tried using thymeleaf-extras-springsecurity4 but it didnt work.
Tried using older versions of thymeleaf-extras-springsecurity5 but that didnt work either.
Tried replacing xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5" with xmlns:sec="http://www.thymeleaf.org/extras/spring-security" but it didnt work.
EDIT: Added the html code instead of an image
I'm trying to use the jquery-bootgrid plugin, but running into some issues using a simple initialization.
The button pagination isn't styled properly and the pageSize/column selection button throws an error in the console when you click on the button:
a.default is not a constructor
This is my markup:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Dashboard </title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-bootgrid/1.3.1/jquery.bootgrid.min.css" />
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">BRANDING</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search" />
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap"> <a class="nav-link" href="#">Sign out</a> </li>
</ul>
</nav>
<div id="content-container" class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item"> <a class="nav-link active" href="#">Menu Item 1 <span class="sr-only">(current)</span> </a> </li>
<li class="nav-item"> <a class="nav-link" href="#">Menu Item 2</a> </li>
<li class="nav-item"> <a class="nav-link" href="#">Menu Item 3</a> </li>
<li class="nav-item"> <a class="nav-link" href="#">Menu Item 4</a> </li>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
<h1 class="h2 pt-3 pb-2 mb-3 border-bottom">Users</h1>
<!-- jquery-bootgrid starts here -->
<table id="grid-basic" class="table table-condensed table-hover table-striped">
<thead>
<tr>
<th data-column-id="id" data-type="numeric">ID</th>
<th data-column-id="email">Sender</th>
<th data-column-id="firstName">First Name</th>
<th data-column-id="lastName" data-order="desc">Last Name</th>
<th data-column-id="deactivated">Deactivated</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>user#domain.com</td>
<td>John</td>
<td>Smith</td>
<td>true</td>
</tr>
</tbody>
</table>
</main>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.5.4/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-bootgrid/1.3.1/jquery.bootgrid.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-bootgrid/1.3.1/jquery.bootgrid.fa.min.js"></script>
<script>
$(document).ready(function() {
$("#grid-basic").bootgrid();
});
</script>
</body>
</html>
I don't feel like I'm doing anything overly complicated here and I'm following the example in the documentation.
This leads me to believe it is a version conflict with bootstrap 4.5.
<ul class="nav navbar-nav navbar-right">
<li>SHOPPING CART</li>
<li><a sec:authorize="isAnonymous()" th:href="#{/login}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/myProfile}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/logout}">LOGOUT</a></li>
</ul>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.w3.org/1999/xhtml">
<head th:fragment="common-header">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Le's Bookstore</title>
<!-- Bootstrap core CSS -->
<link href="/css/bootstrap.min.css" rel="stylesheet" />
<link href="/css/non-responsive.css" rel="stylesheet" />
<!-- Custom styles for this template -->
<link href="/css/style.css" rel="stylesheet" />
<link rel="icon" href="/image/applie-touch-icon.png" />
</head>
<body>
<div th:fragment="navbar">
<div class="page-top"
style="width: 100%; height: 20px; background-color: #f46b42;"></div>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">LE'S BOOKSTORE</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav navbar-left">
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">BOOKS <span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Browse the bookshelf</li>
<li>Store hours & Directions</li>
<li>FAQ</li>
</ul></li>
<form class="navbar-form">
<div class="form-group">
<input type="text" name="keyword" class="form-control"
placeholder="Book title" />
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>SHOPPING CART</li>
<li><a sec:authorize="isAnonymous()" th:href="#{/login}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/myProfile}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/logout}">LOGOUT</a></li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
<!--/.container-fluid -->
</nav>
</div>
<div th:fragment="body-bottom-scripts">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</div>
</body>
</html>
Your namespace is not correct. You may need to add thymeleaf & springsecurity5 as shown below:
<!DOCTYPE HTML>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<!-- head, body, etc -->
</html>
Try to use !isAuthenticated(). Edit your code like this:
<ul class="nav navbar-nav navbar-right">
<li>SHOPPING CART</li>
<li><a sec:authorize="!isAuthenticated()" th:href="#{/login}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/myProfile}">MY ACCOUNT</a></li>
<li><a sec:authorize="isAuthenticated()" th:href="#{/logout}">LOGOUT</a></li>
</ul>
This is the dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.web.controllers" />
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- <mvc:default-servlet-handler /> -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
</beans:beans>
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%# taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<title>mypage</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link href="${pageContext.request.contextPath}/WebContent/resources/mycustom/fabrication.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/WebContent/resources/mycustom/boxmodel.css" rel="stylesheet">
<link href="<c:url value="/resources/css/bootstrap.min.css" />" rel="stylesheet">
<link href="${pageContext.request.contextPath}/WebContent/resources/css/moslake_style.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/WebContent/resources/css/boxmodel.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/WebContent/resources/css/font.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/WebContent/resources/css/media.css" rel="stylesheet">
<script src="<c:url value="/resources/js/jquery.min.js" />"></script>
<script src="<c:url value="/resources/js/bootstrap.min.js" />"></script>
</head>
<body bgcolor="#F5FAFA">
<h1>${pageContext.request.contextPath}</h1>
<div class="header">
<div class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="row">
<div class="col-md-5"></div><!--end of first row columns-->
<div class="col-md-2">
<a class="navbar-brand" href="#"><img src="img/swing.png" alt="swing logo" height="50" width="100"></a>
</div>
<div class="col-md-5"></div>
</div><!--end of row-->
<div class="row">
<div class="col-md-5">
<ul class="nav nav-pills">
<li>
<button class="dropdown-toggle btn-primary btn-sm" data-toggle="dropdown" type="button">
<span class="glyphicon glyphicon-menu-hamburger"></span>
</button>
<ul class="dropdown-menu">
<li><p align="center">Projects List</p></li>
<li class="divider"></li>
<li><b>Project1</b></li>
<li><b>Project2</b></li>
<li><b>Project3</b></li>
<li><b>Project4</b></li>
<li><b>Project5</b></li>
</ul>
</li>
<li class="dropdown">
<button type="button" class="dropdown-toggle btn-primary btn-sm" data-toggle="dropdown">
<span class="glyphicon glyphicon-plus"></span>
</button>
<ul class="dropdown-menu">
<li><p align="center">Add</p></li>
<li class="divider"></li>
<li><b>New Project</b></li>
</ul>
</li>
<li>
<form class="navbar-search" id="srch" action="#">
<input type="text" class="form-control" placeholder="Search">
</li>
<li>
<button class="btn btn-primary btn-md" type="submit"><span class="glyphicon glyphicon-search"></span>Search</button>
</form>
</li>
</ul>
</div><!--end of col-md-5-->
<div class="col-md-4"></div><!--end of col-md-4-->
<div class="col-md-3">
<ul class="nav nav-pills">
<li>
<a class="btn btn-basic">hello!
<span class="badge">Abbas Kapasi</span>
</a>
</li>
<li class="dropdown">
<button class="dropdown-toggle btn-primary btn-sm" data-toggle="dropdown"><i class="glyphicon glyphicon-user"></i> <i class="glyphicon glyphicon-chevron-down"></i></button>
<ul class="dropdown-menu">
<li>Profile</li>
<li class="divider"></li>
<li>Logout</li>
</ul>
</li>
</ul>
</div><!--end of col-md-3-->
</div><!--end of nested row-->
</div><!--end of main container-->
</div><!--end of nav-->
</div><!--end of header-->
</body>
</html>
This causes following error:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Cannot locate BeanDefinitionParser for element [resources]
Offending resource: ServletContext resource [/WEB-INF/containers/dispatcher-servlet.xml]
Like in topic, Can I use Thymeleaf layout dialect with spring?
Do I have to use Spring Standard Dialect?
There is so many materials on web, which makes me really confused.
I've started with Layout dialect, but I cant get to work whole app.
Here is my template main file:
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml" xml:lang="pl" lang="pl" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title>DERP></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="all" href="../../css/template.css" th:href="#{/css/template.css}" />
<link rel="stylesheet" type="text/css" media="all" href="../../lib/font-awesome-4.2.0/css/font-awesome.min.css" th:href="#{/lib/font-awesome-4.2.0/css/font-awesome.min.css}" />
<link rel="stylesheet" type="text/css" media="all" href="../../lib/bootstrap-3.3.1-dist/css/themes/slate/bootstrap.min.css" th:href="#{/lib/bootstrap-3.3.1-dist/css/themes/slate/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" media="all" href="../../lib/animate/animate.css" th:href="#{/lib/animate/animate.css}" />
</head>
<body>
<div th:include="fragments/bodyHeader" th:remove="tag">
for prototyping
</div>
<div id="mainMenu">
<div class="navbar navbar-default">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">DERP</a>
</div>
<div class="navbar-collapse collapse navbar-responsive-collapse">
<ul class="nav navbar-nav">
<li class="active">Active</li>
<li>Link</li>
<li class="dropdown">
Dropdown <b class="caret"></b>
<ul class="dropdown-menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li class="divider"></li>
<li class="dropdown-header">Dropdown header</li>
<li>Separated link</li>
<li>One more separated link</li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<i class="fa fa-home"></i> Customer <b class="caret"></b>
<ul class="dropdown-menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li class="divider"></li>
<li>Separated link</li>
</ul>
</li>
<li class="dropdown">
<i class="fa fa-user"></i> User <b class="caret"></b>
<ul class="dropdown-menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li class="divider"></li>
<li>Separated link</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<!-- #mainMenu ENDS-->
<div layout:fragment="header">Static header</div>
<div layout:fragment="pageContent">Demo static page content</div>
<div id="pageFooter" class="panel panel-default">
<div class="panel-body">Copyright Daniel Korbel 2014</div>
</div>
<div id="javaScriptSection">
<script type="text/javascript" src="../../lib/jquery/jquery-2.1.1.min.js" th:src="#{lib/jquery/jquery-2.1.1.min.js}"></script>
<script type="text/javascript" src="../../js/template.js" th:src="#{/js/template.js}"></script>
<script type="text/javascript" src="../../lib/noty-2.3.1/js/noty/packaged/jquery.noty.packaged.min.js" th:src="#{/lib/noty-2.3.1/js/noty/packaged/jquery.noty.packaged.min.js}"></script>
<script type="text/javascript" src="../../lib/noty-2.3.1/js/noty/layouts/topRight.js" th:src="#{/lib/noty-2.3.1/js/noty/layouts/topRight.js}"></script>
<script type="text/javascript" src="../../js/notyStarter.js" th:src="#{/js/notyStarter.js}"></script>
<script type="text/javascript" src="../../lib/bootstrap-3.3.1-dist/js/bootstrap.min.js" th:src="#{/lib/bootstrap-3.3.1-dist/js/bootstrap.min.js}"></script>
</div>
</body>
</html>
and my sample body file which is returned by controller:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout/template">
<div layout:fragment="pageContent">
<p>LIST</p>
</div>
</html>
But unfortunatelly this code works only with Layout dialect.
Can anyone help me transform that code to work with spring standard dialect?
My thymeleaf config:
public class ThymeleafConfig {
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setOrder(1);
resolver.setCacheable(false);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setDialect(new SpringStandardDialect());
//templateEngine.setDialect(new LayoutDialect());
return templateEngine;
}
#Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
}
Adding the layoutdialect to the templateengine should be enough to get it working. Don't use setDialect. You should have an addDialect or setAdditionalDialects method or something like that. (I use the xml config so i don't know the exact names)
UPDATE: added xml config
<beans:bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<beans:property name="templateResolvers">
<beans:set>
<beans:ref bean="servletContextTemplateResolver" />
<beans:ref bean="classLoaderTemplateResolver" />
</beans:set>
</beans:property>
<beans:property name="dialects">
<beans:set>
<beans:ref bean="thymeleafSpringDialect" />
</beans:set>
</beans:property>
<beans:property name="additionalDialects">
<beans:set>
<beans:bean class="nz.net.ultraq.thymeleaf.LayoutDialect" />
<beans:bean
class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect" />
<beans:bean class="ch.mfrey.thymeleaf.extras.with.WithDialect" />
<beans:bean class="ch.mfrey.thymeleaf.extras.cache.CacheDialect" />
</beans:set>
</beans:property>
</beans:bean>