Spring – ResourceLoaderAware with Example

In this article, we will discuss the various ways through which we can load resources or files (e.g. text files, XML files, properties files, etc.) into the Spring application context. These resources or files may be present at different locations like in the file system, classpath, or URL. Spring provides the Resource and ResourceLoader interfaces. The Resource interface represents external resources and the ResourceLoader interface provides a unified method i.e. getResource() to retrieve an external resource represented by a resource object.

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();
}
  
public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}


Java




public interface ResourceLoader {
    Resource getResource(String location);
}


As we discussed earlier, the Resource interface represents an external resource. As we know, we can’t create an object of the interface. Spring provides the following 6 implementations for the Resource interface.

  • UrlResource: Represents a resource loaded from a URL.
  • ClassPathResource: Represents a resource loaded from the classpath.
  • FileSystemResource: Represents a resource loaded from the filesystem.
  • ServletContextResource : This implementation is for ServletContext resources.
  • InputStreamResource: Represents an input stream resource.
  • ByteArrayResource: Represents a byte array resource.

There are a few ways through which we can read/load external files via. creation of Resource object.

1. Through the ApplicationContext Interface

Java




public interface ResourceLoader {
    Resource getResource(String location);
}


The ResourceLoader interface is meant to be implemented by objects that can return (i.e. load) Resource instances. In Spring, all application contexts implement the ResourceLoader interface. Therefore, all application contexts may be used to obtain Resource instances. Let’s see how we can load/read external resources/files by using application context :

Java




package com.gfg.technicalscripter;
  
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
  
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
  
public class App {
    public static void main(String[] args)
    {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext();
  
        // Through File system
        Resource fileResource = applicationContext.getResource("file:c:\\gfg-testing.txt");
  
        // Through URL path
        Resource urlResource = applicationContext.getResource("url:http:// www.gfg.com/gfg-testing.txt");
  
        // Through Classpath
        Resource classpathResource = applicationContext
                                         .getResource("classpath:com/gfg/technicalscripter/gfg-testing.txt");
  
        readFileThroughResource(classpathResource);
        // We can call readFileThroughResource for
        // any resource object representing a file
    }
  
    private static void readFileThroughResource(Resource resource)
    {
        try {
            InputStream is = resource.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
  
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Spring project structure & gfg-testing.txt file content:

 

 

Screenshot of output console:

 

2. Through the ResourceLoaderAware interface

Since spring bean does not have access to the spring application context, So how can a bean load/access resources or files (e.g. text files, XML files, properties files, etc.)? To solve this issue, the workaround is to implement the ResourceLoaderAware interface and create a setter method for the ResourceLoader object. At last, spring will inject the resource loader into your bean.

Java




package com.gfg.technicalscripter;
  
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
  
public class CustomResourceLoader implements ResourceLoaderAware {
  
    private ResourceLoader resourceLoader;
  
    public void setResourceLoader(ResourceLoader resourceLoader)
    {
        this.resourceLoader = resourceLoader;
    }
  
    public Resource getResource(String location)
    {
        return resourceLoader.getResource(location);
    }
}


XML




<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  
    <bean id="customResourceLoader" class="com.gfg.technicalscripter.CustomResourceLoader" />
  
</beans>


Java




package com.gfg.technicalscripter;
  
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
  
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
  
public class App {
    public static void main(String[] args)
    {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:com/gfg/technicalscripter/config.xml");
        CustomResourceLoader customResourceLoader = applicationContext.getBean(CustomResourceLoader.class);
        Resource classpathResource = customResourceLoader
                                         .getResource("classpath:com/gfg/technicalscripter/gfg-testing.txt");
  
        readFileThroughResource(classpathResource);
    }
  
    private static void readFileThroughResource(Resource resource)
    {
        try {
            InputStream is = resource.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
  
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Screenshot of output console:

 

When a class implements ResourceLoaderAware and is deployed into an application context (as a Spring-managed bean), it is recognized as ResourceLoaderAware by the application context. The application context will then invoke the setResourceLoader(ResourceLoader), supplying itself as the argument (remember, all application contexts in Spring implement the ResourceLoader interface). This getResource() method is very helpful to deal with different resources with different solutions, like File object for file system resource, and URL object for URL resource and it really saves a lot of time.