Instead of reading a file by its pathname, resolve it regarding the classpath.
You simply put the file in src/main/resources or src/test/resources depending on your case, and get an input stream on the file by:
InputStream is = MyClass.class.getResourceAsStream("Environments.xls");
In most cases, you don't really need a java.io.File
, but a means to read it.
And by reading the file this way, you can package your resources in JARs (Maven does it) and the code will still work.
Now if the location of the file to load depends on the target environment (this is a example), here's what I do:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>maven-environment-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-environment-demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<target>
<copy file="${environment.dir}/environment.properties" todir="${project.build.outputDirectory}" />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>development</id>
<properties>
<environment.dir>${project.basedir}/src/main/environment/development</environment.dir>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<environment.dir>${project.basedir}/src/main/environment/staging</environment.dir>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<environment.dir>${project.basedir}/src/main/environment/production</environment.dir>
</properties>
</profile>
</profiles>
</project>
Here, I'm working with properties, but it's for the sake of testing. I'm defining 3 profiles each defining the same property with a different value. This property defines the location of my environment-specific files.
Then, during the process-resources phase I'm copying environment.properties to its proper location for classpath retrieval. Maven does the rest.
Now in order to active one profile, I need to run:
mvn clean install -Pstaging
In the IDE I need to set the profile I wish to work on. In NetBeans, it is done with the dropdown box that appears at the top of the window.
Here is the test class that I used to verify the configuration (here no caching of the properties is done, so don't you use this in production!):
package demo.maven.environment;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class EnvironmentProperties {
public String getProperty(String key) throws IOException {
Properties props = new Properties();
try (InputStream is = EnvironmentProperties.class.getResourceAsStream("/environment.properties")) {
props.load(is);
}
return props.getProperty(key);
}
public static void main(String[] args) throws IOException {
System.out.println(new EnvironmentProperties().getProperty("env.name"));
}
}