73

I am working on a Spring Boot application. I need to parse an XML file (countries.xml) on start. The problem is that I do not understand where to put it so that I could access it. My folders structure is

ProjectDirectory/src/main/java
ProjectDirectory/src/main/resources/countries.xml

My first idea was to put it in src/main/resources, but when I try to create File (countries.xml) I get a NPE and the stacktrace shows that my file is looked in the ProjectDirectory (so src/main/resources/ is not added). I tried to create File (resources/countries.xml) and the path would look like ProjectDirectory/resources/countries.xml (so again src/main is not added).

I tried adding this with no result

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    super.addResourceHandlers(registry);
}

I know that I can add src/main/ manually, but I want to understand why is it not working as it has to. I also tried examples with ResourceLoader - with the same no result.

Could anyone suggest what the problem is?

UPDATE: Just for future references - after building the project, I encountered problem with accessing file, so I changed File to InputStream

InputStream is = new ClassPathResource("countries.xml").getInputStream();
luboskrnac
  • 23,973
  • 10
  • 81
  • 92
lenach87
  • 949
  • 3
  • 11
  • 18

8 Answers8

137

Just use Spring type ClassPathResource.

File file = new ClassPathResource("countries.xml").getFile();

As long as this file is somewhere on classpath Spring will find it. This can be src/main/resources during development and testing. In production, it can be current running directory.

EDIT: This approach doesn't work if file is in fat JAR. In such case you need to use:

InputStream is = new ClassPathResource("countries.xml").getInputStream();
luboskrnac
  • 23,973
  • 10
  • 81
  • 92
  • 1
    Thank you so VERY MUCH!! This really saved me! It does work as expected now – lenach87 Apr 02 '16 at 13:42
  • 1
    how can convert this file to JSonObejct? ( at first data is JSONobject) – Mahdi Jun 03 '17 at 06:22
  • Just to add to @luboskrnac 's answer, also try using `File file = new ClassPathResource(".\countries.xml").getFile();` – Rahul Jawale Nov 08 '17 at 13:23
  • 23
    [Per this answer](https://stackoverflow.com/a/25873705/4009451) `resource.getFile()` expects the file to be on the actual file system, and this solution doesn't work inside a JAR for accessing resources stored under `src/main/resources`. I have confirmed with a simple Spring Boot app. – smeeb Jan 12 '18 at 10:45
  • 3
    @smeeb Thanks. Using `InputStream inputStream = new ClassPathResource("countries.xml").getInputStream();` is what worked for me – TrueKojo May 11 '19 at 16:05
  • Please update your answer according to smeeb's answer, as it will save so many life. – Emdadul Sawon Nov 11 '19 at 18:12
9

While working with Spring Boot application, it is difficult to get the classpath resources using resource.getFile() when it is deployed as JAR as I faced the same issue. This scan be resolved using Stream which will find out all the resources which are placed anywhere in classpath.

Below is the code snippet for the same -

ClassPathResource classPathResource = new ClassPathResource("fileName");
InputStream inputStream = classPathResource.getInputStream();
content = IOUtils.toString(inputStream);
Sachchidanand Singh
  • 1,456
  • 1
  • 15
  • 15
  • 1
    It works. One more thing, please use dependency: commons-io commons-io 2.6 in your springboot application. The old "toString" function is deprecated. You have to use a new version: IOUtils.toString(inputStream, "UTF-8") – AI_ROBOT Aug 30 '18 at 19:45
8

To get the files in the classpath :

Resource resource = new ClassPathResource("countries.xml");
File file = resource.getFile();

To read the file onStartup use @PostConstruct:

@Configuration
public class ReadFileOnStartUp {

    @PostConstruct
    public void afterPropertiesSet() throws Exception {

        //Gets the XML file under src/main/resources folder
        Resource resource = new ClassPathResource("countries.xml");
        File file = resource.getFile();
        //Logic to read File.
    }
}

Here is a Small example for reading an XML File on Spring Boot App startup.

Sanjay Rawat
  • 2,304
  • 15
  • 30
  • Thank you for the answer! The first part, so as suggest by you and luboskrnac saved me! – lenach87 Apr 02 '16 at 13:43
  • @ElenaChubukina Have look at the sample example. You said you need to parse xml on startup.... – Sanjay Rawat Apr 02 '16 at 18:16
  • Thank you! The part with parsing file wasn't a problem (only the part with finding file on classpath) - I use CommandLineRunner, it works fine for me – lenach87 Apr 02 '16 at 21:24
5

I use spring boot, so i can simple use:

File file = ResourceUtils.getFile("classpath:myfile.xml");
Galley
  • 493
  • 6
  • 9
1

You need to use following construction

InputStream in = getClass().getResourceAsStream("/yourFile");

Please note that you have to add this slash before your file name.

Andrew Gans
  • 700
  • 6
  • 9
1

You can use following code to read file in String from resource folder.

final Resource resource = new ClassPathResource("public.key");
String publicKey = null;
try {
     publicKey = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8);
} catch (IOException e) {
     e.printStackTrace();
}
Sanjay Sharma
  • 3,687
  • 2
  • 22
  • 38
1

I use Spring Boot, my solution to the problem was

"src/main/resources/myfile.extension"

Hope it helps someone.

0

Because java.net.URL is not adequate for handling all kinds of low level resources, Spring introduced org.springframework.core.io.Resource. To access resources, we can use @Value annotation or ResourceLoader class. @Autowired private ResourceLoader resourceLoader;

@Override public void run(String... args) throws Exception {

    Resource res = resourceLoader.getResource("classpath:thermopylae.txt");

    Map<String, Integer> words =  countWords.getWordsCount(res);

    for (String key : words.keySet()) {

        System.out.println(key + ": " + words.get(key));
    }
}