First to say is that I've been searching for a solution for a while now and I'm quite desperate now.
I cannot get the css file to be accessible from html page when run by Spring Boot.
html.file
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head lang="en">
<title th:text='#{Title}'>AntiIntruder</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" media="all" href="../assets/css/style.css" th:href="#{/css/style.css}" />
</head>
<body>
...
Application.java
#SpringBootApplication // adds #Configuration, #EnableAutoConfiguration, #ComponentScan
#EnableWebMvc
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/*");
}
}
folder structure:
I've tried putting the css folder into a static folder and/or removing the addResourcesHandlers, referencing to the css by relative path and some other things. Nothing seems to resolve this.
Please, let me know also if you tried to solve this but did not find a solution, so that I know, that I'm not ignored.
1. Using Custom Resource Path
In your Web Config
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/assets/**")) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");
}
}
Put your style.css file inside this folder
src/main/resources/assets/css/
After that in your views
<link rel="stylesheet" type="text/css" th:href="#{/assets/css/style.css}" />
.
2. Using predefined paths in spring boot
Remove addResourceHandlers from your web config
Put the style.css inside any of the following folders
src/main/resources/META-INF/resources/assets/css
src/main/resources/resources/assets/css/
src/main/resources/static/assets/css/
src/main/resources/public/assets/css/
And in the view
<link rel="stylesheet" type="text/css" th:href="#{/assets/css/style.css}" />
.
NOTE: You can remove the assets folder here. If you want to do it, remove it from the predefined resource folder and also from the view th:href. But i kept it as it is because, you explicitly mentioned the assets/ path in your question. So I belive it's your requirement to have assets/ in your resource URL.
The problem was the #EnableWebMvc annotation in the Application.java file. As soon as I removed that one, the css started to be available at localhost:8080/css/style.css but was not applied. So far I haven't found the reason why the #EnableWebMvc was causing the problem.
Then I removed a controller mapped to /** that I had implemented in order to display custom error page.
#RequestMapping("/**")
public String notFound() {
return "errors/404";
}
After removing also this one, I've got my css working. =)
If you put your css in the static folder, you dont need the addResourceHandlers method.
.../static/css/app.css
Or if you really want to put them in the assets folder:
.addResourceLocations("classpath:/assets/") <-- without the * at the end
.../assets/css/app/css
in both cases the css should be available through
th:href="#{/css/app.css}"
Put your css folder inside resources/static folder
In my case the problem was in file read permissions.
I copied the file 'style.css' from another project, and browser could not read it.
After re-creating 'style.css', everything worked fine.
My advice is to put (again) css folder under static folder, remove addResourcesHandlers and reach css with absolute path (e.g. /css/style.css).
For me I had to remove the static reference to the stylesheet for it to work in thymeleaf.
So
<link rel="stylesheet" type="text/css" media="all" href="../assets/css/style.css" th:href="#{/css/style.css}">
Became
<link rel="stylesheet" th:href="#{/css/bootstrap.css}">
I spent hours trying all sorts of configurations and file path renaming. Don't know why but this is the only thing that got my css and js to load in Spring Boot 5.
first implements on one of your configuration class with WebMvcConfigurer like this
#Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
//and overide this configuration method like this
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**", "/resources/**");
}
}
so now you can overide your HttpSecurity configuration like this
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/index").anonymous()
.antMatchers("/**/*.*").permitAll()
.anyRequest().authenticated();
}
}
this ("/**/*.*") regex text will allow files with anny extension
and if your are using an webjars libraries like bootstrap add this config to your WebSecurityConfiguration
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
If this topic still relevant in 2022.
I have had a similar problem and i solved it like this:
This link in /templates/file.html
<link rel="stylesheet" type="text/css" media="all" ref="../static/css/styles.css">
and i have added application.properties
spring.mvc.static-path-pattern=/static/**
my css path is
src/main/resources/static/css/
helpful link
Related
I have webproject which has images inside src/main/webapp folder. I would like to place images in different folder on the disk. But I have no idea how to manage requests to reach this images.
Should I create some kind of httpServlet like shown here: http://balusc.omnifaces.org/2007/07/fileservlet.html
Or as I use Spring MVC with java configuration, there is more suitable and simpler way.
Looking forward for your suggestions.
Use the spring mvc support for static resources, its location attribute is an Spring Resource, so you could use file: prefix
<resources mapping="/resources/**" location="file:/my/external/directory/" />
or
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("file:/my/external/directory/");
}
}
#See Spring Reference Chapter 6.4 The ResourceLoader for a table that list all prefixed for resources
In my case I placed js and css resources in webapp and images in e://images/.
For this case I use two mvc:resources mapping
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:resources mapping="/images/**" location="file:e://images/"/>
And locate the image of e: > images > abc.jpg using ....
<img src="../images/abc.jpg"/>
You could try also <img src="/images/abc.jpg"/> or <img src="images/abc.jpg"> (If not work)
The css/js linked under webapp > resources > js > xyz.js like below.
<script type='text/javascript' src='../resources/js/xyz.js'></script>
You canimplement WebMvcConfigurer in your main Application or Main class.
#SpringBootApplication
#ComponentScan("com.your.package.controller")
#Configuration
public class ServicesApplication implements WebMvcConfigurer { // ServicesApplication is my main class
String your_drive_location = "file:///D:/upload_dir/upload/"; // my file path
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations(your_drive_location );
}
public static void main(String[] args) {
SpringApplication.run(ServicesApplication.class, args);
}
}
I am using JSTL for showing:
<c:forEach items="${ListOfBrand}" var="brand"> // ListOfBrand is a Map
<img src=" <c:out value="/images/"/>${brand.brand_image}" /> // Showing all image from brand table
</c:forEach>
I'm running the latest Play Framework 2.5.1 and I'm getting an error from my log on page:
Error:
value login is not a member of controllers.Application
I have tried adding the # symbol i.e:
#controllers.Application.login()
And removing the injector from the build.sbt, clean up/ clean-files and updates in "CMD". I'm using the sample from https://www.playframework.com/documentation/2.1.0/JavaGuide.
HTML CODE
#(form: Form[Application.Login])
<html>
<head>
<title>Zentasks</title>
<link rel="shortcut icon" type="image/png" href="#routes.Assets.versioned("images/favicon.png")">
<link rel="stylesheet" type="text/css" media="screen" href="#routes.Assets.versioned("stylesheets/login.css")">
</head>
<body>
<header>
<span>Zen</span>tasks
</header>
</body>
</html>
CONTROLLERS
package controllers;
import play.*;
import play.mvc.*;
import views.html.*;
public class Application extends Controller {
public Result index() {
return ok(index.render("Your new application is ready."));
}
public static Result login() {
return ok(
login.render(form(Login.class))
);
}
public static class Login {
public String email;
public String password;
}
}
ROUTES
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# Home page
GET / controllers.Application.index()
GET /login controllers.Application.login()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file #controllers.Assets.versioned(path="/public", file: Asset)
Remove the static keyword from your controller's actions. Play 2.5.1 uses dependency injection by default and if you want to use static actions, you need to explicitly configure it. So, your login action must be like:
// no static keyword here
public Result login() {
return ok(login.render(form(Login.class)));
}
Update:
By the way, you are mixing a lot of things here. I recommend you to not follow 2.1.0 guide while developing for version 2.5.x since there is a lot of differences between these two versions. In fact, Play 2.1.0 is from Feb 06 2013.
Here are some references that explain why your code was failing:
Java Routing: Dependency Injection
Dependency injecting controllers
Replaced static controllers with dependency injection
How may I serve two assets folder for the same URI in Dropwizard. Currently only the first one is being served, when using the same name for URI.
I'm registering AssetsBundle using (in my main application class):
public void initialize(Bootstrap<DummyFrontendConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/assets1", "/public", null, "assets1"));
bootstrap.addBundle(new AssetsBundle("/assets2", "/public", null, "assets2"));
bootstrap.addBundle(new ViewBundle());
}
Css file (main.css) in assets1:
h2{
color: red;
}
Css file (main2.css) in assets2:
h4{
color: green;
}
In html template head:
<link rel="stylesheet" type="text/css" href="public/stylesheets/main.css">
<link rel="stylesheet" type="text/css" href="public/stylesheets/main2.css">
In html template body:
<h2>This should be red</h2>
<h4>This should be green</h4>
Unfortunately the second css file (main2.css) couldn't be loaded during the html page rendering (404 - not found), any ideas?
The assets module isn't designed to function this way. Under the hood it's calling:
environment.servlets().addServlet(assetsName, createServlet()).addMapping(uriPath + '*');
Both servlets can't be mapped to the same path. You could fix this by switching one of the "public" mappings to be another path ("public2", for instance).
If you indeed need to keep your resources completely separate you may want to consider introducing another step in your build (via maven or ant) that merges the assets into a single directory structure for deployment.
There are two methods with different URI which mapping to the same view in spring boot, the first one works well, however, the second one can only display html and css can not be loaded, the code is as below:
#Controller
public class ExamController {
#RequestMapping("/quiz0")
public ModelAndView quizingA() {
System.out.println("run into quiz0");
ModelAndView modelAndView = new ModelAndView("examination");
return modelAndView;
}
#RequestMapping("/quiz1/{course}")
public ModelAndView quizingB(#PathVariable("course") String course) {
System.out.println("run into quiz1, couse choosed: " + course);
ModelAndView modelAndView = new ModelAndView("examination");
return modelAndView;
}
}
From the log, both of them are reached successfully, as I known, there shouldn't be error existed, right?
For the first one which works well the url I used is;
http://localhost:8080/quiz0
For the second one which failed the url I used is:
http://localhost:8080/quiz1/Java
One more information, I have disabled spring security with override WebSecurityConfigurerAdapter. I can paste it out if required.
Could anyone help to explain it?
Thanks in advance.
You're probably including your css with a relative path instead of an absolute one.
e.g.
if you include like this
<link type="text/css" href="css/bootstrap.css" rel="stylesheet"/>
The paths will be converted to
/quiz0/css/bootstrap.css
and
/quiz1/{course}/bootstrap.css
I recommend using it with absolute path
<link type="text/css" href="/css/bootstrap.css" rel="stylesheet"/>
I have a spring mvc application, in a page I list the "Group" details in a table, fetched from database. The url of every group is set to "/viewgroup/410", where 410 is the groupid which will be loaded from the database and displayed in the viewgroup.jsp page.
<td>${group.name}</td>
So, the controller method has the
#RequestMapping("/viewgroup/{groupid}")
public String viewGroup() {
...
}
like this. The jsp pages could not load the static resources which I have in the directory structure
+webapp
+resources
+css
+js
+images
+views
+login.jsp
The jsp pages has the below path for image/js/css.
<link href="resources/css/bootstrap.css" rel="stylesheet" media="screen">
I tried adding
#Controller
#RequestMapping("/viewgroup/**")
public class ViewGroupController {
...
}
and this in jsp
<link href="viewgroup/resources/css/bootstrap.css" rel="stylesheet" media="screen">
Still the jsp page loads could not load the static resources. How do I provide the resource path of the static resources in jsp pages when I pass params in the url?
The fact that you pass query parameters through any URL of your project does not affect the way it addresses static resources. You need just to include a link to your static resources (as a relative path for example) as follow :
<link href="/resources/css/bootstrap.css" rel="stylesheet" media="screen">
The resolution of such static resources is completely independent of the page you're currently looking at, be it /viewgroup/410 or /foo/bar. That's the reason why you don't need the "viewgroup" at the beginning of your link's href.
But you do need to tell Spring MVC how it should address such static resources. Usually, this is done in the Spring configuration. For example, if you use Spring MVC java config through an WebMvcConfigurer instance, you should override the addResourceHandlers method in such way :
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
EDIT : My bad, I thought Spring MVC + any view technology (JSP, Thymeleaf, etc etc) would automatically resolve link's href against the root path of the web-app but this is obviously not true to raw HTML which relative link's href are resolved against current path.
So in the end, as found by OP, links are only to be resolved against root path if they are processed with the view technology in use (in the example with JSP : <c:url value="/resources/css/bootstrap.css"/>)