I'm using a combination of Spring Boot and JAX-RS for my REST API. In my Spring Java Application I have an image located in my resources directory. I want to serve this picture with an URL, it should be something like this:
localhost:8080/api/get/img/1/imageFileName.png
Like this I should be able to use this URL in my Angular Frontend Application in an img tag:
<img src="localhost:8080/api/get/img/1/imageFileName.png"/>
So the issue is, that I really want to have this stuff in my FileSystem. I definately do not want to return a byte array, but that's the only thing I could find so far. This is the only code I could come up with so far:
#GET
#Path("get/img/1")
public String getFile() {
File file = Paths.get(".", "resources", "Mockup9EventsPageAsMember.png").normalize().toFile();
return file.toString();
}
Obviously this will only return the path to the respective directory and not an URL link which I could use in my img tag.
Any suggestions how I can tell my SpringBoot JAX-RS Application to create an URL for me?
I could give you a solution to what you are trying to do, but it is definitely not recommended. The main reason would be the lack of caching. You would need to implement that yourself, which is already provided by the server if you let it serve all the static content.
In a Spring Boot + Jersey app, to be able to serve static content, you need to have the spring-boot-starter-web dependency. Then after that you can put all your static resources into src/main/resources/static1. If you put a file /images/foobar.png in that directory, then you can access it via localost:8080/images/foobar.png.
If you really really want to serve the static content from the resource method (which again I strongly recommend against), you don't have to return a byte[]. You could just return a File or an InputStream. Or you can use StreamingOutput (just search for some examples - you shouldn't have any problems finding any). But again, with this method, you need to take care of sending all the correct caching headers, or else the browser will not cache the files and they will served each time they are requested, which just uses unnecessary resources.
See also
If you have problems accessing the static content, it might be related to this issue
1. There are also more locations. See the docs
Related
I'd like to know if anyone has a solution to access resources of a website through a servlet only.
I have all my resources under WEB-INF. In other words, I don't want users to have direct access to any of my resources.
You can use ServletContext#getResource() for that.
URL resource = getServletContext().getResource("/WEB-INF/file.ext");
File file = new File(resource.getPath());
// ...
You can even use ServletContext#getResourceAsStream() to get an InputStream directly:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/file.ext");
// ...
As you can see in the examples, the ServletContext is available in servlets by the inherited GenericServlet#getServletContext() method.
That said, the phrase I don't want users to have direct access to any of my resources. is a bit contradicting. You're serving those resources by a servlet anyway? A servlet is directly accessible by URL. How is that different from "direct access"? Or do you just want to control the access based on some conditions? I'd say, a Filter is more suitable for this task.
Usually one would only fully hide the JSP files from direct access. In a Servlet which acts as front controller (according the MVC pattern) you could then forward requests to JSP files using RequestDispatcher#forward() which you in turn can obtain by ServletRequest#getRequestDispatcher().
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
You can hide jsp from the end user. In fact, you don't even have to deploy original jsp files with your web application, you can precompile them:
http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html#Web%20Application%20Compilation
And the only way to hide html/js/css files is not to use them. Anything that's sent to the browser can be viewed there.
I am trying to implement a code in our application which needs to monitor the existing registered resources in Jersey and then make decisions accordingly. I know that Jersey provides an application.wadl file which consists of all its resources at runtime.
My question is there a way to look at this file physically? Does Jersey create this file and store it somewhere in the app directory or is it in memory?
Is it possible to call any Jersey api internally on server to get the same info if this particular file is not available like that?
We are using the application class or runtimeconfig. Jersey auto discovers our resources marked with #Path annotation and we are running on Weblogic and Jersey 2.6.
Any help would be appreciated.
Thanks
No WADL file is created on disk. It is created dynamically upon URL request.
http://[host]:[port]/[context_root]/[resource]/application.wadl
E.g.:
http://localhost:8080/rest-jersey/rest/application.wadl
Also, I've found it very useful to inspect the WADL with the SoapUI tool, which can read your WADL from a URL and parse the resources into a tree format. See pic below.
i'm trying to find a way remap a path to an absolute one in order to retrieve images stored in the server filesystem, i'm also using spring mvc but the <mvc:resource> can't map absolute paths, and i can't find a nice way to do this with spring controllers
i.e. I need to map all the image requests from /images/** to /root/var/img/**, in this way when a client browser try to load an image of the page, every images stays in the path above mentioned
You can create a new context with docBase referencing to your folder (/root/var/img) It should look like this:
<Context path=”/images” docBase=”/root/var/img/” ... >
</Context>
Refer to Tomcat context configuration documentation for more details (e.g., for Tomcat 6: Apache Tomcat Configuration Reference: The Context Container).
Introduction to this document lists possible places where context elements can be defined.
EDIT
As I mentioned in comments, Spring-specific way to do this without creating any new context seems to be using RedirectView (link to Spring v2.5 JavaDoc). According to JavaDoc:
"View that redirects to an absolute, context relative, or current
request relative URL, by default exposing all model attributes as HTTP
query parameters."
EDIT2
It seems I've misunderstood RedirectView purpose, which is a good old URL redirection. Thus, answer by #Jens should be more appropriate (+1). I still wonder if there's an existing standard solution in Spring (what I originally thought RedirectView would do..) It's not like there's much code to write, but still :)
EDIT3
After reading more on this topic, I found out that <mvc:resources> is able to do this (i.e., mapping resource using not only relative path, or classpath), you just need to correctly configure location using file: prefix . In fact, there's already answer on SO that explains exactly what you need to do: Spring : serving static resources outside context root
not sure if I am getting that right but I think the common way to do that is to set up a controller which is mapped on the requests to /images/:
#RequestMapping(value ="/images/")
public void fetchImage(#RequestParam String id, HttpServletResponse response)
Then the controller can load the requested image from a configured directory like "/root/var/img" and write it the the OutputStream of the response. E.g:
org.apache.commons.io.IOUtils.copy(fileInputStram, response.getOutputStream())
In addition you have to set the correct mime type etc. in the response.
Jens
I've got a Spring Web MVC application (and also a BlazeDS application, though not as relevant) where files are dynamically generated based on certain client actions.
I'd like to just map a certain directory on the file system to Spring MVC (or the app server) url and let it serve the files in that directory (with streaming and standard last-modified header support). Ideally, the mapped directory would be configured via the spring config, since I already have support per-machine for setting that up.
So, how can I do this? The best I can find so far is to write a controller that reads the file manually and streams it byte-by-byte. However, that seems far less than ideal. Is support for something like this already baked into Spring MVC or the standard application server spec?
Thanks!
If your processing model supports it, why not cut the middleman of the filesystem out of the picture completely and just stream the files back through the response stream as they are generated? Take a look at the AbstractExcelView and AbstractPDFView classes of Spring MVC to see some examples of how this is done.
or the standard application server spec?
Yes, there is. As you didn't mention which one you're using, I'll give a Tomcat-targeted answer. All you basically need to do is to add a Context element for /path/to/your/resources in /conf/server.xml:
<Context docBase="/path/to/your/resources" path="/resources" />
This way they'll be accessible through http://example.com/resources/...
Ideal for this is using an lightweight proxying server in front of your appserver, like a nginx or lighthttpd. You can configure it for serving static content, without calling your app.
If directory and files so dynamic, you can prepare real path to file at your controller and give this filepath to the frontend server, using headers. For example for nginx it's a X-Accel-Redirect header. Read more about this (and follow links for other http servers) there
We want to share user validation configuration between a Java validation class (for sanity checking) and a Javascript-enabled form web interface (for usability). What's the best way to deploy this static file in our web application so that it is both available to the server-side code, and available via a URL accessed by the client?
So far I've thought of putting the file in the application root and pointing the validation class at it when it is used, and putting the file in the WEB-INF/classes directory and somehow configuring the container to serve it.
Has anyone else configured a web application like this? What did you end up doing?
Yeah. Put it in the WEB-INF/classes and have a servlet serve out the relevant portion of the validation configurations based on something like a form-id. Better yet, have the servlet transform the configuration into a JSON object and then you can simply include a script tag and start using it :)