65

Hello I'm using a configuration file from src/main/resources in my java application. I'm reading it in my Class like this :

new BufferedReader(new FileReader(new File("src/main/resources/config.txt")));

So now I'm building this with maven using mvn assembly:assembly. Here is the bit for that in my pom.xml :

<plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <finalName>TestSuite</finalName>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>com.some.package.Test</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

So when I run my app I get this error :

src\main\resources\config.txt (The system cannot find the path specified)

But when I right click on my assembled jar I can see it inside, anyone knows what I'm doing wrong?

Gandalf StormCrow
  • 25,788
  • 70
  • 174
  • 263

6 Answers6

100

Resources from src/main/resources will be put onto the root of the classpath, so you'll need to get the resource as:

new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/config.txt")));

You can verify by looking at the JAR/WAR file produced by maven as you'll find config.txt in the root of your archive.

beny23
  • 34,390
  • 5
  • 82
  • 85
  • 1
    Could you add a little text to your answer explaining what Maven did that causes this difference? That would be a big help. Thank ye. – john_science Sep 28 '13 at 04:20
  • 3
    As stated, Maven puts resources from `src/main/resources` into the root of the classpath, so there is no `src/main/resources` directory in the JAR file - in the same way, the `.class` files are not in a directory called `src/main/java`. Does that make sense? – beny23 Sep 29 '13 at 14:14
  • 14
    If you are in a static context then you can also use "Thread.currentThread().getContextClassLoader()" instead of "getClass()". – Benny Code Apr 15 '14 at 14:10
16

FileReader reads from files on the file system.

Perhaps you intended to use something like this to load a file from the class path

// this will look in src/main/resources before building and myjar.jar! after building.
InputStream is = MyClass.class.getClassloader()
                     .getResourceAsStream("config.txt");

Or you could extract the file from the jar before reading it.

assylias
  • 321,522
  • 82
  • 660
  • 783
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • src/main/resources does not work cause they will be copied to the target/classes folder and be packaged into the jar. – khmarbaise Apr 16 '12 at 08:56
  • I have corrected that. Thank you. It works if you have `.` in your class path but for the wrong reasons. i.e. it reads the original rather than the copy. – Peter Lawrey Apr 16 '12 at 08:57
  • @beny23 That may be simpler than using `getClassLoader()` which always looks at the root/top level. – Peter Lawrey Apr 16 '12 at 09:06
6

The resources you put in src/main/resources will be copied during the build process to target/classes which can be accessed using:

...this.getClass().getResourceAsStream("/config.txt");
Alexandre Bourdin
  • 825
  • 1
  • 14
  • 30
khmarbaise
  • 92,914
  • 28
  • 189
  • 235
4

Once after we build the jar will have the resource files under BOOT-INF/classes or target/classes folder, which is in classpath, use the below method and pass the file under the src/main/resources as method call getAbsolutePath("certs/uat_staging_private.ppk"), even we can place this method in Utility class and the calling Thread instance will be taken to load the ClassLoader to get the resource from class path.

 public String getAbsolutePath(String fileName) throws IOException {
      return Thread.currentThread().getContextClassLoader().getResource(fileName).getFile();
  }

enter image description here enter image description here

we can add the below tag to tag in pom.xml to include these resource files to build target/classes folder

<resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.ppk</include>
            </includes>
        </resource>
</resources>
vijay
  • 609
  • 5
  • 9
1

I think assembly plugin puts the file on class path. The location will be different in in the JAR than you see on disk. Unpack the resulting JAR and look where the file is located there.

Rostislav Matl
  • 4,294
  • 4
  • 29
  • 53
-1

You can replace the src/main/resources/ directly by classpath:

So for your example you will replace this line:

new BufferedReader(new FileReader(new File("src/main/resources/config.txt")));

By this line:

new BufferedReader(new FileReader(new File("classpath:config.txt")));
Ahmed Elkoussy
  • 8,162
  • 10
  • 60
  • 85