This article touches upon how to Handle Resources in Spring and we will look into the various interfaces like Resource, ResourceLoader, and ResourceLoaderAware. We usually do not have to make any modifications to the way in which Spring works with resources. We will specifically learn how Spring handles resources.
Do not be confused with @Resource annotation. This article is about resources like File, URLResources, ServletContext, etc. For @Resource, check out the related article – Guide on @Autowired, @Resource and @Inject in Spring.
1. Resource interface in Spring
Java provides java.net.URL
class for handling standard URL resources. However, it cannot load a resource from classpath or relative to ServletContext and so on. Spring provides additional features to deal with these resources.
Spring has a Resource interface with more capabilities to deal with low-level resources. Spring not only allows you to deal with low-level resources powerfully but also it uses Resource abstraction extensively inside its core.
public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
As you can see above, the Resource interface has several useful methods such as:
exists()
– Indicates if the provided resource actually exists in physical form.isOpen()
– Represents if the inputStream fromInputStreamSource
is open. If so it should be closed after the read operation is complete.getInputStream()
– Returns an InputStream fromInputStreamSource
interface.
Typically, followings are the types of resources Spring deals with. They all implement the Resource
interface:
- UrlResource
- ClassPathResource
- FileSystemResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
1.1. UrlResource in Spring
The UrlResource
class implements the Resource
interface and adds extra features on top of java.net.URL
and java.net.URI
. You can use this class to access any resource that is available on http://
, https://
or ftp://
. Here is an example of the same.
public class ResourcesExample {
public static void main(String[] args) throws IOException {
Resource urlResource = new UrlResource("https://google.com");
readAndPrint(urlResource.getInputStream());
}
public static void readAndPrint(InputStream stream) throws IOException {
int content = stream.read();
System.out.println("\n============ start ===========");
while (content != -1) {
System.out.print((char)content);
content = stream.read();
}
System.out.println("\n============ End ============");
stream.close();
}
}
Java1.2. ClassPathResource in Spring
This class represents a resource that are present in the classpath. Internally, it either uses a thread context class loader or a given class loader to obtain the resource.
//Fetching sample.md from classpath
Resource classPathResource = new ClassPathResource("sample.md");
readAndPrint(classPathResource.getInputStream());
1.3. FileSystemResource in Spring
The FileSystemResource class is an implementation for java.io.File
and java.nio.file.Path
handles. It supports resolution as a File and as a URL. This is used to access Files/resources from the local system.
//Use it with the first example
FileSystemResource fileResource = new FileSystemResource("PathToFile/filename");
readAndPrint(fileResource.getInputStream());
1.4. ServletContextResource in Spring
This resource is an implementation of ServletContext
in a Spring MVC application. It interprets relative paths in a Web application root directory.
I encourage you to see the sample of ServletContextResource usage on Codota.
1.5. InputStreamResource in Spring
It is a Resource implementation for a given InputStream. Use only if no specific Resource implementation is applicable. Prefer using ByteArrayResource
or any of the file-based Resource
implementations wherever possible.
1.6. ByteArrayResource in Spring
This is a Resource implementation for a given byte array. It creates a ByteArrayInputStream for a given byte array. It is useful for loading content from any given byte array without having to resort to a single-use InputStreamResource.
2. Use the ResourceLoader interface
The ResourceLoader interface in Spring is meant to be implemented by objects that can load and return a Resource instance. All application Contexts implements this interface.
public interface ResourceLoader {
Resource getResource(String location);
}
There are several implementations of ResourceLoader available in Spring. These are DefaultResourceLoader
, FileSystemResourceLoader
, ClassRelativeResourceLoader
etc. Below is a simple example that demonstrates the use of DefaultResourceLoader
.
package c.jbd.spring.resources;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import java.io.IOException;
public class DefaultResourceLoaderExample {
public static void main(String[] args) throws IOException {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource r = resourceLoader.getResource("sample.md");
ReaderUtil.readAndPrint(r.getInputStream());
}
}
ReaderUtil is just a simpel util class that reads the file content and prints
package c.jbd.spring.resources;
import java.io.IOException;
import java.io.InputStream;
public class ReaderUtil {
public static void readAndPrint(InputStream stream) throws IOException {
int content = stream.read();
System.out.println("\n============ start ===========");
while (content != -1) {
System.out.print((char) content);
content = stream.read();
}
System.out.println("\n============ End ============");
stream.close();
}
}
## This is a Sample Markdown file
Output:
============ start ===========
## This is a Sample Markdown file
============ End ============
ApplicationContext ctx = new ClassPathXmlApplicationContext();
Resource resource = ctx.getResource("conf/appContext.xml");
3. Use the ResourceLoaderAware interface
In the above section, we learned to use the ResourceLoader interface. Spring also provides a way to automatically inject a ResourceLoader in your custom components by implementing ResourceLoaderAware
interface.
As per the documentation, The ResourceLoaderAware interface is a special callback interface which identifies components that expect to be provided with a ResourceLoader
reference.
package c.jbd.spring.resources.loader;
import c.jbd.spring.resources.ReaderUtil;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component("jbdResourceLoader")
public class JbdResourceLoader implements ResourceLoaderAware {
private ResourceLoader resourceLoader;
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void loadResource(String resourcePath) throws IOException {
Resource resource = resourceLoader.getResource(resourcePath);
ReaderUtil.readAndPrint(resource.getInputStream());
}
}
Lets make use of the JbdResourceLoader in the ResourceLoaderDemo test class and see the output.
package c.jbd.spring.resources.loader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
public class ResourceLoaderDemo {
public static void main(String[] args) throws IOException {
ApplicationContext ctx = new AnnotationConfigApplicationContext(JbdResourceLoader.class);
JbdResourceLoader loader = (JbdResourceLoader) ctx.getBean("jbdResourceLoader");
loader.loadResource("classpath:sample.md");
System.out.println("*** Resource loader using classpath ***");
}
}
Output:
============ start ===========
## This is a Sample Markdown file
============ End ============
*** Resource loader using classpath ***
4. Resource string usages
You have seen in the above examples, the classpath resources are passed as classpath:com/myapp/config.xml
and the URL resources as https://myserver/logo.png
. There are proper prefixes which should be used to indicate its type and location.
Prefix | Example | Description |
---|---|---|
classpth: | classpath:resources/config.xml | The specified resource is loaded from the classpath |
file: | file:////data/config.yml | Loaded from the specified location on the local filesystem |
http:, ftp: | https://mysite/logo.png | Load the image from URL |
(empty) | /data/config.yml | Depends on the ApplicationContext implementation. |
4.1 Inject resource as dependency
You can also use the resource as a property value. You can use the @Value
annotation to set the value. Or use it in your xml config as below.
<bean id="myBean" class="...">
<property name="template" value="/resource/myTemplate.txt"/>
</bean>
@Component
public class AnyClass {
@Value("/resource/myTemplate.txt")
private String template;
...
}
4.2 Wildcards (*) in Resource paths
Application Context allows us to specify a wildcard pattern (*) in the resource paths. These are shown below
/WEB-INF/*-context.xml
com/jbd/**/applicationContext.xml
file:C:/myapp/path/*-context.xml
classpath:com/jbd/**/applicationContext.xml
Conclusion
This article provides a concise overview of Resource, ResourceLoader, and ResourceLoaderAware in Spring, offering valuable insights into how Spring handles resources internally. While not delving deeply into each topic, it effectively informs readers about these essential concepts.
Resource, ResourceLoader, and ResourceLoaderAware are fundamental components in Spring for managing and accessing resources such as files, URLs, and classpath resources. Understanding how Spring handles resources is crucial for developers working on Spring applications, as it enables efficient resource management and integration within the application context.
By discussing these topics, the article equips readers with the foundational knowledge needed to work with resources effectively in Spring. Additionally, by inviting readers to share their thoughts in the comments, the article fosters engagement and encourages further discussion on this important aspect of Spring development.
Overall, the article serves as a valuable introduction to Resource, ResourceLoader, and ResourceLoaderAware in Spring, providing readers with a solid understanding of these concepts and their significance in Spring application development.