Filtering environment specific configuration files
TweetPosted on Tuesday Mar 04, 2014 at 04:45PM in Technology
Environment
- Apache Maven 3.1.1
- Jenkins 1.551
- Eclipse Kepler SR1
- Oracle JDK7u51
- PostgreSQL 9.2.4
- OS X 10.9.2
Requirement
- I'm searching an appropriate way to define environment specific configuration.
- I don't want to create separate files for each environment.
- I don't want to define environment specific information on pom.xml.
Where to define?
- There are some candidates for achieve it with Maven.
- Maven Properties
- Maven can reference it as ${name}.
- Java System Properties
- Maven can reference it as ${name}.
- Environment Variables
- Maven can reference it as ${env.name}.
- Maven Properties
Maven Properties
- User-local properties are can be defined on ~/.m2/settings.xml
- It's easy to define on Jenkins jobs through configuration of MAVEN_OPTS.
- We can specify it like: “-Dname=value”
- We have to take care on Eclipse to make sure select a profile explicitly.
- activeByDefault won't work on some cases[8].
- I go with this way at this time.
Java System Properties
- We need to define it through arguments of java command.
- It's annoying to define on Eclipse.
- I can't found any way on define globally for Run Configuration.
- Thus, I have to configure it for each programs. It's pretty annoying.
- It's easy to define it on Jenkins jobs through configuration of MAVEN_OPTS.
- We can specify it like: “-Dname=value”
Environment Variables
- We need to define it through platform-specific way.
- But any programs can reference it through cross-platform way.
- I guess it's more cross-platform way than Java System Properties.
- We need a plugin[2] for Jenkins to define environment variables in jobs.
- I guess it's not bad to achieve it.
- But it's might not a good idea to storing security informations such as password.
Sample
- This sample executes simple SQL which acquires the name of connected database.
- Assume PostgreSQL is running at localhost:5432 and database named “kyle”, “testdb”, “testdb001” are exists.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.nailedtothex</groupId> <artifactId>mavenprops</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> <dependencies> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.3-1100-jdbc41</version> </dependency> </dependencies> </project>
~/.m2/settings.xml
- This defines variables of the development environment with Eclipse.
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <profiles> <profile> <id>development</id> <properties> <hogeApp.jdbc.url>jdbc:postgresql://localhost:5432/kyle</hogeApp.jdbc.url> <hogeApp.jdbc.user>kyle</hogeApp.jdbc.user> <hogeApp.jdbc.password>***</hogeApp.jdbc.password> </properties> </profile> </profiles> </settings>
Activate the profile on Eclipse explicitly
Right-click the project - Maven - Select Maven Profiles
Check “development” - OK
main/resources/jdbc.properties
url=${hogeApp.jdbc.url} user=${hogeApp.jdbc.user} password=${hogeApp.jdbc.password}
Main.java
package mavenprops; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; public class Main { public static void main(String[] args) throws Exception { Properties info = new Properties(); try (InputStream is = Main.class.getResourceAsStream("/jdbc.properties")) { info.load(is); } try (Connection cn = DriverManager.getConnection(info.getProperty("url"), info); Statement st = cn.createStatement(); ResultSet rs = st.executeQuery("select current_database()")) { rs.next(); System.out.println("current_database(): " + rs.getString(1)); } } }
Run
Run on Eclipse
current_database(): kyle
- The database specified in ~/.m2/settings.xml is shown.
Run from command-line
kyle-no-MacBook:mavenprops kyle$ mvn clean compile exec:java -Dexec.mainClass="mavenprops.Main" -DhogeApp.jdbc.url=jdbc:postgresql://localhost:5432/testdb -DhogeApp.jdbc.user=kyle -DhogeApp.jdbc.password=*** Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenprops 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenprops --- [INFO] Deleting /Users/kyle/Documents/workspace/mavenprops/target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenprops --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ mavenprops --- [INFO] Compiling 1 source file to /Users/kyle/Documents/workspace/mavenprops/target/classes [INFO] [INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops >>> [INFO] [INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops <<< [INFO] [INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops --- current_database(): testdb [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.333s [INFO] Finished at: Tue Mar 04 18:25:25 JST 2014 [INFO] Final Memory: 13M/245M [INFO] ------------------------------------------------------------------------ kyle-no-MacBook:mavenprops kyle$
- The database specified at the command-line arguments is shown.
kyle-no-MacBook:mavenprops kyle$ cat target/classes/jdbc.properties url=jdbc:postgresql://localhost:5432/testdb user=kyle password=***
- Filter worked as expectedly.
How to apply this method on Jenkins job
- We can specify the variables on the configure of the job like this:
Build log
<===[JENKINS REMOTING CAPACITY]===>channel started log4j:WARN No appenders could be found for logger (org.apache.commons.beanutils.converters.BooleanConverter). log4j:WARN Please initialize the log4j system properly. Executing Maven: -B -f /Users/Shared/Jenkins/Home/jobs/MavenProps/workspace/mavenprops/pom.xml clean compile exec:java [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenprops 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenprops --- [INFO] Deleting /Users/Shared/Jenkins/Home/jobs/MavenProps/workspace/mavenprops/target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenprops --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ mavenprops --- [INFO] Compiling 1 source file to /Users/Shared/Jenkins/Home/jobs/MavenProps/workspace/mavenprops/target/classes [INFO] [INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops >>> [WARNING] Failed to getClass for org.codehaus.mojo.exec.ExecJavaMojo [INFO] [INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops <<< [INFO] [INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ mavenprops --- current_database(): testdb001 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.472s [INFO] Finished at: Tue Mar 04 19:08:39 JST 2014 [INFO] Final Memory: 15M/245M [INFO] ------------------------------------------------------------------------ [JENKINS] Archiving /Users/Shared/Jenkins/Home/jobs/MavenProps/workspace/mavenprops/pom.xml to org.nailedtothex/mavenprops/0.0.1-SNAPSHOT/mavenprops-0.0.1-SNAPSHOT.pom channel stopped Finished: SUCCESS
- The database specified at configured in the job is shown.
jdbc.properties on the workspace of Jenkins
- Filter worked expectedly.
References
- フィルタリング
- EnvInject Plugin - Jenkins - Jenkins Wiki
- Setting the system-wide PATH environment variable in Mavericks - Ask Different
- HowTo: Set an Environment Variable in Mac OS X - /etc/launchd.conf - Dowd and Associates
- Maven Settings Example - Users | Community
- maven-war-pluginで環境ごとの設定ファイルを管理してみた - Challenge Java EE !
- I can't get maven to use properties defined in ~/.m2/settings.xml? - Stack Overflow
- Happy Wide Grove: Eclipse+maven+m2e+JavaFX2
Tags: maven