Thymeleaf View Resolver with SpringMVC webapp - spring-mvc

How if one can use ThymeleafViewResolver as a defalt view resolver.
Currentely my WebMvcConfig looks like this
#Configuration
#ComponentScan(basePackages="com.greatLearning.ticketAPI.controller")
public class WebMvcConfig implements WebMvcConfigurer {
#Autowired
ApplicationContext applicationContext;
// #Override
// public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// configurer.enable();
// }
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
//Thymeleaf ViewResolver
#Bean
public SpringResourceTemplateResolver templateResolver(){
// SpringResourceTemplateResolver automatically integrates with Spring's own
// resource resolution infrastructure, which is highly recommended.
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
// HTML is the default value, added here for the sake of clarity.
templateResolver.setTemplateMode(TemplateMode.HTML);
// Template cache is true by default. Set to false if you want
// templates to be automatically updated when modified.
templateResolver.setCacheable(true);
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine automatically applies SpringStandardDialect and
// enables Spring's own MessageSource message resolution mechanisms.
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// Enabling the SpringEL compiler with Spring 4.2.4 or newer can
// speed up execution in most scenarios, but might be incompatible
// with specific cases when expressions in one template are reused
// across different data types, so this flag is "false" by default
// for safer backwards compatibility.
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Bean
public ThymeleafViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
// NOTE 'order' and 'viewNames' are optional
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
for *.jsp view it is working just fine, but I want to use Thymeleaf to resolve my .html templates becasue I don't want to use *.jsp .
One thing to note is that in my controller
TestController.java
#RequestMapping("/hello")
public String method1() {
return "hello";
}
#RequestMapping("/hello2")
#ResponseBody
public String method2() {
return "hello"; //This works fine
}
when I hit /hello api this is what I get
How do I configre viewResolver so that spring picks up ThymeleafViewResolver to resolve html rather than jsp

Problem Solved!!!!!
Here is what I did after an hour of debugging the libraries
in WebMvcConfig.java I revomed the public InternalResourceViewResolver resolver() method as it is sed to configure jsp.
Now in ThymeleafViewResolver viewResolver() remove these two:
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
got help through debgging and [this post](Problem Solved!!!!!
Here is what I did after an hour of debugging the libraries
in WebMvcConfig.java I revomed the public InternalResourceViewResolver resolver() method as it is sed to configure jsp.
Now in ThymeleafViewResolver viewResolver() remove these two:
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
got help through debgging and this post.
As to why I will answer if anyone is interested. :)

Related

How do I using RedisMessageListenerContainer in configuration class

I am using spring-MVC and spring-data-redis to control Redis-cluster pool.
When I using jedisCluster.subscribe(new JedisPubSubListener(), "bb");
my application will stock in this code(I try to use thread but the other one can't get the instance in #autowerid).
I google a lot of way point me to using spring-boot .
but I can change the structure in our project.
So I think when spring init I can register a listener to use.
But I can run sauce in my original code.
Can someone make an example for me if I using this following code :
#Configuration
public class RedisClusterConfig {
private List<String> redisNodes(){
return Arrays.asList(redisNode.split(","));
}
#Bean
JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
jedisPoolConfig.setTestOnReturn(testOnReturn);
jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
#Bean
RedisConnectionFactory redisClusterConnectionFactory(JedisPoolConfig
jedisPoolConfig){
JedisConnectionFactory redisConnectionFactory = new
JedisConnectionFactory(new RedisClusterConfiguration(redisNodes()));
redisConnectionFactory.setPoolConfig(jedisPoolConfig);
return redisConnectionFactory;
}
}
this is how I setting in my configuration.
#Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(consumerRedis(),topic());
return container;
}
#Bean
public ConsumerRedisListener consumerRedis() {
return new ConsumerRedisListener();//this class implements MessageListener
}
#Bean
public ChannelTopic topic() {
return new ChannelTopic("channel");
}

addResourceHandler #EnableWebMvc setup

My handler was working prior to some dependency updates and ditching of the XML in my app. But now I get this error
org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /resources/img/logo.png
My view resolver is working fine, my controller is pointing to the right places it is just my css/js that doesn't seem to map.
public class ConfigClass {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
WebMvcConfigurationSupport appears to be essential.
public class ConfigClass extends WebMvcConfigurationSupport{
//Rest here
}
EDIT
The initial answer was based on an amateur "cached" answer. The actual solution was using
public class ConfigClass extends WebMvcConfigurerAdapter {
However, this is now deprecated. Am looking into an answer for that.

thymeleaf 3 spring 5 load css

I'm trying to configure Spring5 and Thymeleaf3 togheter.
I'm working on Eclipse, I build with clean install and run the app with springboot:run.
I've setup a controller and a couple of template and css but it seems that thymeleaf cannot find the css, in the browser it shows the template (es. 'panda.html') without loading the css but if I open manually the .html the browser load also the .css . What i need to add to my code?
this is the mapping
#Controller
public class MyController {
#Autowired
UtentiRepository utentiRepository;
#GetMapping("/gab")
public String panda(Model model) {
return "panda";
}
and this is the template resolver
#Bean
public SpringResourceTemplateResolver templatecssResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/static/css/");
templateResolver.setSuffix(".css");
return templateResolver;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templatecssResolver());
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
You've to override the addResourceHandlers(..) method of the you calls that implements the WebMvcConfigurerAdapter not as a bean (SpringResourceTemplateResolver )
SO just add the overiding method
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**")
.addResourceLocations("classpath:/static/css/");
}
in your template use
<link href="<c:url value="/css/style.css" />" rel="stylesheet">
or using themleaf
<link th:href="#{/css/style.css}" />" rel="stylesheet">

Spring Boot adding thymeleaf-layout-dialect

I am using spring boot (v1.5.3.BUILD-SNAPSHOT)
I am new to spring boot.
Using gradle
Note that the normal thymeleaf dialect works fine (th:...)
spring-boot-starter-thymeleaf\1.5.3.BUILD-SNAPSHOT
I want to add thymeleaf-layout-dialect
I added the dependency
compile('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect')
the documentation says to add the dialect by doing the following
TemplateEngine templateEngine = new TemplateEngine(); // Or
SpringTemplateEngine for Spring config
templateEngine.addDialect(new LayoutDialect());
So i added a configuration class
#Configuration
public class MyConfiguration {
#Bean
public SpringTemplateEngine templateEngine(){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addDialect(new LayoutDialect());
return templateEngine;
}
}
but when I try running the app I get the following error
org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set
at org.thymeleaf.Configuration.initialize(Configuration.java:203) ~[thymeleaf-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.TemplateEngine.initialize(TemplateEngine.java:827) ~[thymeleaf-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:203) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
Can someone tell me how to add the thymeleaf-layout-dialect correctly?
The issue is:
org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set
To integrate Thymeleaf with Spring, you need to configure 3 beans:
ThymeleafViewResolver Bean - You would be set it with a template engine
SpringTemplateEngine Bean - You would be set it with a template resolver
TemplateResolver Bean
In your templateEngine bean you didn't set any template resolver, so you might change your templateEngine() method as following:
#Bean
public SpringTemplateEngine templateEngine(TemplateResolver templateResolver){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
templateEngine.addDialect(new LayoutDialect());
return templateEngine;
}
Spring will provide you with a templateResolver bean of SpringTemplateEngine.
BTW If you define spring-boot-starter-thymeleaf as dependency, it will provide thymeleaf-layout-dialect as a dependency with the convenient version, then Spring will use ThymeleafAutoConfiguration.java - Spring Boot 1.5.x to configure a default beans for the three required beans.
For example:
LayoutDialect bean is define here ThymeleafWebLayoutConfiguration.ThymeleafWebLayoutConfiguration():
#Configuration
#ConditionalOnClass(name = "nz.net.ultraq.thymeleaf.LayoutDialect")
protected static class ThymeleafWebLayoutConfiguration {
#Bean
#ConditionalOnMissingBean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
}
SpringTemplateEngine bean is defined with a template resolver and dialect from here ThymeleafWebLayoutConfiguration.ThymeleafDefaultConfiguration():
#Configuration
#ConditionalOnMissingBean(SpringTemplateEngine.class)
protected static class ThymeleafDefaultConfiguration {
private final Collection<ITemplateResolver> templateResolvers;
private final Collection<IDialect> dialects;
public ThymeleafDefaultConfiguration(
Collection<ITemplateResolver> templateResolvers,
ObjectProvider<Collection<IDialect>> dialectsProvider) {
this.templateResolvers = templateResolvers;
this.dialects = dialectsProvider.getIfAvailable();
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
for (ITemplateResolver templateResolver : this.templateResolvers) {
engine.addTemplateResolver(templateResolver);
}
if (!CollectionUtils.isEmpty(this.dialects)) {
for (IDialect dialect : this.dialects) {
engine.addDialect(dialect);
}
}
return engine;
}
}
And finally a thymeleafViewResolver bean is defined here AbstractThymeleafViewResolverConfiguration.thymeleafViewResolver():
#Bean
#ConditionalOnMissingBean(name = "thymeleafViewResolver")
#ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
configureTemplateEngine(resolver, this.templateEngine);
resolver.setCharacterEncoding(this.properties.getEncoding().name());
resolver.setContentType(appendCharset(this.properties.getContentType(),
resolver.getCharacterEncoding()));
resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
resolver.setViewNames(this.properties.getViewNames());
// This resolver acts as a fallback resolver (e.g. like a
// InternalResourceViewResolver) so it needs to have low precedence
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
resolver.setCache(this.properties.isCache());
return resolver;
}
which is extended by ThymeleafAutoConfiguration.Thymeleaf2ViewResolverConfiguration:
#Bean
#ConditionalOnMissingBean(name = "thymeleafViewResolver")
#ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
configureTemplateEngine(resolver, this.templateEngine);
resolver.setCharacterEncoding(this.properties.getEncoding().name());
resolver.setContentType(appendCharset(this.properties.getContentType(),
resolver.getCharacterEncoding()));
resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
resolver.setViewNames(this.properties.getViewNames());
// This resolver acts as a fallback resolver (e.g. like a
// InternalResourceViewResolver) so it needs to have low precedence
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
resolver.setCache(this.properties.isCache());
return resolver;
}
Hope it is clear now.

Spring MVC InternalResourceViewResolver

I'm a newer of Spring MVC , and I'm trying to config a simple controller like below ,but when i test it. I got
javax.servlet.ServletException: Circular view path [index]: would dispatch back to the current handler URL [/index] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
Here is my WebConfig.java Code:
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
Here is my IndexController.java Code:
#Controller
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method = RequestMethod.GET)
public String index() {
return "index";
}
}
Here is my Test Fiel :
public class TestIndexController {
#Test
public void testIndexController() throws Exception {
IndexController indexController = new IndexController();
MockMvc mockMvc = standaloneSetup(indexController).build();
mockMvc.perform(get("/index")).andExpect(view().name("index"));
}
}
Every time when i changed the get("/index") to get("/index.jsp") ,i passed the test. but i just can't figure it out, please help me out
In your test setup, you create an instance of the Controller under test, but the context created for the test has no knowledge of the existence of your WebConfig and therefore, no instance of your ViewResolver.
Here is a quick fix :
public void testIndexController() throws Exception {
IndexController indexController = new IndexController();
MockMvc mockMvc = standaloneSetup(indexController)
setViewResolvers((new WebConfig()).viewResolver()).build();
mockMvc.perform(get("/index")).andExpect(view().name("index"));
}
If you don't want to access WebConfig in your test class, you can also create a new instance of ViewResolver and add it to your mockMvc setup.
Hope this helps.

Resources