Spring MVC + Thymeleaf: not loading some resources - spring

I am new to Thymeleaf and Spring MVC.
I have been dealing with the following problem: some resources (css or images) don't get loaded by my webpage while other do. They are in the same path and folder, the syntax is the same (i have checked by just switching the name of the resource and it worked).
For example, my Thymeleaf Template can find and read my own css files, but it won't read the bootstrap-4 one.
Here is my project structure:
And here an example of the code trying to read bootstrap.css:
The same problem happens with images of the same format.
Any ideas of what could be causing the issue?
Thank you in advance

You can register a resource handler by extending a WebMvcConfigurerAdapter.
Something like this.
#EnableWebMvc
#Configuration
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/styles/**").addResourceLocations("/styles/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
Anyway, the css files should be in the css directory

Okay so I understood what the problem was: intelliJ.
It didn't see the new files added to the project.
Running mvn clean install fixed the problem

Related

Spring MVC Cannot configure views' path

I have a project that uses Spring Boot 2.2.5 (Spring version 5) - here is a link to a bare minimum project demonstrating my problem. In all the tutorials I followed they claim views' path can either be configured inside application.properties like this:
spring.mvc.view.prefix=/WEB-INF/jsp
spring.mvc.view.suffix=.jsp
or inside WebMvcConfigurationSupport derived class like this:
#Override
public void configureViewResolvers(final ViewResolverRegistry registry) {
registry.jsp("classpath:/", ".jsp");
}
or like this:
#Override
public void configureViewResolvers(final ViewResolverRegistry registry) {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
registry.viewResolver(resolver);
}
None of which work in my case. Spring will always serve .jsp files from src/main/webapp and from nowhere else in spite of my configuration or lack of it. No other file types will be served from that directory, not even HTML.
Some tutorials claim that when not configured Spring will serve anywhere from
src/main/resources/static
src/main/resources/public
src/main/resources/resources
src/main/java/META-INF/resources
I am yet to see this.
CSS and Javascript files will be served from src/main/resources but only if I have this in my MVC configuration:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/");
}
Configuring this from application.properties doesn't work
spring.resources.static-locations=classpath:/
In relation to this are there other special folder names like classpath: that can be used? I tried webapp: but it doesn't seem to be expanded
UPDATE: I thought for a moment that maybe subclassing WebMvcConfigurationSupport is to blame since it acts like #EnableWebMvc. Subclassing WebMvcConfigurer brought the following error. Placing #EnableWebMvc solves it.
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.requestMappingHandlerAdapter(WebMvcAutoConfiguration.java:369)
The following method did not exist:
'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration.requestMappingHandlerAdapter(org.springframework.web.accept.ContentNegotiationManager, org.springframework.format.support.FormattingConversionService, org.springframework.validation.Validator)'
I read somewhere that JSP view are not supported inside embedded servlets. What a nice feature! Anyway I don't thing this is related to my problem.
I would like to stick to JSP and avoid Thymeleaf as my project is based on React. I will create MVC pages in order to be Search engine friendly, though but I will figure this out along the way.
Here is a screenshot of my project's layout

Static resources arent loaded in thymeleaf template

I've gone ahead and tried almost any tutorial with the hopes it wouldfix this.
I'm new to spring boot.
So I have a spring boot web application setup, but css, jscript and any other static content won't be loaded in template. It's not a problem with the css or jscript as implementing them directly into the html file will make it work.
This (http://prntscr.com/lk6f6q) is how my project looks like. "test".js just includes a simple alert call.
Html: https://hastebin.com/ixejakiqev.xml
Pom: https://hastebin.com/vakinawuva.xml
What am I doing wrong? I'm trying to solve this since a week and nothing seems to work. Am I maybe missing a library?
Check the exact issue using network tab of the browser.
and also ensure that you have a class something like below to handle static resources.
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(
"/webjars/**",
"/img/**",
"/css/**",
"/js/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/",
"classpath:/static/img/",
"classpath:/static/css/",
"classpath:/static/js/");
}
}
The security config did not allow unverified access to the static resources.

Unable to access the html file in template folder of spring boot application

html files are placed under resources/templates/login.html directory of spring boot application(show in the screenshot), deployed it in the weblogic server and when I try to access the login.html with the below URL, it gives The webpage cannot be found message
http://localhost:7001/demo/login.html
below is the screenshot
In one of the post I found the below code snippet and tried, but it didn't work
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
I am not getting what mistake I did, Could some one help me regarding this ...?
Spring Boot by default serves all content found under /static, /public, /resources or /META-INF/resources, see docs. So all content in your static folder should be served well (check that). But the templates folder is not a sub-folder of the static, so it will not be served. If I get you right, the templates is not supposed to be part of the URL path, right? So you could either move your login.html to the static folder, or you could add the templates folder to the classpath resource locations. Either programmatically (as you did for the other locations), or by setting the corresponding property:
spring.resources.static-locations=classpath:/templates/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

Spring Boot project with static content generates 404 when running jar

The recent blog post (https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot) by Spring regarding the use of static web content in Spring Boot projects indicates that several resource directories may be used:
/META-INF/resources/
/resources/
/static/
/public/
This is thanks to the WebMvcAutoConfiguration class which automatically adds these directories to the classpath. This all seems fine and appears to work when using the spring-boot-maven-plugin spring-boot:run goal, all of your static content is working (eg: /index.html).
When you package your Spring Boot project and allow the spring-boot-maven-plugin to create the enhanced JAR then attempt to run your project using java -jar my-spring-boot-project.jar you find that your static content now returns a 404 error.
It turns out that whilst Spring Boot is being clever at adding the various resource directories to the classpath, Maven is not and it's up to you to deal with that part. By default, only src/main/resources will be included in your JAR. If you create a folder called /static in the root of your project (as implied by the blog post) then it will work fine whilst using the spring-boot:run Maven goal but not once you create a JAR.
The easiest solution is to create your /static folder inside /src/main/resources and then Maven will include it in the JAR. Alternative you can add additional resource locations to your Maven project:
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>static</directory>
<targetPath>static</targetPath>
</resource>
</resources>
I hope this is useful to someone, it's kind of obvious when you step back and look at how Maven works but it might stump a few people using Spring Boot as it's designed to be pretty much configuration free.
I am banging my head against the wall trying to figure out how to do this with gradle. Any tips?
EDIT: I got it to work by adding this to my build.gradle:
// Copy resources into the jar as static content, where Spring expects it.
jar.into('static') {
from('src/main/webapp')
}
There are 2 things to consider (Spring Boot v1.5.2.RELEASE)-
1) Check all Controller classes for #EnableWebMvc annotation, remove
it if there is any
2) Check the Controller classes for which annotation is used -
#RestController or #Controller.
Do not mix Rest API and MVC behaviour in one class. For MVC use #Controller and for REST API use #RestController
Doing above 2 things resolved my issue. Now my spring boot is loading static resources with out any issues.
#Controller => load index.html => loads static files.
#Controller
public class WelcomeController {
// inject via application.properties
#Value("${welcome.message:Hello}")
private String message = "Hello World";
#RequestMapping("/welcome")
public String welcome(Map<String, Object> model) {
model.put("message", this.message);
return "welcome";
}
#RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet/less" th:href="#{/webapp/assets/theme.siberia.less}"/>
<!-- The app's logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="#{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>
<!-- Development only -->
<script type="text/javascript" th:src="#{/webapp/libs/less.min.js}"></script>
</head>
<body>
</body>
</html>
I was going around few pages to understand how to serve static content in Spring boot environment. Mostly all advises was around placing the static files with in /static /resources/ src/main/webapp etc. Thought of sharing below approach.
Allow spring boot to auto configure Dispatcher Servlet - Make sure DispatcherServletAutoConfiguration is not in the exclude for AutoConfiguration.
#EnableAutoConfiguration(exclude =
{
//DispatcherServletAutoConfiguration.class,
})
Inject your external directory for static content routing
#Value("${static-content.locations:file:C:/myprj/static/")
private String[] staticContentLocations;
3.Override WebMvcAutoConfiguration using WebMvcConfigurerAdapter to advice spring not to use default resource Location but use what we instruct it.Like below
#Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter()
{
return new WebMvcConfigurerAdapter()
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
if (!registry.hasMappingForPattern("/**"))
{
// if this is executed spring won't add default resource
// locations - add them to the staticContentLocations if
// you want to keep them
// default locations:
// WebMvcAutoConfiguration.RESOURCE_LOCATIONS
registry.addResourceHandler("/**").addResourceLocations(
staticContentLocations);
}
}
};
}
If C:/myprj/static has index.html , then http://localhost:portno/index.html should work. Hope that helps.
Spring Boot will use WebMvcAutoConfiguration to config static contents, this class will only take effects when you don't have a custom WebMvcConfigurationSupport bean ,and in my cases , i do have one.
#Configuration
#ConditionalOnWebApplication
#ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
WebMvcConfigurerAdapter.class })
#ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
#AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
#AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
}
so i'll just have to config it by myself, here is my solution:
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static-file/**").addResourceLocations("classpath:/static/");
}
I had to add thymeleaf dependency to pom.xml.
Without this dependency Spring boot didn't find static resources.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
I've a assets folder in static dir and permitting in SpringConfig which extended WebSecurityConfigurerAdapter.
http.authorizeRequests().antMatchers("/", "/login", "/assets/**")
.permitAll()
I just stumbled about this 404 topic when I try to create a sandbox example as template (https://github.com/fluentcodes/sandbox/tree/java-spring-boot) from my existing working solution: No static content index.html is provided.
Since the example was rather simple and the existing solution worked I don't get deep into the deep digging spring solutions mentioned.
I looked in the created target classes and there was no static/index.html as expected.
The reason was rather simple: I created the resources not under src/main/ but under src/. Need some time to find since there are so many complex solutions mentioned. For me it had a rather trivial reason.
On the other hand when starting spring boot: Why I don't get any hint, that no static content from location1, location2 .... locationx could be found. Think its a topic.

Resources(js/css/images) are not working after spring security

1) I have configured application using pure java configuration. Everything seems to be working correctly except css/js/images. The application is available on Github at
https://github.com/rajendersaini/cabms/
Just want to point out the configuration
AppConfig - spring mvc config - register resources using
registry.addResourceHandler("/resources/**")
.addResourceLocations("/WEB-INF/resources/").setCachePeriod(31556926);
and in SecurityConfig -
http.authorizeRequests()
.antMatchers(LoginController.AUTHLOGIN,
ResourceConfig.RESOURCE_PATH_MATCHER).permitAll()
.anyRequest().authenticated().and().formLogin()
.loginPage(LoginController.AUTHLOGIN);
Can you please help fixing this issue?
Where do your static resources end up in your war file? I ask because you have them under the WEB-INF directory. I don't know if Spring will allow you to serve public content out of WEB-INF.
In my build, I have my static stuff under
src/main/webapp/resources/...
/css
/js
/img
This way, they end up at the top level of the war file under the /resources directory. You could give that a shot.
1) Finally my application resources are working - few changes I have made, In my mvc app config, I don't know when I introduced this line and this was the culprit. I will investigate it later
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
2) Java webapp initializer was looking for mapping which should be "/*" instead of "/"
3) In headers and footer we need to have context appended to resource paths.
You don't specify a secure rule which will ignore an application security for static resources. Try to add code like this in your Spring Security configuration class:
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}

Resources