i am trying to use thymeleaf 3.0.7.RELEASEwith spring mvc java based configuration.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.sagar")
public class MvcConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware{
#Autowired
RoleToUserProfileConverter roleToUserProfileConverter;
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
methods inside springsecurity configuration class.
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
throws Exception{
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers( "/admin/list")
.access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
.antMatchers("/newuser/**", "/delete-user-*").access("hasRole
('ADMIN')").antMatchers("/edit-user-*")
.access("hasRole('ADMIN') or hasRole('DBA')").and().formLogin()
.loginPage("/login")
.loginProcessingUrl("/login").usernameParameter("ssoId").
passwordParameter("password").and()
.rememberMe().rememberMeParameter("remember-me").
tokenRepository(tokenRepository)
.tokenValiditySeconds(86400).and().csrf().and().exceptionHandling()
.accessDeniedPage("/Access_Denied");
}
and my home.html file
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
this is home page using thymeleaf
</body>
</html>
my pom.xml dependencies includes
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
the spring security version is 4.2.3.RELEASE and spring version is 4.3.9.RELEASE
the errors i am getting are:-
Message Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing
(template: "ServletContext resource [/WEB-INF/templates/home]")
Root Cause
java.io.FileNotFoundException: Could not open ServletContext
resource [/WEB-INF/templates/home]
Root Cause
org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing
(template: "ServletContext resource [/WEB-INF/templates/home]")
The templateResolver method needs to be fixed.
Try setting suffix
resolver.setSuffix(".html");
Try setting correct TemplateMode
resolver.setTemplateMode("HTML5");
I think this should solve the problem
Related
I'm trying to load static resources to thymeleaf html file. But resources aren't loaded.Does anyone knows what Am i doing wrong here....
I'm using Spring Java Config here. This is my Config class
#Configuration
#EnableScheduling
#ComponentScan(basePackages = "test.controller")
public class ControllerConfig extends WebMvcConfigurationSupport {
private static final Logger log = LoggerFactory.getLogger(ControllerConfig.class);
#Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> _converters) {
_converters.add(getMappingJackson2HttpMessageConverter());
addDefaultHttpMessageConverters(_converters);
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(getObjectMapper());
return converter;
}
#Bean
public ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
return objectMapper;
}
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCacheable(false);
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
return viewResolver;
}
}
This is my HTML page.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8"/>
<title th:text="'Hello ' + ${name} + '!'"></title>
<link th:href="#{/resources/css/main.css}" rel="stylesheet"/>
</head>
<body>
<h2 class="hello-title" th:text="'Hello ' + ${name} + '!'"></h2>
<script th:src="#{/resources/js/main.js}"></script>
</body>
</html>
This is how my folder structure goes for static resources which needed to be loaded.
I found resources on the internet where WebMvcConfigurerAdapter had been used. but I'm using WebMvcConfigurationSupport instead. I do'nt have the luxury to change this.
Thymeleaf dependency I have added is
compile group: 'org.thymeleaf', name: 'thymeleaf-spring4', version: '2.1.2.RELEASE'
compile "org.springframework:spring-webmvc:${springVersion}"
springVersion = 4.0.6.RELEASE
When I run the project and loaded the HTML file CSS aren't applied. But HTML is loading fine as expected :(
Try configuring your resources like this:
registry.addResourceHandler("/**").addResourceLocations("classpath:/resources/")
And linking your css like this:
<link rel="stylesheet" th:href="#{/css/main.css}"/>
I Think Thymeleaf doesn't know when user is logged in , I have hidden two <a> tags from users who are authenticated but they still are displayed.
pom.xml :
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Here's the code for problem - hidding two anchor tags from users
who are authenticated :
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
...
...
<div sec:authorize="isAnonymous()">
<a th:href="#{/login}">Log in</a>
<br>
<a th:href="#{/register}">Register</a>
</div>
<br>
<a th:href="#{/recipeList}">List Page</a>
Even after I log in , I still see the "login" and "register" tags
And here's the configuration, if its useful :
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public DataSource dataSource;
#Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Bean
public JdbcUserDetailsManager jdbcUserDetailsManager() throws Exception{
JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
jdbcUserDetailsManager.setDataSource(dataSource);
return jdbcUserDetailsManager;
}
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception{
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/register").permitAll()
.antMatchers("/recipeList").permitAll()
.antMatchers("/foodDescription/**").permitAll()
.antMatchers("/addNew/**").hasAnyRole("ADMIN","USER")
.antMatchers("/delete/**").hasRole("ADMIN")
.antMatchers("/edit/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/").permitAll();
http.csrf().disable();
}
}
My guess is that Thymeleaf doesn't know when user is logged in, if any other class is needed from my code, I'll edit it . Been stuck on this forever now.
I assume that you are using Spring Boot 2.1.x
Then you have to use the version 5:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
I am running a spring boot application. When I enter the URL http://localhost:8080 (or http://localhost:8080/index.jsp)I expect the index.jsp file to load, but I am getting the following error on the browser.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Mar 05 21:56:33 IST 2016
There was an unexpected error (type=Not Found, status=404).
No message available
My index.jsp is present in webContent directory and my AppConfig class is as follows
#EnableJpaRepositories("com.test.repository")
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages="com.test.domain")
#PropertySource(value={"classpath:application.properties"})
public class AppConfig {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() {
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName(environment.getRequiredProperty("spring.datasource.driver-class-name"));
datasource.setUrl(environment.getRequiredProperty("spring.datasource.url"));
datasource.setUsername(environment.getRequiredProperty("spring.datasource.username"));
datasource.setPassword(environment.getRequiredProperty("spring.datasource.password"));
return datasource;
}
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public WebMvcConfigurerAdapter forwarderToIndex() {
return new WebMvcConfigurerAdapter() {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward://index.jsp");
}
};
}
}
I also referred this which didn't help me. How do I eliminate this error and redirect to index.jsp?
You can remove Error page auto configuration by using
exclude = { ErrorMvcAutoConfiguration.class }
in your #SpringBootApplication annotation
i.e
#SpringBootApplication(scanBasePackages = { "com.myapp.app" }, exclude = { ErrorMvcAutoConfiguration.class })
if you are not using
#SpringBootApplication you can do that by placing in your configuration class
#EnableAutoConfiguration( exclude = { ErrorMvcAutoConfiguration.class })
you can add tomcat jasper dependency in your pom.xml file
<dependency>
<groupId> org.apache.tomcat </groupId>
<artifactId> tomcat-jasper </artifactId>
<version>9.0.5</version>
</dependency>
I'm trying to put spring security into my spring mvc project using java configuration, however, I can still access all the pages without any spring security interception. Can anybody give some help? Thank you. (I'm using weblogic 12c)
part of pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
WebAppInitializer.java
package com.home.config;
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootCtx = new AnnotationConfigWebApplicationContext();
rootCtx.register(HomeConfig.class);
container.addListener(new ContextLoaderListener(rootCtx));
container.setInitParameter("defaultHtmlEscape", "true");
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(WebConfig.class);
ServletRegistration.Dynamic servlet = container.addServlet(
"spring-dispatcher", new DispatcherServlet(webCtx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
WebConfig.java
package com.home.config;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.home.controllers", "com.home.websecurity" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
// Configure static content handling
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
SecurityConfig.java
package com.home.websecurity;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("user").password("abc123")
.roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("root123")
.roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin()
.and().httpBasic();
}
}
SecurityWebInitializer.java
package com.home.websecurity;
public class SecurityWebInitializer extends
AbstractSecurityWebApplicationInitializer {
}
I spent a long time try to get Spring 4 to work with Weblogic 12c. What works for me in this case is to add the following code to your onStartup() method in WebAppInitializer class:
Dynamic registration = context.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
registration.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
and get rid of the SecurityWebInitializer class. I also have to explicitly import the security config to the root config class.
This has been a quite common problem here in stackOverflow, but none of the topics of the same problem solves mine.
We have a template configuration that uses xml config, but now we're trying to move away from that and start using Java config.
So I have a new project using Java config and Spring Boot. We're also using JSP and Tiles 3.
Problem is: it fails to render our admin login page.
Here is the code:
Main config class:
#SpringBootApplication
#EnableScheduling
#Import(OnAdminBeans.class)
public class AppConfig extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AppConfig.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppConfig.class);
}
}
The AppConfig.class is is the main package. Through the #ComponentScan that #SpringBootApplication brings, it scans the other configurations that are on mainpackage.config, so it imports the view config class:
#Configuration
#EnableWebMvc
public class ViewConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/adm/static/**").addResourceLocations("/adm/static/");
}
// #Override
// public void addViewControllers(ViewControllerRegistry registry) {
// registry.addViewController("/adm/login").setViewName("login-template-tiles");
// }
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.viewResolver(viewResolver());
registry.viewResolver(jspViewResolver());
registry.viewResolver(tilesViewResolver());
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setCookieName("locale");
localeResolver.setCookieMaxAge(30);
localeResolver.setDefaultLocale(new Locale("pt", "BR"));
return localeResolver;
}
#Bean
public MultipleViewResolver viewResolver() {
Map<String, ViewResolver> viewsResolvers = new HashMap<String, ViewResolver>();
viewsResolvers.put(MultipleViewResolver.ViewType.JSP.getKey(), jspViewResolver());
viewsResolvers.put(MultipleViewResolver.ViewType.TILES.getKey(), tilesViewResolver());
MultipleViewResolver viewResolver = new MultipleViewResolver();
viewResolver.setViewsResolvers(viewsResolvers);
viewResolver.setOrder(1);
return viewResolver;
}
#Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
viewResolver.setOrder(2);
return viewResolver;
}
#Bean
public UrlBasedViewResolver tilesViewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(TilesView.class);
viewResolver.setOrder(3);
return viewResolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer configurer = new TilesConfigurer();
configurer.setDefinitions("/WEB-INF/tile-defs/tiles-definitions.xml");
return configurer;
}
}
The LoginController.class is defined as:
#Controller
#RequestMapping(value = "/adm")
public class LoginController {
#RequestMapping(value = "/login")
public ModelAndView login() {
return new ModelAndView("login-template-tiles");
}
}
And in tiles-definitions.xml I have the following definition for login-template-tiles:
<definition name="login-template-tiles" template="/WEB-INF/jsp/adm/templates/login-template.jsp">
<put-attribute name="admin-title" value="Admin" />
<put-attribute name="content" value="/WEB-INF/jsp/adm/templates/sections/login/index.jsp" />
</definition>
Note that both files exist.
Given all that the LoginController.login() does get called when i try to access /adm/login. But it fails to find the proper jsp file, aparently.
It returns a 404. With TRACE enabled, I get the following log:
DispatcherServlet with name 'dispatcherServlet' processing GET request for [/WEB-INF/jsp/adm/templates/login-template.jsp]
Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#2118c09a] in DispatcherServlet with name 'dispatcherServlet'
Looking up handler method for path /WEB-INF/jsp/adm/templates/login-template.jsp
Did not find handler method for [/WEB-INF/jsp/adm/templates/login-template.jsp]
Testing handler map [org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping#2c148974] in DispatcherServlet with name 'dispatcherServlet'
No handler mapping found for [/WEB-INF/jsp/adm/templates/login-template.jsp]
Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#784c3547] in DispatcherServlet with name 'dispatcherServlet'
No handler mapping found for [/WEB-INF/jsp/adm/templates/login-template.jsp]
Testing handler map [org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping#533e0604] in DispatcherServlet with name 'dispatcherServlet'
Testing handler map [org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping#cfd1b4e] in DispatcherServlet with name 'dispatcherServlet'
No mapping found for HTTP request with URI [/WEB-INF/jsp/adm/templates/login-template.jsp] in DispatcherServlet with name 'dispatcherServlet'
Any suggestions are appreciated!
EDIT:
Ok. By debugging, I found out that it has something to do with the embedded Tomcat. Other than that, I have no clue what is going on.
EDIT 2:
Found that the problem is in org.springframework.web.servlet.DispatcherServlet#getHandler. It simply doesn't find a HandlerMapping for that request. Do I have to register one?
OK! Found the problem.
This link helped me: https://samerabdelkafi.wordpress.com/2014/08/03/spring-mvc-full-java-based-config/
More specifically this configuration:
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
By setting a default handler, I would no longer get a white page but instead the JSP code as html, which clearly tells me that the JSP was being found but not rendered.
So the answer was on this page: JSP file not rendering in Spring Boot web application
I was missing the tomcat-embed-jasper artifact.
Add below dependency to your pom.xml
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
The tips here helped me when I got stuck with a similar problem. I fixed it after adding this fragment on my configuration
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}