'Spring boot can not find resource file after packaging

I use Spring boot maven plugin to package application as jar file.

It can find the resource file direct run in Itellij IDE, But it can not find resource file after, it display error as :

java.io.FileNotFoundException: class path resource [jmxremote.password] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/XXX/target/YYY.jar!/BOOT-INF/classes!/jmxremote.password

However, the file "jmxremote.password" indeed exist in the jar file.

    private Properties initialJMXServerProperties() throws RuntimeException {
    URL passwordURL = JMXConfig.class.getClassLoader().getResource(passwordFileName);
    URL accessURL   = JMXConfig.class.getClassLoader().getResource(accessFileName);

    String passFile     = Optional.ofNullable(passwordURL).map(URL::getPath).orElseThrow(() -> new RuntimeException("JMX password file not exist"));
    String accessFile   = Optional.ofNullable(accessURL).map(URL::getPath).orElseThrow(() -> new RuntimeException("JMX access file not exist"));

    Properties properties = new Properties();
    properties.setProperty(PASSWORD_FILE_PROP, passFile);
    properties.setProperty(ACCESS_FILE_PROP, accessFile);
    return properties;
}


Solution 1:[1]

You cannot load the file from a JAR as URL. You have to load it as an InputStream.

In your case:

InputStream passwordInputStream = 
                 JMXConfig.class.getClassLoader().getResourceAsStream(passwordFileName);

Read more about here: Reading a resource file from within jar

Solution 2:[2]

I have also faced similar issue.

class SomeClass{
  @Autowired
  ResourceLoader resourceLoader;

  void someFunction(){
    Resource resource=resourceLoader.getResource("classpath:preferences.json");
    Preferences defaultPreferences = objectMapper.readValue(resource.getInputStream(), Preferences.class);
 }
}

In this case, I have mapped JSON data to the Preferences class. In your case, you may use

resource.getURL()

for further use. This works for both the development environment and deployment, means it also works when you build and deploy JAR/WAR in tomcat or use java -jar.

Solution 3:[3]

    parameters = parameters == null ? new HashMap<>(1) : parameters;
    ApplicationHome h = new ApplicationHome(getClass());
    File jarF = h.getSource();
    String reportPath = "jasperreports" + File.separator + client + File.separator + module + File.separator + jrxml + ".jrxml";
    String realReportPath = jarF.getParentFile().toString() + File.separator + reportPath;
    File reportFile = new File(realReportPath);
    InputStream inputStream;
    if (reportFile.exists()) {
        inputStream = new FileInputStream(reportFile);
    }else {
        ClassPathResource resource = new ClassPathResource(reportPath);
        //Compile to jasperReport
        inputStream = resource.getInputStream();
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Simon Martinelli
Solution 2 sajal rajabhoj
Solution 3 ShakingJ