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

This 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://.

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();
  }
}

1.2. ClassPathResource in Spring

This class represents a resource that needs to be 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

This 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());
  }
}
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();
  }
}
============ 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.

    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());
  }
}
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 ***");
  }
}
## This is a Sample Markdown file
============ 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.

<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 has given you information on Resource, ResourceLoader & ResourceLoaderAware. You have learned about the Resources in Spring and how Spring handles them internally. I have not gone deep on each of these topics but discussed to keep you informed. Let me know your thoughts on the comments below.