Spring (with Jade) Resources - java

The Problem
My spring-boot application recently changed routing from host/endpoint to host/middle/endpoint. Since the change, I am running into an issue where the resources are not being found relative to the new url structure. Before, I could reference resources like css stylesheets like link(rel='stylesheet', href='css/style.css'), but now the logger shows an error saying it can't find the resource at /middleman/css/style.css.
From my research, I have found that what I need to do is use a resource handler registry. I have created one (as shown below) but it doesn't seem to be working. I think the problem is that even though I now have the resource registry, I am not referencing resources in the registry. What is the proper way to solve this problem and have all resources point load from the same place regardless of the endpoint? I very well may be missing some obvious piece of SOP
Note: This is all a dumbed down representation of my project in order to give the idea of what is going on without giving unnecessary information.
Project Structure
src
main
java
com.mystuff.cool
configurations
ResourceConfiguration.java
controllers
RoutingController.java
application
Application.java
resources
static
css
footer.css
style.css
images
place1.png
location1.png
spot1.png
favicon.ico
javascripts
layout.js
templates
home.jade
Application Class
#ComponentScan(basePackages = {"my.packages"})
#EnableAutoConfiguration
#EnableSAMLSSO
#Configuration
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(new Object[]{ Application.class, ServiceConfig.class, ResourceConfiguration.class}, args);
}
}
Resource Configuration
#EnableWebMvc
#Configuration
public class ResourceConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}
}
Controller
#Controller
public class RoutingController
{
#RequestMapping("/house/home")
public String home(Model model)
{
model.addAttribute("title", "Home is where the heart is");
commonModelTribs(model);
return "home";
}
}
Home Page
doctype html
html
title Place-spedia #{title}
link(rel='icon', href='images/favicon.ico')
link(rel='stylesheet', href='css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='css/footer.css')
body
div#footer-icons
a(href='place1')
img#place1(src="images/place1.png")
a(href='location1')
img#location1(src="images/location1.png")
a(href='spot1')
img#spot1(src='images/spot1.png')

If you are using spring boot, you don't need to worry about the resource configuration since you are already configuring the resource directory through the auto configuration. The default behavior for the autoconfiguration is to look within resources/static.
Your issue is with your href values, try inserting a leading forward slash:
link(rel='icon', href='/images/favicon.ico')
link(rel='stylesheet', href='/css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='/css/footer.css')
Spring is routing your application to a new relative path, so by putting the leading / in your href attributes, you are telling the router to look absolutely within the static directory instead of relatively from the middle directory.

Related

how to serve static content in springboot 2.2.6?

I am newbie to Springboot and I am trying to display html page on its root(localhost:8080) path. To do so I googled and gone through -
Spring Boot not serving static content
https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot
Spring Boot app not serving static content
Springboot does not serve static content
Tried almost everything but none of them worked for me.
Exact problem
With out index.html file inside any of resources/(static/ or public/ or meta-inf/resources) works fine and show the list of some spring data rest. If I create an index.html file then it gives an error of 404 not found with out #EnableWebMvc annotation, if use #EnableWebMvc then it shows the list of Spring data rest apis.
Other than index.html file it show the list of Spring data api in root path, and url(localhost:8080/test.html) to other than index.html has same problem.
This problem has no effects by implementing public class StaticResourceConfiguration implements WebMvcConfigurer with this configuration to.
Starting with a simple spring boot initializer
... we can place static (html) files into one of:
(src/main/resources:)
static
resources
public
META-INF
resources
which results in the default (class path) locations, configured via the spring.resources.static-locations property.
These will be exposed through the value of spring.mvc.static-path-pattern-property (ref), by default: /**.
So a static index.html file in one of the above mentioned folders, with default config, will be accessible at:
http:localhost:8080/ (due to "welcome file mapping" -> static mapping)
and http://localhost:8080/index.html (due to the static mapping)
Accordingly: no problem with http://localhost:8080/test.html ...
Checkout at github.
So this, at least answers the "question title" "how to serve static content in springboot 2.2.6?".
The order of spring.resources.static-locations appears (index.html preferred from META-INF/resources) also to be the "precedence" of static file locations (left-to-right, first match wins).
When we add #EnableWebMvc
..."evertyhing gets broken" (context loads, but) only:
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /index.html
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /test.html
..please aslo consider this: why spring-boot application doesn't require #EnableWebMvc
With "non-default config", You would have to provide more details, to find a specific solution.
But for "newbie in Springboot": starting with an intializer and "the defaults" sounds optimal! From here on, you can re-fine your configuration based on a working one.
And if you want/need the #EnableWebMvc annotation for some reason, this will result in the "previous" behavior again/restore the (2.2.6) default static content handling:
#EnableWebMvc
#SpringBootApplication
public class DemoApplication implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/");
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
(Assuming no conflicts with existing configuration/resource handlers)
It's working for me
registry.addResourceHandler("//**").addResourceLocations("classpath:/static/");

Spring 5 add static file directory webapp

I have a Spring 5 (not Spring Boot) web application. I have one controller that outputs html. I output a string which is HTML and it works, however the relative paths the JS content do not work. I will layout my structure as follows:
src
main
java
resources
webapp
css
js
img
WEB-INF
index.html
test
java
resources
When I output my html text, all the relative locations cannot be found:
if I call:
http://localhost:8080/myapp/controller?{some parameters}
I would expect
http://localhost:8080/myapp/js/myjsfile.js
would be there. When I build and deploy the WAR, the exploded WAR file has all the right code. So I would expect the file to be there and found. However, I expect from what I've been reading that static files can be served out differently. So, I have two questions:
1) What is the standard way of serving static files from a Spring 5 web application? Do I change the structure this way:
src
main
java
resources
static
css
js
img
webapp
WEB-INF
index.html
test
java
resources
And then I am presuming I have to do the webconfig as such:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/resources/**")
.addResourceLocations("static/js", "static/css", "static/img")
.setCachePeriod(31556926);
}
}
2) OR, can I use the existing structure and then change the WebConfig to add those static locations as follows:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/webapp/**")
.addResourceLocations("/js", "css", "img")
.setCachePeriod(31556926);
}
}
But if putting these files under webapp doesn't work, I can understand moving them to /resources if that is the standard way of doing thing.
So, if I could get any help with this, that will be fine. I am fine with either way as long as it works. Thanks!
Try to use the resources/static folder to provide your view files. And add the following configuration to your WebMvcConfigurer:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}
It will map all static files requested in the "/" URL to redirect to resources/static folder.
Option 1 is the way to go, place your folder under resources directory (name it as you wish):
src/main/java/resources
myStaticResourcesFolder
css
js
img
Then just do this:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**") // map to whatever url you need
.addResourceLocations("myStaticResourcesFolder/"); //
}

Return HTML page from Spring controller

I have a Spring Boot app setup as a REST api. I now also want to be able to serve simple HTML pages to the client, without the use on any template engine like Thymeleaf. I want access to the HTML pages to fall under the same security constraints setup by Spring Security with the use of WebSecurityConfigurerAdapter, already present in my app.
What I've tried is having a Controller:
#Controller
public class HtmlPageController {
#RequestMapping(value = "/some/path/test", method = RequestMethod.GET)
public String getTestPage() {
return "test.html";
}
}
and placing the test.html file in /resources/test.html or /webapp/WEB-INF/test.html.
Every time I try to access the page at localhost:8080/some/path/test a 404 is returned.
How do I make this work?
Okey so apparently Spring Boot supports this without any additional configuration or controllers.
All I had to do was to place the HTML file in the correct directory /resources/static/some/path/test.html and it can be reached at localhost:8080/some/path/test.html.
In my attempts to change the directory from which the file is served I was unsuccessful. It seems that providing a separate #EnableWebMvc (needed for configuring the resource handlers) breaks the Spring Boot configuration. But I can live with using the default /static directory.
There is a Spring MVC mecanism that exists to provide static resources.
In the config class, overide this method :
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("some/path/*.html")
.addResourceLocations("/static/");
}
And place your html files in the src/main/webapp/static/ folder.
If you request some/path/test.html (note the .html), it will return the test.html file located in static folder.
You can obviously use a different folder or a more sofiticated directory structure.
This way you don't have to create a controller. Note that your config class should implements WebMvcConfigurer.
Your html, js and css files should be under the src/main/resources/static directory. and your return statement you can try removing .html.
#RestController
public class HtmlPageController {
#GetMapping("/some/path/test")
public String getTestPage() {
return "test";
}
}
See tutotrial example how to define html view in Spring MVC configuration
#Bean
public InternalResourceViewResolver htmlViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/html/");
bean.setSuffix(".html");
bean.setOrder(2);
return bean;
}
setOrder is set to 2 because it include also JSP support in example
Also you need to change to return without .html suffix
return "test.html";

Spring Boot static resources are not available

Files in resources/static are not available. How I can fix it?
Hierarchy:
resources/
db/
static/
image.png
templates/
application.properties
But if I open localhost:8081/image.png I get error.
My WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
}
You should add below line to your existing resource mapping:
registry.addResourceHandler("/**")
.addResourceLocations("resources/static/");
You have configured the webjars resourceHandler to serve client side script or stylesheet dependencies. but custom handler is not added to serve your image file.
Since you are overriding the addResourceHandlers (ResourceHandlerRegistry registry) method, you should provide all the resourceLocation and handler mapping in your implementation.
Please check serving-static-web-content-with-spring-boot article to have more clear idea.
Note:
If you are using spring-boot you shouldn't be overriding the above method untill explicitly required as its already taken care in WebMvcAutoConfiguration.java.
Please check below default implementation:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(
this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
}
Here give path of your image:
registry.addResourceHandler("/**").addResourceLocations("file:/path/to/your/image/");
If you would prefer to serve static content (including web pages, js, pdf, css, pdf, doc etc.) from outside of the WAR, may be that is usefull. if you wanna changed any that static contents, just you can put changed file to your content path on application server easly and serving that without deploying or restarting you application server. If you prefer this way, you can do it with a small configuration on your application server.

Spring static resources mapping : controller vs addResourceHandler

I am trying to map a particular set of resources(audio) to a controller. But resources/** maps to all resources. How can I isolate a particular resource request so that it doesnt go through the Spring static resources mapping, but to my controller? Is moving the audio resources to a different folder other than resources the only solution?
For example:
Folder structure:
/resources/js
/resources/css
/resources/audio
Resources Mapping using Spring Web Config:
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
...
}
Resources Controller:
public class ResourceController {
#RequestMapping(value = "/resources/audio",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public Resource getAudio(...) {
}
....
}
Is moving the audio resources to a different folder other than
resources the only solution?
Whats the problem with that ? Seems perfect : conventional and intuitive to me. If its not a static don't do make it static.
As far as I know, there is no way to specify exclusion in ant path. And I think many utilities based on ant path matching provide both an include and a exclude path for that reason.
But anyway, it would be dangerous in the sense of future evolutions to have under /resources data that will be served by a controller, as NimChimpsky also said.

Categories