How to serve images on Spring based web services - java

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.

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.

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

Is it possible to enable directory listing in Spring Boot application?

We're migrating an existing application to Spring Boot. The application in question (Genie) acts as a distributed, scalable client for data processing clusters like Hadoop or Presto. As such we need to output results of queries to disk and allow users access to their data. In the past we've done this by enabling directory listing in Tomcat where we would deploy our war and allowing users to browse and access their files using the DefaultServlet.
I tried exporting the directory using resource handlers like so:
#SpringBootApplication
public class GenieWeb extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {
// Other configuration
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
final String myExternalFilePath = "file:///path/to/dir/";
registry
.addResourceHandler("/urlPath/*")
.setCachePeriod(0)
.addResourceLocations(myExternalFilePath);
}
}
This works fine when the URI of the resource is known but any request for a directory returns a 404. Ideally this would behave the same way the DefaultServlet in standalone Tomcat behaves when listings is set to true as an init parameter.
I've tried various ways to access the Tomcat configuration and the DefaultServlet in particular but have had no luck enabling directory listing via the typical "listing" property.
Excessive searching didn't turn up any results so I was curious if anyone knew if this was possible before I resign myself to going back to a WAR build or fronting with Apache. The main reason I don't want to do this is to make deploying our application as painless as possible and having everything self contained in one jar file has a lot of appeal.
Thanks in advance!

Should I use ServletDispatcher when trying to make an angular webapp, with no jsp pages?

