Reputation: 105
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:
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});
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
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())
Always use forward slashes (/
) in path names. Java handles them correctly on windows too.
Upvotes: 1