Configuring the Spring Boot profile from Maven

In ${personalProject} I need to be able to change among Spring Boot Profiles at build time. This is because I do want to mess up with Tomcat at all, I just simply want to have a Tomcat setup as close as its original setup as possible.

I could use JAVA_OPTS environment variable, for example. But that forces me to change the startup.sh script or any other mechanism so that Tomcat finds the right profile to use.

Another option would be to run the multiple webapps (my app consists of multiple war components) passing the -Dspring.boot.profile, again that forces me to change things in the Tomcat setup.

However, another option is to change the main application.yml (or application.properties) at build time. That way the CI/CD Jenkins can choose the profile when building. But I want that to happen without using more tools than the ones I’m using right now. Also, I want to be sure the pipeline works regardless the OS used in the CI/CD, in production or locally (I have a mixture of OSs here, production is still Linux, CI/CD is FreeBSD and local is MacOS).

To do so, I decided to use maven profiles to do that. That way it’d be just a matter of telling Maven which profile to use. The problem here is that maven profiles and Spring Boot profiles are different things.

Now we need is to tell Maven what profiles we have. In the pom.xml we need to define the profiles we have. For each profile, the variable springProfile will have a different value. In the main block we need to add something like this:

<profiles>
	<profile>
		<id>local</id>
		<properties>
			<springProfile>local</springProfile>
		</properties>
		<activation>
			<activeByDefault>true</activeByDefault>
		</activation>
	</profile>
	<profile>
		<id>dev</id>
		<properties>
			<springProfile>dev</springProfile>
		</properties>
	</profile>
	<profile>
		<id>production</id>
		<properties>
			<springProfile>production</springProfile>
		</properties>
	</profile>
</profiles>

Pay attention to two things:

  • The springProfile tag will be used later. You can choose any name you want here, but later you need to use the same.
  • The activeByDefault profile is the one that will be used by Maven as the default profile if none is passed to Maven with the -Pprofile flag. Don’t use production because you may end up messing with your production environment, depending on what you are trying to do.

Next, we need to define a placeholder in the application.yml that will be replaced as the variable springProfile selected by the the active maven profile. In that file, put something like this:

spring.profiles.active: @springProfile@ # local dev production

Note that the placeholder variable is the one used in the pom file before. They have to match.

Right now you have a placeholder, the only thing missing is to tell Maven to replace the placeholder with the choosen profile with mvn -Pblah.

Now, under the build tag in the pom file, you need to add this:

<plugins>
	...
	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-resources-plugin</artifactId>
		<version>2.7</version>
		<configuration>
			<delimiters>
				<delimiter>@</delimiter>
			</delimiters>
			<useDefaultDelimiters>false</useDefaultDelimiters>
		</configuration>
	</plugin>
	...
</plugins>

This one is needed to tell Maven the delimiter being used in the placeholder variable.

Finally, you need to use the resource maven plugin to replace the appearances of @springProfile@ under certain directories. You need to add this:

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

That applies filtering to files under the src/main/resources directory. So, to recap, depending on the Maven profile passed, Maven will expose the springProfile variable with different values, that will be picked by the resource plugin that would replace the placeholder using the delimiter configured in the <plugin> block. So at the end, in the application.dev we’d have this:

spring.profiles.active: dev # local dev production

References:

  • https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html