0

I've done my research, but I just really can't get it to work. I'm using Spring Boot with Maven. Thymeleaf and jquery for my frontend.

My directory:

project-system/
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── rigor
│   │   │       └── io
│   │   │           └── projectsystem
│   │   │               ├── rush
│   │   │               │   ├── TemporaryController.java
│   │   │               └── ProjectSystemApplication.java
│   │   └── resources
│   │       ├── application.properties
│   │       ├── MOCK_DATA.json
│   │       ├── static
│   │       └── templates
│   │           ├── index.html
│   │           └── records.html

Inside TemporaryController, I'm doing this operation:

list = new ObjectMapper().readValue(new File("./src/main/resources/MOCK_DATA.json"), new TypeReference<List<POJO>>() {});

So with this, I'm able to access the MOCK_DATA.json under the resources directory.

But now, I want to package it into a jar. This is proving a bit troublesome for me. Here's my build in my pom file:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/target/classes/src/main</outputDirectory>
                        <includeEmptyDirs>true</includeEmptyDirs>
                        <resources>
                            <resource>
                                <directory>${basedir}/src/main/</directory>
                                <filtering>false</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>rigor.io.projectsystem.ProjectSystemApplication</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

And the resulting target directory this gives me is:

├── target
│   ├── classes
│   │   ├── application.properties
│   │   ├── MOCK_DATA.json
│   │   ├── rigor
│   │   │   └── io
│   │   │       └── projectsystem
│   │   │           ├── rush
│   │   │           │   ├── TemporaryController.class
│   │   │           └── ProjectSystemApplication.class
│   │   ├── src
│   │   │   └── main
│   │   │       ├── java
│   │   │       │   └── rigor
│   │   │       │       └── io
│   │   │       │           └── projectsystem
│   │   │       │               ├── rush
│   │   │       │               │   ├── TemporaryController.java
│   │   │       │               └── ProjectSystemApplication.java
│   │   │       └── resources
│   │   │           ├── application.properties
│   │   │           ├── MOCK_DATA.json
│   │   │           ├── static
│   │   │           └── templates
│   │   │               ├── index.html
│   │   │               └── records.html
│   │   └── templates
│   │       ├── index.html
│   │       └── records.html
│   ├── generated-sources
│   │   └── annotations
│   ├── generated-test-sources
│   │   └── test-annotations
│   ├── maven-archiver
│   │   └── pom.properties
│   ├── maven-status
│   │   └── maven-compiler-plugin
│   │       ├── compile
│   │       │   └── default-compile
│   │       │       ├── createdFiles.lst
│   │       │       └── inputFiles.lst
│   │       └── testCompile
│   │           └── default-testCompile
│   │               ├── createdFiles.lst
│   │               └── inputFiles.lst
│   ├── surefire-reports
│   │   ├── rigor.io.projectsystem.ProjectSystemApplicationTests.txt
│   │   └── TEST-rigor.io.projectsystem.ProjectSystemApplicationTests.xml
│   ├── test-classes
│   │   └── rigor
│   │       └── io
│   │           └── projectsystem
│   │               ├── ProjectSystemApplicationTests$1.class
│   │               └── ProjectSystemApplicationTests.class
│   ├── project-system-0.0.1-SNAPSHOT.jar
│   └── project-system-0.0.1-SNAPSHOT.jar.original

As you can see, there are some redundancies that are happening, and when I try to run the jar file, it gives me a java.io.FileNotFoundException: ./src/main/resourfces/MOCK_DATA.json (No such file or directory)

Rigo Sarmiento
  • 434
  • 5
  • 21

2 Answers2

1

You cannot treat internal jar resource as a regular file, you need to ask classloader to do it for you, and the path would be relative to top level of the jar (so you want just to ask classloader to load "MOCK_DATA.json" without any paths), or to /resources folder. This is how to do it:

Classpath resource within jar

BTW. /src/main/resources folder is automatic in maven unless you need to configure filtering etc other then defaults :)

maslan
  • 2,078
  • 16
  • 34
  • I tried not coping the resources folder via maven plugin, but they're not put inside a resources directory. So I just want to clarify, the `MOCK_DATA.json` should be under the resources folder, then remove the `maven-resources-plugin` artifact i have in my pom, then use the classloader? I'm trying this but it's not working. ClassLoader is not finding my `MOCK_DATA.json` – Rigo Sarmiento Dec 18 '18 at 07:05
  • Scratch just what I said. I'm now using getClass().getClassLoader().getResourceAsStream. It's good now. – Rigo Sarmiento Dec 18 '18 at 07:11
  • @RigoSarmiento regarding the resources plugin what I wanted to say is : when the resource is in /src/main/resources in your project, then you dont need to declare the plugin because that one is default. Unless you want some specific plugin configuration. If you want additional resource directory or change the path to something else, then the plugin configuration would be necessary – maslan Dec 18 '18 at 07:23
1

If you're trying to read from a .jar, then

new File("./src/main/resources/MOCK_DATA.json"

will NOT work. Instead, you need Class.getResourceAsStream() or equivalent.

Here is an example:

https://www.tutorialspoint.com/java/lang/class_getresourceasstream.htm

  ...
  try {
     // input stream
     InputStream is = this.getClass().getResourceAsStream(MY-RESOURCE);
     BufferedReader br = new BufferedReader(new InputStreamReader(is));
    ...
     is.close();
  } catch(Exception e) {
     System.out.println(e);
  }

Here are some additional details: How getClassLoader().getResourceAsStream() works in java

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
paulsm4
  • 114,292
  • 17
  • 138
  • 190