How to serve static and uploaded content in Java Spring Boot MVC - java

I try with following process to serve static content but have no luck.
I have written the below code in my application.properties:
spring.resources.static-locations=classpath:/public/
where public is the directory of my static and uploaded content, like user profile and others.
but it's giving me a 404 error when I access the file like:
http://localhost:8082/public/uploads/file/a.png
I have also tried with:
http://localhost:8082/uploads/file/a.png
but it does not working either.

Unless you don't have other configuration parameters set, spring boot should serve static resources under /
So if your static resources are under a folder called public/file you'll find that at the url localhost:8082/file/a.png
If you have spring.mvc.static-path-pattern parameter set spring boot should serve static resources at that path
In the case of spring.mvc.static-path-pattern = files (for example) it will serve them at http://localhost:8082/files/file/a.png
Here's a good article explaining all :
https://www.baeldung.com/spring-mvc-static-resources

If you have server.servlet.context-path (or server.servlet.contextPath, it's the same) set in your application.properties, you need to have this part in the URL, for example:
server.servlet.context-path=/foo
then you should visit http://localhost:8082/foo/uploads/file/a.png

Related

Java 8 Spring Boot - Cannot render index.html from Static folder on Websocket service

I'm a relatively new Java developer that is working on a Java 8 Spring Boot project. I am trying to learn and understand WebSockets so I have created a basic Websocket server that appears to be up and running correctly.
I wanted to use the Static folder to render a basic HTML page with a JS file and CSS. From what I have researched, it should use it automatically, but I'm getting a standard whitepage error when I use the browser to connect when my research seems to indicate it should render by default?
I've heard that Thymeleaf is used to render templates, but I have also read that I can connect a basic HTML file from the Static folder instead. When I try to connect to the main server, it gives me the following logs from my different attempts to see the index.......
No mapping for GET /
No mapping for GET /index
No mapping for GET /index.html
I'm not sure what the problem could be and my Google-Fu is turning up no solutions. I feel like I must be missing something fundamental here, but I'm not sure how to properly map that route. I have Spring Web dependencies installed so I could create a RestController mapping to that route, but how would I properly return those static files?
You need to create the endpoint for the default entry page of your application. Something like this:
#Controller
public class HomeController {
#GetMapping("/")
public String index() {
return "index";
}
}
Your index.html goes inside this path "src/main/resources/templates/".
The solution I found through another source on Discord..
Part of the problem was I was using #RestController instead of #Controller.
The other issue was I had my index.html in the public folder instead of Templates.
And the final error was I had the incorrect Thymeleaf dependency. I needed the Thymeleaf Starter and I had accidentally added a different one from Maven Repo.

Would this be a correct to remove Router/Handler Function in the code (Spring Boot)?

There is Spring Boot Cloud repository on GitHub with simple route handler example.
#Bean
public RouterFunction<ServerResponse> indexRouter(
#Value("classpath:/static/index.html") final Resource indexHtml) {
// Serve static index.html at root, for convenient message publishing.
return route(
GET("/"),
request -> ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml));
}
You can pay attention that index.html is in a static folder which was instantiated by Spring in default mode, so this file is loaded when index path ("/") is requested.
I understand that it is possible that some webservers will not associate main path with index.html file. However from Spring Boot and Java perspective would this be a correct not to include such Bean to the project in this case (when the main path is requested)?
I have tried to test it in different contexts including Spring Boot Security and everything works well. So I close this question, however if someone has wider experience appreciate additional arguments.

Spring Boot Static Resources From Controllers and Other Classes

I've been trying to solve this issue and I can't find the answer.
I've been having to use src/main/resources/public/whatever... in order to access static resources from class files. I was under the impression that if you use /static /public /resources... that Spring Boot already has those paths configured.
I'm lost at this point and not sure how I can access these files without having to prepend src/main/resources/public.
EDIT
Based on the suggestions regarding the static content, I created a private directory to protect files etc... that I don't want publicly available. And left css, images, etc... in the /public folder.
Thank you all for the suggestions and recommendations, I appreciate it!
After more searching I ran across an example that used the ClassLoader. I've only been using Spring for a short time and not aware of all the tools that are available, there might be a better way than this; if so please tell let me know.
ClassLoader classLoader = getClass().getClassLoader()
new File(classLoader.getResource('public/file-name-or-directory').getFile())
So far it looks like it's working, I need to do some further testing and will post back if any issues.
The directories you list, /static, /public and /resources, are for static content that will be served up by a web-application. Things like javascript files and images that will always be the same no matter who requests them and when, as opposed to JSPs for example that need to be processed on the server per request.
If you need to access a configured property in one of your Java classes (it must be a Spring bean), then you can put it in your application.properties file, and have Spring inject it using the #Value annotation.
Example code from Spring docs:
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
#Component
public class MyBean {
#Value("${name}")
private String name;
// ...
}
Spring Boot expect you to use for content served directly
src/main/resources/static
and to use for templating
src/main/resources/templates

How to serve images on Spring based web services

I am developing a java web service for the first time. I am using Spring Framework to do it. I need to serve user images. I will get Base64 String from the client and write it as an image and add its reachable url to database than whenever a client wants to see this image I will just send the image url and by this way a client will be able to use the image with less effort.
But to do this I need to reach these images in their folder via browser.
I don't know how to reach a folder and its files on java based web services.I hope someone helps.
If there is a way you think better to do. Please feel free to write.
Spring Framework 4.1 has improved support for resource handling. It allows you to declaratively configure from where to serve resources for a certain request path, and that's what you're probably interested in.
In your code, making file system resources accessible from the web mostly boils down to overriding the addResourceHandlers() method of your WebMvcConfigurerAdapter based configuration class. The Spring Framework documentation shows the following example:
For example, to serve resource requests with a URL pattern of /resources/** from a public-resources directory within the web application root you would use:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/");
}
}
Substitute /public-resources/ with your filesystem path prefixed with file://, e.g. file://user-uploads/.
I suggest taking a look at the relevant blog post and the accompanying example project. The demo project sports a good example of how to configure resource handling for a complex scenario.

Spring load a file

I need to load a file from within a directory in the root of a WAR using Spring
This is the directory structure
rootOfWar
--static-dir
---- my-file.css
--WEB-INF
---- classes
.....
It is a normal WAR.
In a Spring #RestController I need to be able to read and write to my-file.css file. What is the best way to get the File, ServletContextResource or?
More Details
- The location of the file is out of my control I cannot move the file.
- The jee container is Tomcat.
- The Spring version is current 4.1.6
- The Spring environment is not using XML only annotations with WebApplicationInitializer, WebMvcConfigurerAdapter and an annotation configuration class.
Is there another way to do this like specify a file as a resource in the configuration so that it is loaded by the frame work and accessible within the application?
Basically I have JEE knowledge but my Spring knowledge on best practices concerning read/write are lacking.
If you need to modify a file you should not make it part of the WAR. Store it somewhere outside the web package and reference it there. Everything else will lead to problems, especially when you deploy to Websphere which is often run in a restricted environment where writes are rejected.
But I consider overwriting files in the web path bad design, because you are likely to run into caching issues. Better write a servlet that generates the CSS you need. If you would be able to name the content that should overwrite your css file, you are also able to render this dynamically.
Something like this may be already sufficient:
#RequestMapping(value = "/my.css", produces = "text/css;charset=UTF-8")
public String showCss() {
return "<here goes your css>";
}
(This is written from my memory and not tested).
The good thing is that you can modify the css any time you want and even set caching information as needed.

Categories