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.

Resource.java
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();
}
InputStreamSource.java
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 from InputStreamSource is open. If so it should be closed after the read operation is complete.
  • getInputStream() – Returns an InputStream from InputStreamSource interface.

Typically, followings are the types of resources Spring deals with. They all implement the Resource interface:

  1. UrlResource
  2. ClassPathResource
  3. FileSystemResource
  4. ServletContextResource
  5. InputStreamResource
  6. 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.

ResourcesExample.java
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();
  }
}
Java

1.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.

Java
    //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.

Java
    //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.

ResourceLoader.java
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.

DefaultResourceLoaderExample.java
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

ReaderUtil.java
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();
  }
}
sample.md
## This is a Sample Markdown file

Output:

============ start ===========
## This is a Sample Markdown file
============ End ============
Remember: All application contexts implement the ResourceLoader interface. So, you can also use application contexts to obtain Resource instances.

Java
    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.

JbdResourceLoader.java
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.

ResourceLoaderDemo.java
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.

PrefixExampleDescription
classpth:classpath:resources/config.xmlThe specified resource is loaded from the classpath
file:file:////data/config.ymlLoaded from the specified location on the local filesystem
http:, ftp:https://mysite/logo.pngLoad the image from URL
(empty)/data/config.ymlDepends 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.

XML
<bean id="myBean" class="...">
    <property name="template" value="/resource/myTemplate.txt"/>
</bean>
AnyClass.java
@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.

By |Last Updated: April 2nd, 2024|Categories: Spring Framework|