I have medium knowledge on how to make java webapps, and jsp pages. I am trying to extend my expertise, by learning how to use Spring MVC, AngularJS and RESTful api's.
I am having trouble drawing the lines between the dots. First of all, from what I have read, there should be no real need for jsp pages, when trying to do pure angularJS. So I'm trying to not use jsp's this time.
I am pretty much trying to make two html-pages, each with a link to the other. Now in a completely basic Spring MVC setup, this would be done with the help of two controllers, and the ServletDispatcher. In the servlet-context.xml (default name) I could probably change the default suffix from .jsp to .html, but I have read that I should treat static html pages as resources, instead of views, as they do not need the powers of a servlet.
The thing is, I have never made any kind of web page which didn't utilize a dispatcher, or front controller servlet, and although it might be completely obvious to most, I do not know what the alternative is. I am very in doubt if I am supposed to use the ServletDispatcher at all, and what the alternative is. I kinda thought the ServletDispatcher, and front controller pattern implementation was one of the most central parts of Spring...
So should I use the ServletDispatcher for an Angular web application, or should I just use Spring to make the RESTful api?
Spring framework allows you to serve static resources using ResourceHttpRequestHandlers which stores registrations of resource handlers for serving static resources such as images, css files and others through Spring MVC including setting cache headers optimized for efficient loading in a web browser. Resources can be served out of locations under web application root, from the classpath, and others.
Since you already have a basic spring MVC setting and running, then you need to configure your angularJS-app as a static resources, you can choose to keep your angularJS application folder under webapp folder, and continues your angularJS development there and you don`t need any JSP there.
Configure ResourceHttpRequestHandlers
with XML
<mvc:resources mapping="/app/**" location="/app/"/>
with Java config
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/app/**").addResourceLocations("/app/");
}
}
Now you can access your angularJS app as http://localhost:8080/context-root/app/
Your API development will continue as well in your spring MVC controllers.
Here is a great youtube series of Web Development Using Spring and AngularJS
Use AngularJS to make static web pages(HTML+CSS+JS+other static resources).
Use Servlet to make RESTful API.(Restlet framework is recommended to make RESTful API, it can run as a standalone java app or integrate into Servlet to run in Tomcat.)
JS will call RESTful API to get data and update the page view.

How should a spring MVC presentation layer be structured compared to a Symfony2 app?

To better understand what I'm trying to achieve here is an image of a typical Symfony2 application with only one bundle and a spring MVC app side by side:
I know there is a conceptual difference between Symfony2 which can be used to build a whole application and Spring MVC which can also be used to build a whole application, but in my case I want it to act as my presentation layer only.
Working with Spring MVC somewhat feels like working with raw bare metal. I prefer an opinionated approach. I want to have something similar to bundles in Symfony2 where each bundle houses its controllers, views, forms, templates, configurations, js and css. I want views to be grouped by controller name.
I want something that houses the configurations for the whole application such as the database or email server in addition to somewhere where I can add layouts for all "bundles". I want cache and logs folders.
I know that I can create all of that manually, but I got that feeling that there should be something like a standard folder structure for spring MVC applications.
I almost sound like I searching for a framework built on top of Spring MVC (maybe this is the solution after all), but maybe I'm having the wrong approach to the whole thing.
Note: My business logic is housed in separate bounded contexts. The presentation layer is part of the application that will communicate with all these contexts.
First of all I want to tell that I build a lot of php apps with Symfony (not Symfony 2) so there might be some inconsistency in what I'm telling, but I can share my point of view anyway.
First of all Symfony, as written in php, is complete framework for everything. It has a vision of folder (package) structure not only because it makes your code well organized... but also due to technical limitatins of php. Php is mostly basing on incuding other php sources by using directives like:
include ('/lib/somelib.lib.php');
This is the only way php can load resources. This leads to some consequences in writing frameworks in php. For example in Symfony when you point your browser to http://localhost/some_module/some_url symfony will assume "by convenction" that you want to load a controller named: some_module and you want to execute method some_url in this controller. At the first glance this sounds great, but there is one "catch" in this. Symfony requires it because this is the only way Symfony can infer which controller and which method you want to load (this is probably similar in Symfony2). Otherwise you would need to create extra configuration file.
Java on the other hand gives you many ways to achieve this without forcing you the name of your controller and a method. Spring MVC simply utilizes what java gives you. In Spring you can give any name to your controller, and any name to your method. You can achieve this for example by using annotatations on controller class and method:
#Controller
public class MyController {
#RequestMapping(value = "/some_module/some_url", method = RequestMethod.GET)
public ModelAndView searchForSomeData(#PathVariable("currentPage") String currentPageUrlString, #RequestParam("userId") Integer userId) {
(...)
}
You can place your controller in any folder (package) and spring will discover it via "component scanning feature". You don't need to rely on "convention over configuration" which is used in php (because of it's limitations). You can create some "standard" folder structure but you don't have to.
Another thing is that Symfony (also due to some limitations how php applications are built) forces you to use its's own template engine as view technology. That's why there is what you called "grouping controllers by view name" (you can use other engines for view processing like Smarty but this comes with pain). In Spring on the other hand you are not bound to any view technology. You can use Apache Tiles, jsp pages and whatever you want. You just configure it and use it. What is more you can use two or more view technologies in one application - you only need to tell spring when to use one view technology and when to use the other (for example basing on url prefix). The configuration is surprisingly simple. Simply use annotations, for example like this:
#Configuration
public class WebConfig {
#Autowired
#Qualifier("tilesViewResolver")
private ViewResolver tilesViewResolver;
#Autowired
#Qualifier("jstlViewResolver")
private ViewResolver jstlViewResolver;
#Bean
#DependsOn({ "tilesViewResolver", "jstlViewResolver" })
public ViewResolver viewResolver() {
Map<String, ViewResolver> resolvers = new HashMap<>();
resolvers.put("internal", jstlViewResolver);
resolvers.put("tilesView", tilesViewResolver);
ViewResolver globalViewResolver = new PrefixViewResolver(resolvers, jstlViewResolver);
return globalViewResolver;
}
#Bean(name = "tilesViewResolver")
public ViewResolver tilesViewResolver() {
UrlBasedViewResolver url = new UrlBasedViewResolver();
url.setViewClass(TilesView.class);
return url;
}
#Bean(name = "jstlViewResolver")
public ViewResolver jstlViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/internal/");
resolver.setViewClass(JstlView.class);
resolver.setSuffix(".jsp");
return resolver;
}
}
So again here Spring does not force you to use anything because it does not operate in environment with some limitations like Symfony in php.
The same goes for logs folder and others. You don't get the logs folder because you need to declare which technology you want to use for logging in Spring/java (whether it is log4j, logback, commons logging, slf4j etc). In symfony you have your logs folder defined because of two reasons. Firstly you are forced (some people will say "encouraged", but I prefer to name it "forced") to use Symfony's logging system which by default is configured to use "logs" directory in your application directory. Secondly again the limitations/characteristics of php comes - when you deploy php application you usually keep the logs in application folder because you don't have permission to write to any other folder on filesystem. When you deploy java application on Tomcat you usually keep the logs in Tomcat directory or other directory on filesystem.
So the bottom line is freedom. That's why you don't get any "standard" in Spring MVC in this area. You create your own standard which fits your application.

Categories