Static files can not found Spring MVC + Thymeleaf - java

I have a spring application which is a starting project. I used Thymeleaf as template engine. But i have problem which is i can not reach to the static files such as CSS or javascript. This is my file structure for this application.
This is the configuration file for Thymeleaf engine. And i also tried to add resource handling which is : SpringBoot with Thymeleaf - css not found
package com.ggk.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
#Configuration
#EnableWebMvc
#ComponentScan("com.ggk")
public class ThymeleafConfig extends WebMvcConfigurerAdapter {
#Bean
public ServletContextTemplateResolver servletContextTemplateResolver() {
ServletContextTemplateResolver servletContextTemplateResolver = new ServletContextTemplateResolver();
servletContextTemplateResolver.setPrefix("/WEB-INF/templates/");
servletContextTemplateResolver.setSuffix(".html");
servletContextTemplateResolver.setTemplateMode("HTML5");
servletContextTemplateResolver.setCacheable(false);
return servletContextTemplateResolver;
}
#Bean
#Autowired
public SpringTemplateEngine springTemplateEngine(ServletContextTemplateResolver servletContextTemplateResolver) {
SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
springTemplateEngine.setTemplateResolver(servletContextTemplateResolver);
return springTemplateEngine;
}
#Bean
#Autowired
public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine springTemplateEngine) {
ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
thymeleafViewResolver.setTemplateEngine(springTemplateEngine);
return thymeleafViewResolver;
}
}
here is my index.html adding css files.
<link rel="stylesheet" href="../css/animate.css" th:href="#{/css/animate.css}" type="text/css"/>

I guess you cannot view the static resources directly via chrome as well, like:
http://<domain_name>:<port>/<context_root>/css/animate.css
I think it gives you a 404 error. If this is the case, that means your app needs a configuration to serve static resources. Basically you need to add a ResourceHandler to your config. See following link for an example:
https://stackoverflow.com/a/30663486/878361
In summary you need to:
extend WebMvcConfigurerAdapter (which you've already done)
override addResourceHandlers method and add your resource locations like follows:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}

Move css and images to webapp.

Related

405 error code on static html spring boot

I am trying to return a static html(index.html) page using spring boot but I am alway getting a 405 error whem I trying (http://localhost:8080/). Strange fact is that debugger enters index() method.
HomeController:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "index.html";
}
}
I have tried to return "index.html" and "index" strings.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
#SpringBootApplication
public class Application {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext
= SpringApplication.run(Application.class, args);
}
}
location of html file is:
src\main\resources\public\index.html
here goes a part of startup logger output:
INFO 8284 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/],methods=[GET]}" onto public java.lang.String com.acs.map.controller.HomeController.index()
Screanshot of an error
and i am running project with gradle: gradle bootRun
Logger message after request:
WARN 3988 --- [nio-8080-exec-6] o.s.web.servlet.PageNotFound : Request method 'GET' not supported
Also I have tried with and without this configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
registry.addResourceHandler("/resources/public/**").addResourceLocations("classpath:/resources/public/");
super.addResourceHandlers(registry);
}
#Bean
public ViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(InternalResourceView.class);
return viewResolver;
}
}
By default Spring Boot will serve static content from a directory called /static (or /public or /resources or /META-INF/resources). I did a quick check by following the below structure and was successful.
So I believe by extending WebMvcConfigurerAdapter class like below and it should return static content using your current controller code (without the WebConfig class).You can use viewResolver as well to map between view names and actual views as well by further modifying your code.
#SpringBootApplication
public class Application extends WebMvcConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Here are my project dependencies

The type WebMvcConfigurerAdapter is deprecated

