0

I have the following spring boot jar structure

- bootstrap.yml
- org
- META-INF
  -- MANIFEST.MF
  -- Maven
     -- org.account.core
      -- account-service
       -- pom.properties
       -- pom.xml

Now i want to read my pom file from Util class from within the same jar. The below code always returns empty.

public static String findFilePathInsideJar(String matchingFile) throws IOException {
        String path = null;
        File jarFile = new File(FileUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        if (jarFile.isFile()) {
            JarFile jar = new JarFile(jarFile);
            Enumeration<JarEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                String name = entries.nextElement().getName();
                if (name.endsWith(matchingFile)) {
                    path = name;
                    break;
                }
            }
            jar.close();
        }
        return path;
 }

and i call the utility like following

String path = findFilePathInsideJar("pom.xml");

path is always null.

Saurabh Kumar
  • 16,353
  • 49
  • 133
  • 212
  • 1
    There are no files in a jar, only resources. Why do you need the pom? – M. Deinum Oct 17 '18 at 09:57
  • You should use `getResourceAsStream(...)`... – khmarbaise Oct 17 '18 at 09:58
  • @M.Deinum i am reading artifact-id from POM. – Saurabh Kumar Oct 17 '18 at 10:00
  • @khmarbaise I am doing 'getResourceAsStream(...)' but path is empty so call to 'getResourceAsStream(...)' has no effect. The call is there but i put till where I start getting the issue :) – Saurabh Kumar Oct 17 '18 at 10:02
  • Possible duplicate of [How to really read text file from classpath in Java](https://stackoverflow.com/questions/1464291/how-to-really-read-text-file-from-classpath-in-java) – Aleksei Budiak Oct 17 '18 at 10:29
  • @AlekseiBudiak Yeah but i dont know the path of my pom so i need to find it first. If i hardcode than it will not work for another project. – Saurabh Kumar Oct 17 '18 at 11:24
  • Why are you reading stuff from the pom? That is something you shouldn't be doing imho. That should be part of your `application.properties`. – M. Deinum Oct 17 '18 at 11:48
  • @M.Deinum I understand your concern but if somebody changes the artifact id and forgets to change the application.properties than it will create inconsistency. – Saurabh Kumar Oct 17 '18 at 11:50
  • 1
    Then put something in your build that places it in the `application.properties` or use a plugin which adds that to the info endpoint to obtain it. You can even instruct maven not to include those artifacts in your jar. If someone configures it like that you have an issue. – M. Deinum Oct 17 '18 at 11:51
  • @M.Deinum Agree with every point. How to do "Then put something in your build that places it in the application.properties"? – Saurabh Kumar Oct 17 '18 at 11:56
  • You can use [resource filtering](https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) for that. – M. Deinum Oct 17 '18 at 12:08
  • 1
    Or even better use the [spring boot plugin to generate build info](https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/build-info.html). – M. Deinum Oct 17 '18 at 12:22
  • How to read build info file ? – Saurabh Kumar Oct 17 '18 at 12:32

1 Answers1

0

Path is always null because jarFile.isFile() == false :)

Also Path it's useless because you cannot read it later outside JarFile, here’s an example of how to read pom.xml from current Spring Boot uber jar:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) throws IOException {
        SpringApplication.run(DemoApplication.class, args);

        String currentJarPath = deduceCurrentJarPath();
        Optional<InputStream> pom = findFileInJar(currentJarPath, "pom.xml");

        // read pom.xml and print in console
        if (pom.isPresent()) {
            InputStream inputStream = pom.get();
            byte[] pomBytes = new byte[1024 * 1024];
            inputStream.read(pomBytes);
            inputStream.close();
            System.out.println(new String(pomBytes));
        }

    }

    private static String deduceCurrentJarPath() {
        String path = DemoApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        int endPathIndex = path.indexOf(".jar") + ".jar".length();
        int startPathIndex = "file:".length();
        return path.substring(startPathIndex, endPathIndex);
    }

    public static Optional<InputStream> findFileInJar(String jarPath, String fileName) {
        try (JarFile jarFile = new JarFile(new File(jarPath))) {
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = jarEntries.nextElement();
                String name = jarEntry.getName();
                if (name.endsWith(fileName)) {
                    InputStream inputStream = jarFile.getInputStream(jarEntry);
                    byte[] bytes = new byte[inputStream.available()];
                    inputStream.read(bytes);
                    return Optional.of(new ByteArrayInputStream(bytes));
                }
            }
            return Optional.empty();
        } catch (IOException e) {
            e.printStackTrace();
            return Optional.empty();
        }
    }

}
tsarenkotxt
  • 3,231
  • 4
  • 22
  • 38