I'm working on a webapp using Spring MVC and Thymeleaf with Java-configuration. In the template for the html page the language is set to be Swedish through this code:
<html lang="sv">
And the encoding is set to UTF-8 through this meta tag:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
But for some reason, that will not display the swedish letters.
I tried changing the <html> tag to the XHTML version xml:lang="en" but it makes no difference.
Since I'm still very new to Spring and Thymeleaf, I don't know where something might be wrong, or where the language/charset is supposed to be stated/set so I'm giving you the thymeleaf configuration code and the page controller:
#Configuration
public class ThymeleafConfig {
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setOrder(1);
resolver.setCacheable(false);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
return resolver;
}
}
Controller:
#Controller
public class IndexController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index() {
ModelAndView model = new ModelAndView();
model.setViewName("index");
return model;
}
}
I got proper encoding only when property characterEncoding was added to both ServletContextTemplateResolver and ThymeleafViewResolver.
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
...
<property name="characterEncoding" value="UTF-8"/>
</bean>
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
...
<property name="characterEncoding" value="UTF-8"/>
</bean>
Add the following line to templateResolver in ThymeleafConfig:
resolver.setCharacterEncoding("UTF-8");
As remarked in the docs setCharacterEncoding:
Specifies the character encoding to be set into the response when the
view is rendered.
Related
I want to add apache tiles in my spring boot application.
Like we configure prefix and suffix in application.properties file i want to know how we can configure tiles.xml as well.
I have added maven dependency of apache tiles in POM.xml file, But when i am returning the name of the tile definition from my controller its giving 404 error.
This is my POM.xml file
<!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-jsp -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.8</version>
</dependency>
This is my tiles.xml file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration
3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<definition name="home-page"
template="/WEB-INF/layout/layout.jsp">
<put-attribute name="body" value="/WEB-INF/pages/landing-page.jsp" />
<put-attribute name="script" value="" />
<put-attribute name="stylesheet" value="" />
</definition>
</tiles-definitions>
This is my controller method
#Controller
public class LandingPage {
#RequestMapping("/")
public String landingPage() {
return "home-page";
}
}
This is my TilesConfig.java file
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
#Configuration
public class TilesConfig {
#Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver tilesViewResolver = new
UrlBasedViewResolver();
tilesViewResolver.setViewClass(TilesView.class);
return tilesViewResolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
String[] tilesXml = { "WEB-INF/tiles.xml" };
tilesConfigurer.setDefinitions(tilesXml);
return tilesConfigurer;
}
}
First thing you need to do is to use #EnableWebMvc in your configuration.I have added in below configuration
Can you try adding the below configuration to your application
public class MvcWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
// Load database and spring security configuration
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebAppInitializer.class};
}
// Load spring web configuration
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "your component scan packages" })
public class WebMvcConfig implements WebMvcConfigurer {
/**
* Initialise Tiles on application startup and identify the location of the tiles configuration file, tiles.xml.
*
* #return tiles configurer
*/
#Bean
public TilesConfigurer tilesConfigurer() {
final TilesConfigurer configurer = new TilesConfigurer();
configurer.setDefinitions(new String[] { "WEB-INF/tiles.xml" });
configurer.setCheckRefresh(true);
return configurer;
}
/**
* Introduce a Tiles view resolver, this is a convenience implementation that extends URLBasedViewResolver.
*
* #return tiles view resolver
*/
#Bean
public TilesViewResolver tilesViewResolver() {
final TilesViewResolver resolver = new TilesViewResolver();
resolver.setViewClass(TilesView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Make sure you have static resources and views are in correct path.
You can configure the tiles view resolver as below.
#Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver tilesViewResolver = new UrlBasedViewResolver();
tilesViewResolver.setViewClass(TilesView.class);
return tilesViewResolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
String[] tilesXml = { "WEB-INF/tiles.xml" };
tilesConfigurer.setDefinitions(tilesXml);
return tilesConfigurer;
}
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'm trying to change language using <spring:message> tag. But it doesn't get recognized.
language.jsp
<%# taglib prefix="spring"
uri="http://www.springframework.org/tags" %>
<html>
<body>
<h1><spring:message code="home.title" /></h1>
<p><spring:message code="home.intro" /></p>
<p>
English |
French
</p>
</body>
</html>
AppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.dilini.controller", "com.dilini.service"})
#Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver jspViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public HandlerInterceptor performanceInterceptor() {
PerformanceInterceptor interceptor;
interceptor = new PerformanceInterceptor();
return interceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(performanceInterceptor()).addPathPatterns("/user/*");
registry.addInterceptor(localeChangeInterceptor());
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:/messages");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
#Bean
public HandlerInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
return interceptor;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setDefaultLocale(new Locale("en"));
return localeResolver;
}
}
src/main/resources/messages/en.properties
home.title=Home
home.intro= this is my magnificent intro
Likewise the french.
src/main/resources/messages/fr.properties
home.title=Accueil
home.intro=Splendide page d'accueil,
Do I need to add another dependency for this feature? Or there is any issue is the code?
Please help
try this below code
#Bean(name = "localeResolver")
public LocaleResolver getLocaleResolver() {
CookieLocaleResolver resolver= new CookieLocaleResolver();
resolver.setCookieDomain("myAppLocaleCookie");
resolver.setCookieMaxAge(600);
return resolver;
}
#Bean(name = "messageSource")
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageResource= new ReloadableResourceBundleMessageSource();
// For example: i18n/messages_en.properties
// For example: i18n/messages_fr.properties
messageResource.setBasename("classpath:i18n/messages");
messageResource.setDefaultEncoding("UTF-8");
return messageResource;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
localeInterceptor.setParamName("lang");
registry.addInterceptor(localeInterceptor).addPathPatterns("/*");
}
Note : messages_en.properties and messages_fr.properties should be present into src/main/resources/i18n
In your appconfig i don't see the interceptor registration. You simply defined it but you never registered it. You should override the addInterceptors method
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
Try to add it and check if it works
In your src/main/resources/messages/ be sur to create both i18 files (en and fr named as below ):
in your MessageSource you just set the basename to messages => messageSource.setBasename("classpath:/messages");
so your local files should be named messages_[local].properties (spring will search for local names file as set in the as .setBasename() )
as below
messages_en.properties that contains :
home.title=Home
home.intro= this is my magnificent intro
and messages_fr.properties that
home.title=Accueil
home.intro= ceci est ma magnifique intro
It should work
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
Getting javax.servlet.ServletException: Could not resolve view with name 'home' in servlet with name 'dispatcher' when running a web app. To me the #RequestMapping, tiles configuration and mapping looks good but still getting an error.
Here is the WebAppInitializr.java
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootConfig.class, MessageSourceConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(WebMvcConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
And the WebAppConfig
#EnableWebMvc
#ComponentScan(basePackages = { "com.examples" })
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
private static final String TILES_VIEW_RESOLVER_DEFINITION = "/WEB-INF/tiles/tiles_configuration.xml";
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("/assets/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public TilesViewResolver tilesViewResolver() {
TilesViewResolver tilesViewResolver = new TilesViewResolver();
tilesViewResolver.setOrder(2);
return tilesViewResolver;
}
#Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(TilesView.class);
return viewResolver;
}
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setDefinitions(new String[] { TILES_VIEW_RESOLVER_DEFINITION });
tilesConfigurer.setCheckRefresh(true);
return tilesConfigurer;
}
}
The request mapping i have in the controller is:
#RequestMapping(value = "/", method = RequestMethod.GET)
And the tiles definition:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<definition name="defaultTemplate" template="/WEB-INF/views/templates/baseLayout.jsp">
<put-attribute name="meta" value="/WEB-INF/views/templates/meta.jsp" />
<put-attribute name="navbar" value="/WEB-INF/views/templates/navbar.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/WEB-INF/views/templates/footer.jsp" />
</definition>
<definition name="home" extends="defaultTemplate">
<put-attribute name="title" value="Home" />
<put-attribute name="body" value="/WEB-INF/views/home.jsp" />
</definition>
</tiles-definitions>
Any help resolving this issue would be highly appreciated.
In your tile definition file you put the title attribute but in the your baseLayout.jsp file you didn't placed it. You need to add the following line of code inside your <title> element of the baseLayout.jsp file
<title><tiles:getAsString name="title"/></title>