Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Maven and various application.properties for artifact generation of different testing regions in a Spring configured app

I want to use Maven to handle artifact generation for the different local and testing regions. I believe I can use different profiles but I am not certain.

In Maven can I select different directories to select files used on packaging (such as application.properties)? How would I set that up?

An idea of what I want is to have a the following folders for resources in my project

  • local
  • build server
  • dev
  • sys
  • prod

Each folder should contain a different version of application.resources which is a file in Spring that can be used to handle hard-coded strings for use in variables. For local builds- our developers also work on different operating systems. Should I require I want to make it seamless on different OS' also.

Key outcomes would be:

  • Control Maven lifecycle phases from inside the IDE (IntelliJ)
  • Not complicate phases and team processes
  • Keep things as consistent for each developer
  • Make the different configurations per developer/region appear invisible when running a phase e.g. install

Ideally I would have my project set up according to best practices (Duvall, Matyas, Glover).

like image 954
Crowie Avatar asked Apr 29 '13 13:04

Crowie


People also ask

Where is application properties file in Maven project?

You will need to add the application. properties file in your classpath. If you are using Maven or Gradle, you can just put the file under src/main/resources . If you are not using Maven or any other build tools, put that under your src folder and you should be fine.

What is application properties in Spring boot?

Properties File Properties files are used to keep 'N' number of properties in a single file to run the application in a different environment. In Spring Boot, properties are kept in the application. properties file under the classpath. The application.properties file is located in the src/main/resources directory.

How do you change application properties at runtime Spring boot?

To change properties in a file during runtime, we should place that file somewhere outside the jar. Then we tell Spring where it is with the command-line parameter –spring. config. location=file://{path to file}.


2 Answers

We provide different properties currently but not by way of different folders. We do this via a mix of

  • Spring's PropertyPlaceholderConfigurer
  • Maven profiles (something we use to build our Dev environment),
  • Build Server (TeamCity in our case)
  • Maven phases to produce the correct artifact
  • start-up and build arguments

My understanding of what we do is limited, but hopefully this serves as a useful example for others and maybe myself to consider.

We provide parameters, as you'll see below, to point to different property files. Each property file has configuration for a region/environment. I'll explain the current use as best I can in-case it provides some use to others.

To use Maven profiles we have created a profile in our pom identified as development which includes a region configuration property called env. I don't yet know entirely how that is being used yet in our project however you'll see below our POM includes the a Maven Compiler plugin and a Maven Tomcat plugin.

Day to day, as developers we run our our applications locally on Tomcat from within IntelliJ and provide the env property. On start-up the env property is provided as an argument to set to classpath*:dev-common.properties. This file is a properties configuration file - setting placeholder values for our different regions.

The value of env is made available to our PropertyPlaceholderConfigurer


Example 1 - Implementation of Maven profile in pom.xml:

The implementation of a profile in our pom is:

<profile>
        <id>development</id>
        <activation>
            <property>
                <name>env</name>
                <value>development</value>
            </property>
        </activation>
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>2.3.2</version>
                        <configuration>
                            <source>1.6</source>
                            <target>1.6</target>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.tomcat.maven</groupId>
                        <artifactId>tomcat7-maven-plugin</artifactId>
                        <version>2.0-SNAPSHOT</version>
            ...
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    </profile>

Example 2 - Property placeholder configurer for normal build:

We also make use ofa Spring component, a PropertyPlaceholderConfigurer. We use this in collaboration with a build argument to set up a classpath pointer to resource files.

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>
                ${env}
            </value>
        </list>
    </property>


Example 3 - Property placeholder configurer for test:

We have Spring Contexts specifically set up for integration testing which also use the PropertyPlaceholderConfigurer. These are picked up by a integration testing class using a combination of @ContextConfiguration(locations = {"classpath:test-dataexchange-application-context.xml"}) and @RunWith(SpringJUnit4ClassRunner.class)).

In the testing context we configure the PropertyPlaceholderConfigurer as follows to pick up the properties of an integration testing region:

<bean id="testpropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath*:dev-local-common.properties</value>
        </list>
    </property>


Other notes:

We make use of Team City for build management but I have not seen how these settings are used there, if they are at all. I can conceive there's an ability to combine the above approaches together to aid Continuous Integration and Delivery.

I do not see where the profile identified as development is being used. It is something I must follow up with my fellow team members.


Resources:

  • Building for different environments at the Maven Project site.
  • Maven 3 does not allow configuration of a profile outside of a pom or settings.xml (the Maven configuration file) and says that users who used these external settings should now put them inside of settings.xml
like image 89
Crowie Avatar answered Oct 07 '22 00:10

Crowie


If you are using Spring boot, there is an easy way of doing this.

Create two profiles in maven, and set a property in each profile with the name of the Spring profile you want to execute.

    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <!-- Default spring profile to use -->
            <spring.profiles.active>dev</spring.profiles.active>
            <!-- Default environment -->
            <environment>develop</environment>
        </properties>
    </profile>

Inside your application.properties, add this property: spring.profiles.active=${spring.profiles.active}

Create an application.property for each profile, using this pattern application-profile.properties. For example: application-dev.properties application-prod.properties

Be sure to active filtering in the resource plugin:

  ...
  <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
  </resource>
 ...

Another way is to create a file during the execution of maven called activeprofile.properties. Spring boot looks this file to load the active profile. You can create this file as follows:

   <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <configuration>
                        <target>
                            <echo message="spring.profiles.active=${spring.profiles.active}" file="target/classes/config/activeprofile.properties" />
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
            </configuration>
        </plugin>
like image 33
jfcorugedo Avatar answered Oct 07 '22 00:10

jfcorugedo