How to make thymeleaf spring security namespace available? - java

I've got a Spring Boot app. From what I understand a boot app will only need the dependency in the pom and all is great. Unfortunately, that's not the case and even when I overcomplicate my configuration it still doesn't work - I can't use the sec namespace in my pages.
In my page the first issue is the namespace URI:
I've tried every option available in the Intellij fix menu and can't get it.
I suppose the result of that issue is the fact that I can't use the sec namespace anywhere. The pictured example may indeed be an invalid use but I've used <div> as well which is straight from the Thymeleaf examples:
Many of the answers here and other sources are relying on xml configuration as well, which is of no use. Still, I've made Java-based beans based on those xml examples with no luck.
What steps are required to use spring security and thymeleaf integration in a spring boot app using only Java based configuration (if that)?
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<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.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
...
</dependencies>

I have encountered the same issue and for me it helped to define schema locations like this:
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.thymeleaf.org http://www.thymeleaf.org
http://www.ultraq.net.nz/thymeleaf/layout http://www.ultraq.net.nz/thymeleaf/layout
http://www.thymeleaf.org/thymeleaf-extras-springsecurity4 http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
...
This includes also additional dialects for layout and spring security 4 which you can remove if you are not using them.

Related

Spring boot doesn't identify html templates without Thymeleaf dependency

I am using spring-boot 2.5.0 and maven as dependency management tool. I have following dependencies as of now in my project.
"<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>"
I want to use jsp instead of thymeleaf but when I put my "index.html" file inside templates or static sub-folder of resources folder it doesn't recognize the html file and throws white label error.When I added the thymeleaf dependency it worked perfectly and recognized the html file. So, what should I do to make spring-boot detect my html file without adding thymeleaf dependency. By the way I have never used jsp before.
It seems you are missing either of the two things.
you should put below the property with the desired value in the property/yaml file
spring.mvc.view.prefix: <location of html/jsp>
spring.mvc.view.suffix: <.extension>
check at your controller whether you are sending the correct view name or not.

Setting up applicationContext.xml for a simple Spring app in Intellij Ultimate

I'm a complete newcomer to Spring and I'm trying to set up a simple Spring application which I'm following through an online tutorial. The tutor is using Eclipse however and IntelliJ is complaining
Cannot find the declaration of element 'beans'.
....from within applicationContext.xml
My only Spring POM dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
My applicationContext.xml
Do I have to setup this up from the 'Facets' context menu in Project Structure?? If so, how?
I have all the standard Spring plugins that come bundled in a typical Ultimate installation:
My project structure:
You have to use the following dependency also for Spring Beans apart from Spring Core.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>

Spring boot: 404 error when calling JSP using controller

I'm getting the following error when running my project using Spring Tool Suite,
But in case my problem is I have already added the appropriate dependencies to pom.XML file. So what could be the problem?
My pom.XML file dependencies as follows,
<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-starter-tomcat</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
My controller ApplicationController.java as follows,
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class ApplicationController {
#RequestMapping("/")
public String Welcome() {
return "welcomepage";
}
}
My vives are in src/main/webapp/WEB-INF/view/welcomepage.jsp you can look the tree view below,
And I have already changed the application.properties file as well. But still, I can't understand what is wrong.
My application.properties file as follows,
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
I just print hello in My welcomepage.jsp,
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
hello
</body>
</html>
Looks like you was very close to the working application. The main issue in your code is in <scope>provided</scope> for your Jasper dependency.
And also looks like you are running your code from eclipse IDE through the main method.
Long story short:
If you would like to run your application through the main method in MyApplication.java then just remove scope provided for the Jasper.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Or you can run your application exactly in that state like you have right now from the console:
mvn clean spring-boot:run
But I suggest to remove this scope so you could be able to run your code from IDE and from console. In addition to that looks like spring-boot-starter-tomcat dependency is redundant (it must be available within spring-boot-starter-web). In a nutshell please try to use following 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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
</project>
Hope my answer will help you.
You may also need to add this in pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
UPDATE 1:
JSP Limitation
When running a Spring Boot application that uses an embedded servlet container (and is packaged as an executable archive), there are some limitations in the JSP support.
With Jetty and Tomcat, it should work if you use war packaging. An
executable war will work when launched with java -jar, and will also be deployable to any standard container. JSPs are not supported when using an executable jar.
Undertow does not support JSPs.
Creating a custom error.jsp page does not override the default view
for error handling. Custom error pages should be used instead.
Scope
compile This is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.
provided This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
runtime This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
Also, Try to change the Following in tomcat-embed-jasper
Remove <scope>provided</scope> OR change the scope to compile <scope>compile</scope>
JSP Limitations
Spring Boot JSP 404
I was able to generate a jar from my application and then run it with java -jar myapp.jar But I only managed to run this jar with the version below spring-boot-starter-parent:
MyApp/pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
I researched in:
Spring Boot JSP 404

How to determine the <parent> dependency for a set of springframework dependencies

