dtkx
dtkx

Reputation: 105

Maven relative path best practices

I have been looking for a while for practical examples to understand Maven relative paths best practices to get Resources, however I got confused, hoping you could please support me to understand what are best practices to get Resources and how to apply to a concrete example:

Concrete Example:

Structure Say I have the following structure and trying to get a resource(located in resources) from a class in the folder planning, so basically I am trying to create a String of a relative path that is consistent with maven execution:

├───.settings
├───images
├───src
│   ├───main
│   │   ├───java
│   │   │   └───com
│   │   │       └───moga
│   │   │           ├───planning --->Trying to get a resource from here
│   │   │           ├───population
│   │   │           │   ├───chromossome
│   │   │           │   ├───gene
│   │   │           │   └───initialpopulation
│   │   │           └───utils
│   │   └───resources
│   │       └───com
│   │           └───moga
│   │               └───planning
│   │                   └───sample
│   └───test
│       ├───java
│       │   └───com
│       │       └───moga
│       │           ├───planning
│       │           └───population
│       │               ├───chromossome
│       │               └───gene
│       └───resources
│           └───com
│               └───moga
│                   └───planning <-- Resource that I want to get is here
│                       └───sample
└───target
    ├───classes
    │   └───com
    │       └───moga
    │           ├───planning
    │           │   └───sample
    │           ├───population
    │           │   ├───chromossome
    │           │   ├───gene
    │           │   └───initialpopulation
    │           └───utils
    ├───generated-sources
    │   └───annotations
    ├───generated-test-sources
    │   └───test-annotations
    ├───maven-archiver
    ├───maven-status
    │   └───maven-compiler-plugin
    │       ├───compile
    │       │   └───default-compile
    │       └───testCompile
    │           └───default-testCompile
    ├───surefire-reports
    └───test-classes
        └───com
            └───moga
                ├───planning
                │   └───sample
                └───population
                    ├───chromossome
                    └───gene

Class RunCapacityPlanning that gets the resource I am currently using the following quick fix

Path pathCapacityPlanningGeneral = Paths.get(System.getProperty("user.dir"),
        "src","test","resources","com","moga","planning","paramsGeneral.txt");
File file = new File(pathCapacityPlanningGeneral.toString());
if (!file.exists()) {
    System.out.println("File Do not exist");
    System.out.println(pathCapacityPlanningGeneral.toString());
}

The above code is builded with mvn package and the file exists(Do not print the message).

POM

...
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
...

Approaches Here are some potential approaches I have found:

  1. Maven Official
    File file = new File( path );
    if ( !file.isAbsolute() )
    {
        file = new File( project.getBasedir(), file );
    }
    

To test this approach, here is what I tried:

From this I understand that I should add this to my POM

  <properties>
<project.basedir>somepath</project.basedir>
...
  </properties>

public static void main(String[] args) throws IOException {
    // 1) Approach 1
    // $ cannot be resolved to a variable,
    // project cannot be resolved
    System.out.println(${project.baseDir});
  1. Use getResource Basically I tested modify the main file:
URL pathCapacityPlanningGeneral =
        RunCapacityPlanning.class.getResource("paramsGeneral.txt");
File file = new File(pathCapacityPlanningGeneral.toString());
if (!file.exists()) {
    System.out.println("File Do not exist");
    System.out.println(pathCapacityPlanningGeneral.toString());
}

The above after mvn package java -cp target/CapacityPlan-1.0-SNAPSHOT.jar com.moga.planning.RunCapacityPlanning throws:

File Do not exist
jar:file:/C:/Users/.../capacityplan/target/capacityplan-1.0-SNAPSHOT.jar!/com/moga/planning/paramsGeneral.txt

Do anybody knows what I am doing wrong in this approach?

Thanks so much in advance

Upvotes: 2

Views: 773

Answers (1)

Timothy Truckle
Timothy Truckle

Reputation: 15622

The Point here is:
The resources are resolved using the Class Path, and not along your project directory layout. This means that resource resolution start below
src/[main|test]/[java|resources]/

The best way to resolve a resource ist to look it up by

new File(getClass()
          .getResource("the resource relative path")
          .toURI()) 

This way it does not matter it that resource is in a plain directory or inside a jar.

"the resource relative path" can start with a /. In that case it is resolved relative to the CLASSPATH root. If it does not start wit / it is resolved relative to the current package.

In your example it the folder planning is what you want you could either use

// from package "planning" one level up
new File(getClass()
            .getResource("../plannung")
            .toURI()) 

or

// from CLASSPATH root decending
new File(getClass()
            .getResource("/com/moga/plannung")
            .toURI()) 

ATTENTION!

Always use forward slashes (/) in path names. Java handles them correctly on windows too.

Upvotes: 1

Related Questions