How to set build properties from a file in Maven POM?

后端 未结 2 1525
无人共我
无人共我 2021-02-09 01:15

I need to read and filter a properties file from a location outside my project, say ${user.home}/my.properties. This properties file looks like this:

res.dir         


        
相关标签:
2条回答
  • 2021-02-09 02:07

    You could simply implement your own maven-plugin that will take care of this for you.

    Here is an example with the following structure:

    .
     |-- pom.xml
     |-- plugin
     |   `-- pom.xml
     |   `-- src
     |       `-- main
     |           `-- java
     `-- app
         `-- pom.xml
         `-- src
             `-- main
                 `-- java
    

    You will need to create a Mojo that takes the properties file as an input and then propagates the properties to the pom.xml of the app. The pom.xml will actually not be updated but just the project data in it.

    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>com.stackoverflow</groupId>
        <artifactId>Q12082277</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>pom</packaging>
    
        <name>${project.artifactId}-${project.version}</name>
    
        <modules>
            <module>plugin</module>
            <module>app</module>
        </modules>
    
    </project>
    

    plugin/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>
    
        <parent>
            <groupId>com.stackoverflow</groupId>
            <artifactId>Q12082277</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>Q12082277-plugin</artifactId>
        <packaging>maven-plugin</packaging>
    
        <name>${project.artifactId}-${project.version}</name>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-plugin-api</artifactId>
                <version>3.0.4</version>
            </dependency>
            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-project</artifactId>
                <version>2.2.1</version>
            </dependency>
        </dependencies>
    </project>
    

    plugin/src/main/java/com/stackoverflow/Q12082277/plugin/PropertiesMojo.java

    package com.stackoverflow.Q12082277.plugin;
    
    import org.apache.maven.plugin.AbstractMojo;
    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugin.MojoFailureException;
    import org.apache.maven.plugin.logging.Log;
    import org.apache.maven.project.MavenProject;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.Properties;
    
    /**
     * @author maba, 2012-08-24
     *
     * @goal extract
     */
    public class PropertiesMojo extends AbstractMojo {
    
        private Log log;
    
        /**
         * The current project representation.
         * @parameter expression="${project}"
         * @required
         * @readonly
         */
        private MavenProject project;
    
        /**
         * A properties file
         *
         * @parameter expression="${propertiesFile}"
         * @required
         */
        private File propertiesFile;
    
        @Override
        public void execute() throws MojoExecutionException, MojoFailureException {
            log.info("Executing PropertiesMojo on " + propertiesFile.getAbsolutePath());
    
            try {
                Properties fileProperties = new Properties();
                fileProperties.load(new FileInputStream(propertiesFile));
                Properties projectProperties = project.getProperties();
                for (Object key : fileProperties.keySet()) {
                    projectProperties.setProperty((String)key, (String) fileProperties.get(key));
                }
                project.getProperties().list(System.out);
            } catch (FileNotFoundException e) {
                throw new MojoFailureException("The file " + propertiesFile.getAbsolutePath() + " was not found!", e);
            } catch (IOException e) {
                log.error("");
            }
    
        }
    
        @Override
        public void setLog(Log log) {
            this.log = log;
        }
    }
    

    You will use this plugin from the following app/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>
    
        <parent>
            <groupId>com.stackoverflow</groupId>
            <artifactId>Q12082277</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>Q12082277-app</artifactId>
    
        <name>${project.artifactId}-${project.version}</name>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>com.stackoverflow</groupId>
                    <artifactId>Q12082277-plugin</artifactId>
                    <version>1.0-SNAPSHOT</version>
                    <executions>
                        <execution>
                            <phase>initialize</phase>
                            <goals>
                                <goal>extract</goal>
                            </goals>
                            <configuration>
                                <propertiesFile>${user.home}/my.properties</propertiesFile>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.2.1</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <mainClass>com.stackoverflow.Q12082277.App</mainClass>
                    </configuration>
                </plugin>
            </plugins>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </project>
    

    And then you will have to add the following app.properties that will work as a template and take the values that we have just read from file and set them and create a concrete file app.properties that will be reachable from within the jar.

    app/src/main/resources/app.properties

    res.dir=${res.dir}
    resource.dir=${resource.dir}
    bin.dir=${bin.dir}
    cfg.dir=${cfg.dir}
    

    And finally here is a test application that just loads the app.properties from the classpath and prints the result.

    app/src/main/java/com/stackoverflow/Q12082277/App.java

    package com.stackoverflow.Q12082277;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    /**
     * @author maba, 2012-08-23
     */
    public class App {
    
        public static void main(String[] args) throws IOException {
            ClassLoader loader = App.class.getClassLoader();
            InputStream in = loader.getResourceAsStream("app.properties");
            Properties properties = new Properties();
            properties.load(in);
            properties.list(System.out);
        }
    }
    

    Now you can stand in the top directory and execute

    mvn install
    

    Then go down into the app folder and execute

    mvn exec:java
    

    And it will print

    -- listing properties --
    resource.dir=C://my/stuff/here
    cfg.dir=C://my/stuff/here/config
    bin.dir=C://my/stuff/here/bin
    res.dir=/my/stuff/here
    

    Which is exactly what you wanted.

    0 讨论(0)
  • 2021-02-09 02:10

    I think it would be better if you turned the properties file into a template file and take the properties from the pom.xml using maven resource filtering.

    A simple setup might look like this

    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>com.stackoverflow</groupId>
        <artifactId>Q12082277</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <name>${project.artifactId}-${project.version}</name>
    
        <properties>
            <res.dir>/default/stuff/here</res.dir>
            <resource.dir>${res.dir}</resource.dir>
            <bin.dir>${resource.dir}/bin</bin.dir>
            <cfg.dir>${resource.dir}/config</cfg.dir>
        </properties>
    
        <dependencies>
        <!-- Your dependencies -->
        </dependencies>
    
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    
    </project>
    

    src/main/resources/app.properties

    res.dir=${res.dir}
    resource.dir=${resource.dir}
    bin.dir=${bin.dir}
    cfg.dir=${cfg.dir}
    

    src/main/java/com/stackoverflow/Q12082277/App.java

    package com.stackoverflow.Q12082277;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    /**
     * @author maba, 2012-08-23
     */
    public class App {
    
        public static void main(String[] args) throws IOException {
            ClassLoader loader = App.class.getClassLoader();
            InputStream in = loader.getResourceAsStream("app.properties");
            Properties properties = new Properties();
            properties.load(in);
            properties.list(System.out);
        }
    }
    

    System.out

    -- listing properties --
    resource.dir=/default/stuff/here
    cfg.dir=/default/stuff/here/config
    bin.dir=/default/stuff/here/bin
    res.dir=/default/stuff/here
    

    The pom.xml will have the default properties that are used by everybody.

    If you want to override the values then call maven with input parameters:

    mvn install -Dres.dir=/my/stuff/here -Dresource.dir="C:/${res.dir}"
    

    System.out

    -- listing properties --
    resource.dir=C://my/stuff/here
    cfg.dir=C://my/stuff/here/config
    bin.dir=C://my/stuff/here/bin
    res.dir=/my/stuff/here
    

    By doing it this way everybody will have the same view of the properties and you can override them if you want to when running on your own machine.

    0 讨论(0)
提交回复
热议问题