Spring Boot access static resources missing scr/main/resources
Asked Answered
N

8

74

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();
Neibart answered 2/4, 2016 at 9:52 Comment(6)
Are you adding this file in your web.xml or any config file to tell the app it ExistsCarrington
Only adding the file to the folder won't help app to scan for the fileCarrington
I don't have web.xml, I have a Java-based configuration. Could you please advise me what should I take into account? Maybe you have any sample? I would be very thankful!!!Neibart
Good recommendation by luboskrnacCarrington
For annotation based solution: https://mcmap.net/q/260126/-how-to-get-files-from-resources-folder-spring-frameworkGlaciology
This worked for me was using File file = new File("sampleFile") and SpringBoot was never finding it in my resources/static folder. Thanks for the suggestion!Melchior
D
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();
Donegan answered 2/4, 2016 at 11:42 Comment(6)
Thank you so VERY MUCH!! This really saved me! It does work as expected nowNeibart
how can convert this file to JSonObejct? ( at first data is JSONobject)Micronucleus
Just to add to @Donegan 's answer, also try using File file = new ClassPathResource(".\countries.xml").getFile();Sheeree
Per this answer 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.Imago
@Imago Thanks. Using InputStream inputStream = new ClassPathResource("countries.xml").getInputStream(); is what worked for meSvetlana
Please update your answer according to smeeb's answer, as it will save so many life.Van
C
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);
Churchman answered 13/4, 2018 at 7:3 Comment(1)
It works. One more thing, please use dependency: <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> in your springboot application. The old "toString" function is deprecated. You have to use a new version: IOUtils.toString(inputStream, "UTF-8")Leafstalk
H
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.

Herc answered 2/4, 2016 at 12:22 Comment(3)
Thank you for the answer! The first part, so as suggest by you and luboskrnac saved me!Neibart
@ElenaChubukina Have look at the sample example. You said you need to parse xml on startup....Herc
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 meNeibart
G
5

I use spring boot, so i can simple use:

File file = ResourceUtils.getFile("classpath:myfile.xml");
Googol answered 21/1, 2019 at 5:56 Comment(0)
E
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.

Estival answered 18/6, 2018 at 15:16 Comment(0)
C
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();
}
Corrientes answered 21/10, 2018 at 13:47 Comment(0)
E
1

I use Spring Boot, my solution to the problem was

"src/main/resources/myfile.extension"

Hope it helps someone.

Ethelethelbert answered 4/3, 2019 at 8:11 Comment(0)
A
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));
    }
}
Asch answered 22/10, 2019 at 10:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.