I just migrate to spring mvc version 5.0.1.RELEASE but suddenly in eclipse STS WebMvcConfigurerAdapter is marked as deprecated
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
// to serve static .html pages...
registry.addResourceHandler("/static/**").addResourceLocations("/resources/static/");
}
....
}
How can i remove this!
Since Spring 5 you just need to implement the interface WebMvcConfigurer:
public class MvcConfig implements WebMvcConfigurer {
This is because Java 8 introduced default methods on interfaces which cover the functionality of the WebMvcConfigurerAdapter class
See here:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.html
I have been working on Swagger equivalent documentation library called Springfox nowadays and I found that in the Spring 5.0.8 (running at present), interface WebMvcConfigurer has been implemented by class WebMvcConfigurationSupport class which we can directly extend.
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
public class WebConfig extends WebMvcConfigurationSupport { }
And this is how I have used it for setting my resource handling mechanism as follows -
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
In Spring every request will go through the DispatcherServlet. To avoid Static file request through DispatcherServlet(Front contoller) we configure MVC Static content.
Spring 3.1. introduced the ResourceHandlerRegistry to configure ResourceHttpRequestHandlers for serving static resources from the classpath, the WAR, or the file system. We can configure the ResourceHandlerRegistry programmatically inside our web context configuration class.
we have added the /js/** pattern to the ResourceHandler, lets include the foo.js resource located in the webapp/js/ directory
we have added the /resources/static/** pattern to the ResourceHandler, lets include the foo.html resource located in the webapp/resources/ directory
#Configuration
#EnableWebMvc
public class StaticResourceConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
System.out.println("WebMvcConfigurer - addResourceHandlers() function get loaded...");
registry.addResourceHandler("/resources/static/**")
.addResourceLocations("/resources/");
registry
.addResourceHandler("/js/**")
.addResourceLocations("/js/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new GzipResourceResolver())
.addResolver(new PathResourceResolver());
}
}
XML Configuration
<mvc:annotation-driven />
<mvc:resources mapping="/staticFiles/path/**" location="/staticFilesFolder/js/"
cache-period="60"/>
Spring Boot MVC Static Content if the file is located in the WAR’s webapp/resources folder.
spring.mvc.static-path-pattern=/resources/static/**
Use org.springframework.web.servlet.config.annotation.WebMvcConfigurer
With Spring Boot 2.1.4.RELEASE (Spring Framework 5.1.6.RELEASE), do like this
package vn.bkit;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; // Deprecated.
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
public class MvcConfiguration implements WebMvcConfigurer {
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}

Spring #RequestMapping, 404 error

So, I'm trying to learn Spring Framework, but currently I'm stuck on this problem, for some reason my mappings don't work and when I try to access that address I'm getting a 404 error.
Can someone please clarify what I'm doing wrong (both in usage of spring classes and the source of the problem I have described above)?
I'm configuring spring using the example shown in this video: YouTube Video, the code is basically the same, the only difference is package name and the location of the JSP file (could this be the source of my problem?).
The project was made in IntelliJ Idea and is attached to the following link (Google Drive): Project Link
As my servlet container I'm using Tomcat8 (tried both 9 and 8.5, no cigar).
HomeController.java
package com.demo.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
package com.demo.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by ARTERC on 1/16/2017.
*/
#Controller
public class HomeController {
#RequestMapping("/")
public String home() {
return "home";
}
}
WebInit.java
package com.demo.spring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#Configuration
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
WebConfig.java
package com.demo.spring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("com.demo.spring")
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".jsp");
return resolver;
}
}
home.jsp path: /web/home.jsp
Okay, so I found the solution.
Add war plugin to pom.xml
Fix web resource directory path (was webapp) Image Link

How to include my class into Spring context?

We're running a Spring setup where I don't see any XML config files, seems everything is done via annotation.
I've got some custom component classes in a specific package I need added to the spring context for autowiring and I annotated the class with #Component but it's not making a difference. Am I missing another annotation?
There is one loop I have where I needed to do a component scan to discover all the classes in the package, maybe I can just add them there since I'd already have a BeanDefinition handle on them. If so, what would I have to do?
for (BeanDefinition bd : scanner.findCandidateComponents("com.blah.target")) {
// how to add it to context here?
}
If you don't see any XML config file, then the project should have a package springconfig with a java file called WebConfig.java. This is exact equivalent of XML config file.
Below is a snippet of a typical Webconfig.java
package .....springconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
<...>
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="<your source package>")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
String dir="/resources/";
registry.addResourceHandler("/images/**").addResourceLocations(dir + "images/");
...
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(100);
return resolver;
}
}
Check out this tutorial: Simple Spring MVC Web Application It is very nicely explained here.

ViewResolver using Java annotation

Is it possible in Spring 3.1.1 to configure a view resolver using Java annotations?
I am done with all configurations using Java annotations, but I am stuck at view resolver.
Code
package com;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#ComponentScan("com")
public class AppConfig
{
{
//Other bean declarations
}
#Bean
public UrlBasedViewResolver urlBasedViewResolver()
{
UrlBasedViewResolver res = new InternalResourceViewResolver();
res.setViewClass(JstlView.class);
res.setPrefix("/WEB-INF/");
res.setSuffix(".jsp");
return res;
}
}
I used this code and ran the application, but it's not returning the appropriate view. However, if I configure a viewresolver in the app-servlet.xml file, it works fine.
Your class should extend WebMvcConfigurerAdapter class. please have a look at below example
#Configuration
#ComponentScan(basePackages="com")
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
I tested your scenario with Spring 4.3.4 and it is working ok.
I would suggest double checking packages you scan and that AppConfig is properly provided.
I am attaching all files starting from your AppConfig. Yet it is good to extend WebMvcConfigurerAdapter. The source code attached is not ideal, it s simplistic and only to try to reproduce the problem you have reported.
Starting from AppConfig:
package com;
import org.springframework.context.annotation.*;
import org.springframework.web.servlet.view.*;
#Configuration
#ComponentScan("com")
public class AppConfig {
#Bean
public UrlBasedViewResolver getViewResovler() {
UrlBasedViewResolver urlBasedViewResolver = new UrlBasedViewResolver();
urlBasedViewResolver.setViewClass(JstlView.class);
urlBasedViewResolver.setPrefix("/WEB-INF/jsp/");
urlBasedViewResolver.setSuffix(".jsp");
return urlBasedViewResolver;
}
}
Then:
package com;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { AppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Finally:
package com;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MainController {
#RequestMapping("/")
public ModelAndView asdf() {
return new ModelAndView("ABC");
}
}
The problem with the above is that the DispatcherServlet.initViewResolvers get's called before the bean getViewResolver is defined and it cannot find the bean so it never adds the view resolver.
If you move the bean definition into an xml definition, it get's picked up. For some reason the MvcConfiguration class you have defined does not trigger a DispatcherServlet refresh if there are no ViewResolvers defined in the XML.

Categories