I like to know if below is possible and how.
I was following a tutorial for spring boot and it was mentioned there we can have a parent dependency.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
And then define the dependencies without the version number.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
This will add the dependencies version 1.5.6.RELEASE of spring-boot-starter and spring-boot-starter-web in to the projects dependencies.
Just like that I want to find what is the <parent> code snippet for the following dependencies I need to add in to a new project.
Dependencies in <groupId>org.springframework</groupId>. I need to use the version 4.3.9.RELEASE.
spring-context
spring-jdbc
spring-test
Thanks!
If you are using Spring Boot then these three dependencies will be provided for you by the following starters:
spring-test will be provided by spring-boot-starter-test
spring-context will be provided by spring-boot-starter-data-jpa
spring-jdbc will be provided by spring-boot-starter-jdbc
So, with the following parent:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
... if you add these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
... then you will get
spring-context
spring-jdbc
spring-test
However, Spring Boot 1.5.6.RELEASE depends on v4.3.10.RELEASE of those core Spring libraries not 4.3.9.RELEASE as suggested in your question. Typically, you would accept Spring's curation of dependencies so if Sping provides 4.3.10.RELEASE then either (a) you should use that version or (b) downgrade Spring Boot toa version which provides 4.3.9.RELEASE.
Read on for details on how to identify the correct starter for a given curated library ...
The spring-boot-starter-parent is a special starter that provides useful Maven defaults and a dependency-management section which defines numerous dependencies which you might want to use in your POM. These dependencies are often referred to as "curated" or "blessed" and since they are defined in a dependency-management section somewhere in the maven hierarchy you can refer to them in your POM without a version tag (i.e. they inherit the version from the dependency-management section entry.)
You can see the spring-boot-starter-parent POM here and peeking inside you can see that it references the spring-boot-dependencies POM here.
Looking at your question you mentioned that you can declare a dependency like so ...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
... this is because the spring-boot-dependencies POM declares the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${revision}</version>
</dependency>
So, the parent and the starters are just a means of wrapping up dependency declarations and making them easier for application developers to use. The Spring docs summarise this as:
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.
However, this does not mean that all dependencies must be declared via parents or starters so, if you are not using Spring Boot then you can declare a dependency without using a parent or a starter and what you have described in your question (declaring dependencies on 3 core Spring libraries) can be safely covered by simply depending on those 3 libraries explicitly. For example, just add the following to your your pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.9.RELEASE</version>
<scope>test</scope>
</dependency>
Since you are going though the tutorials I'm assuming you are new to spring.
The folks at spring were nice enough to setup a site that generates projects.
It is very easy to use. I recommend trying that while learning. Download a few apps with the dependencies you want and look at how they are set up.
Once you are comfortable and want to dive deeper, read #glytching's answer again, it is very good.
Use spring-framework-bom if you don't use Spring Boot and need Spring Framework dependencies only:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
In such case dependency would be without version was specified:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
Also, yet another option exists if you use Spring Boot but you don't want to use spring-boot-starter-parent as parent artifact:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
See Spring Boot docs for more details. An important note from the docs:
Each release of Spring Boot is associated with a base version of the Spring Framework so we highly recommend you to not specify its version on your own.
It means that you should use Spring Framework version is defined for Spring Boot.

Thymeleaf 3.0 Spring Boot + Security integration does not work

I struggle to get Thymeleaf to work with Spring Security in my Spring Boot 1.4.3 based project.
Tags like e.g.
<div sec:authorize="hasAuthority('ADMIN')">
are simply not parsed.
If I try to add the SpringSecurityDialect manually like this:
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
I am getting:
Exception in thread "main" java.lang.NoClassDefFoundError: org/thymeleaf/dialect/IExpressionEnhancingDialect
I have included the following in my dependencies:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
The SpringSecurityDialect does not seem to be added by the autoconfiguration.
After I add the Bean manually, I get the mentioned exception.
Is this a bug or am I missing something?
My Thymeleaf versions are:
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-extras-java8time.version>3.0.0.RELEASE</thymeleaf-extras-java8time.version>
<thymeleaf-layout-dialect.version>2.1.2</thymeleaf-layout-dialect.version>
To get it working, if you are using Thymeleaf 3.0.2 with Spring Boot 1.4, you need to force version 3.0.1.RELEASE of thymeleaf-extras-springsecurity4 (because it inherits version 2.1.2 which does not work in combination with Thymeleaf 3):
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.1.RELEASE</version>
</dependency>
The tags should be using the hasRole function.
<div sec:authorize="hasRole('ROLE_ADMIN')">
If you use Spring Boot 2.0.0.RELEASE:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
you need just the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
Version of thymeleaf-extras-springsecurity4 will be inherited from the spring-boot-starter-parent and would be 3.0.2.RELEASE.
Thanks to #yglodt for pointing this out.
Also in your templates add spring-security namespace xmlns:sec="http://www.thymeleaf.org/extras/spring-security" and use hasRole instead of hasAuthority value in <sec:authorize> tag:
<div sec:authorize="hasRole('ROLE_ADMIN')">
...
</div>
I used to have the same problem.
Thymeleaf SpringSecurity only works with versions 3.x.x of thymeleaf, and the version that's shipped with Spring-boot is something like 2.x.x atm.
Looking up how to add v3.x.x to my project brought me to the following documentation page:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-use-thymeleaf-3
So you just need to add your dependencies, and then add the following in your properties to override the default version of thymeleaf to your dependencies:
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>

Categories