-1

I make a Spring Boot web application, and I have to read static (.json) files on startup.

No problem, it works when I start the app in Idea. But if I run mvn package, and start I start the jar, the given path (BASE_DIR) does not exists anymore, so the files cannot be found.

How can I solve to read the files starting with Idea and the .jar as well?

package skyxplore.dataaccess.gamedata.base;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.apache.commons.io.FilenameUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import skyxplore.dataaccess.gamedata.entity.abstractentity.GeneralDescription;

@Slf4j
public abstract class AbstractGameDataService<V> extends HashMap<String, V> {
    public static final String BASE_DIR = "src/main/resources/data/gamedata/";

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final JsonFileFilter jsonFilter = new JsonFileFilter();

    private final String source;

    public AbstractGameDataService(String source) {
        this.source = BASE_DIR + source;
    }

    protected void loadFiles(Class<V> clazz) {
        File root = new File(source);
        if (!root.exists()) {
            throw new IllegalStateException("Source directory does not exists. Path: " + root.getAbsolutePath());
        }
        if (!root.isDirectory()) {
            throw new IllegalArgumentException("Source must be a directory. Path: " + root.getAbsolutePath());
        }
        File[] files = root.listFiles(jsonFilter);
        for (File file : files) {
            try {
                String key = FilenameUtils.removeExtension(file.getName());
                V content = objectMapper.readValue(file, clazz);
                if (content instanceof GeneralDescription) {
                    GeneralDescription d = (GeneralDescription) content;
                    log.info("Loaded element. Key: {}, Value: {}", key, content);
                    put(d.getId(), content);
                } else {
                    throw new RuntimeException(source + " cannot be loaded. Unknown data type.");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public abstract void init();
}
Saphyra
  • 450
  • 3
  • 15

2 Answers2

-1

After you package your applications, resource files are no longer accessible from file system - thus you cannot list/open them using File. You need to read them as resources from JAR using class.readResourceAsStream for example. When you run it from IntelliJ files are not read from JAR but from project directory.

Here you have Oracles Java tutorial on how to use resources

Another solution (as you have some additional logic for reading files) you could put files aside JAR not as resource and read it from there then.

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • class.getResourceAsStream returns stream of one specified file. But I have to scan one specified folder, and read all files one by one. – Saphyra Jul 23 '18 at 14:51
  • 1
    I know, that is problem you have to overcome. Google on how to list resources. – Antoniossss Jul 23 '18 at 14:54
-1
BASE_DIR = "src/main/resources/data/gamedata/"

Once you do a mvn package, src/main/resources folder becomes the root of the jar. You can use a class-loader to load this file. Something like:

AbstractGameDataService.class.getResourceAsStream("/data/gamedata/<your json file>")

Other possibility since you are using spring-boot, you can leverage spring scanning itself. Using spring constructs load file using : classpath:/data/gamedata/<your json file>

Himanshu Bhardwaj
  • 4,038
  • 3
  • 17
  • 36