Choosing spring profile when building with maven - spring

I was trying to create a build for my production environment.In my spring web application, I have 4 .yml files
application.yml
application-development.yml
application-staging.yml
application-production.yml
In the application.yml file, I specified
spring:
profiles:
active: production
the command i am using maven to create a build is
mvn clean install tomcat7:deploy -B -Pproduction
In my target folder I can see all properties and my production settings in not come up.
What i am getting is my default application.yml properties. How to build correctly?

In your application.yml, add as follows:
spring:
profiles:
active: #active-profiles#
Then try :
mvn clean install tomcat7:deploy -B -P production
In pom.xml (The maven profile is passed during the mvn command - production profile which finds the property and replaces the ones in application.yaml by spring-boot-maven-plugin inbuilt in spring-boot-starter-parent)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
<relativePath />
</parent>
.
.//Dependencies go here
.
<profiles>
<profile>
<id>production</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<active-profiles>production</active-profiles>
</properties>
</profile>
</profiles>
More info here :
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
http://dolszewski.com/spring/spring-boot-properties-per-maven-profile/
Maven resource filtering not working - because of spring boot dependency

Related

Cannot set Spring profile through Maven profile

This is my application-mysql.yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/XXXX
username: XX
password: XX
driver-class-name: com.mysql.jdbc.Driver
This is my pom:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>spring.profiles.active</name>
<value>mysql</value>
</property>
</activation>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
Now I want to simple: mvn clean install.
Also tried mvn clean install -Pdev.
and get error when starting the Spring Boot application like it is not taking the application-mysql properties.
When I set in the application.properties
spring:
profiles:
active: dev
Then it works.
It looks like you're mixing up Maven properties with System properties. The <properties> inside the pom can only be used within the context of that pom. So they are not being exposed as System properties, hence not being picked up by Spring.
Not sure how/why you are starting the application during build, I assume for a test.
What I suggest to do is to read https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config which shows you how you can control the configuration under different conditions (without Maven).

Spring Boot Not Resolving Properties Variable When Using spring-boot:run

This was working for me and I'm not sure what changed.. I have my spring boot profile configured to be set based on a maven profile. The basics:
application.properties:
spring.profiles.active=#environment#
pom.xml:
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>development</environment>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
<profile>
<id>production</id>
<properties>
<environment>production</environment>
</properties>
</profile>
</profiles>
When I run mvn clean package -Pdevelopment I see the line The following profiles are active: development.
Yet when I run mvn spring-boot:run -Pdevelopment I see the line The following profiles are active: #environment#.
Using the spring-boot:run command seems to not be able to resolve application property variables based on maven environment variables. Anyone know why? I tried adjusting the spring starter version without success.
According to the docs, you could tune the profiles to enable when running the application as follows:
$ mvn spring-boot:run -Dspring-boot.run.profiles=development
If not, try to comment your "spring.profiles.active" property in application.properties, that should work!
See also this thread.
Based on this tip in the docs, I added a configuration to my spring-boot-maven-plugin which broke this functionality:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
Removing the addResources configuration restores the property expansion behavior.

activate spring boot profile from maven profile

I want to separate my junit test and integration test separate. So I created a separate profile in pom.xml for the integration test as follows:
<profiles>
<profile>
<id>integration-test</id>
<properties>
<test>IntegrationTestTrigger</test>
<spring.profiles.active>integration-test</spring.profiles.active>
</properties>
</profile>
<profiles>
The when I run the maven command mvn test -Pintegration-test, it is picking the test class as defined in the <properties> tag shown above as IntegrationTestTrigger. But it is not setting the spring.profiles.active property. So the test is starting with default profile. It is working fine with the maven command mvn test -Dtest=IntegrationTestTrigger -Dspring.profiles.active=integration-test
But as per my organisations jenkins setting, I need to run mvn test -Pintegration-test for the integration test, so I cannot add any extra environment variables to mvn command
Indeed as #gtivari333 said, profile/properties section is only to be used for substitution in POM files (and other files processed by maven, if so desired).
To set JVM properties aka "system properties" in POM directly, for use during test execution, you need to set them using surefire plugin configuration like this:
<profiles>
<profile>
<id>integration-test</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
<systemProperties>
<foo>bar</foo>
<spring.profiles.active>integration-test</spring.profiles.active>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
The properties at the is meant for property substitution at the .properties/.yml file inside resources folder.
Example:
application.yml:
spring:
profiles:
active: '#spring.profiles.active#'
pom.xml:
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
Here, the #spring.profiles.active# will be replaced with dev during compile(by maven-resources-plugin plugin). Spring Boot uses # as the resource delimiter at the spring-boot-starter-parent pom. You can change it to any character by changing the following property
//pom.xml
<project .....>
<properties>
<resource.delimiter>#</resource.delimiter>
...
</properties>
See https://github.com/gtiwari333/spring-boot-blog-app/blob/master/pom.xml#L436 for an complete example
See also: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-automatic-expansion-maven

How to refer a profile in maven spring boot project

I am novice when it comes to maven and spring boot. I need to run a spring boot project based on the profile. By default, the scope of following dependency is test which throws error at run time if I want to use h2. As I am not allowed to change the scope, I thought of adding two profiles in pom.xml - one default to be active by default and one for the h2 dependency without scope as test.
Following is what I added to pom.xml -
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>automation</id>
<properties>
<env>automation</env>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
Now, I tried to run my project using following command -
mvn -D "spring-boot.run.profiles=automation" -DskipTests=true spring-boot:run
But I still see the same h2 dependency scope error that I was seeing earlier.
Caused by: java.lang.IllegalStateException: Cannot load driver class: org.h2.Driver
i.e. I am unable to change the scope of dependency this way. What am I missing here?
You are defining a Maven profile, but activating a Spring profile. Use the following syntax:
mvn groupId:artifactId:goal -P profile-1,profile-2
https://maven.apache.org/guides/introduction/introduction-to-profiles.html
Update
I tested the configuration you posted, and spring-boot:run fails for me if only default profile is active with the follwoing exception:
java.lang.IllegalStateException: Cannot load driver class: org.h2.Driver
You can check your dependencies with
mvn dependency:tree
The output of above command varies according to maven profiles passed in.

Spring Boot's spring-boot:run doesn't honor specified profile

I am upgrading my old spring boot 1.5.x to latest 2.0.4, and I found mvn spring-boot:run doesn't honor the profile specified in command line:
I have an application.properties which stores common properties, and application-dev.properties and application-prod.properties specifying their db connections and tomcat ports.
It means, I have two profiles: dev and prod. I lookup the document, I have to specify profiles in pom.xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>dev</profile>
<profile>prod</profile>
</profiles>
</configuration>
</plugin>
And I want to execute the dev profile, I run:
mvn spring-boot:run -Dspring-boot.run.profiles=dev
And I see console outputs
boot.SpringApplication - The following profiles are active: dev
It seems Ok, but then I found it connects to wrong database and open different port, which is specified in prod profile.
It seems all values specified in prod override the dev ones.
And if I comment the values in prod, the dev ones are pickup (so, there is no typo in dev profile).
I tried the following combos:
mvn spring-boot:run -Dspring-boot.run.profiles=dev
mvn spring-boot:run -Dspring-boot.run.profiles="dev"
mvn spring-boot:run -Pdev -Dspring-boot.run.profiles=dev
mvn spring-boot:run -Pdev -Dspring-boot.run.profiles="dev"
All show The following profiles are active: dev but connect to prod DB and open wrong tomcat port.
I then tried:
mvn spring-boot:run -Pdev -Dspring.profiles.active=dev
mvn spring-boot:run -Pdev -Dspring.profiles.active="dev"
mvn spring-boot:run -Dspring.profiles.active="dev"
mvn spring-boot:run -Dspring.profiles.active=dev
mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=dev"
All the 5 above show The following profiles are active: dev,prod (which is incorrect, I just want dev) and still connect to prod DB
What may go wrong here?
This was easy in spring boot 1.5.x but became a WTF in 2.0.x . I feel frustrated here.
env:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
</parent>
------- updated -------
As #Jayesh said , maybe there's something wrong hidden, which leads default to prod. I renamed my application-prod.properties to application-prod2.properties. I am sure there's no prod2 string in the whole project code.
after mvn clean compile install,
Rerun with
mvn spring-boot:run -Dspring-boot.run.profiles=dev
Same result (The following profiles are active: dev but still opens to wrong DB specified in prod2)
And...
mvn spring-boot:run -Dspring.profiles.active=dev
Same result: The following profiles are active: dev,prod, connects to wrong DB, opens wrong port specified in prod2
It seems spring boot picks whatever application-*.properties and load the last one
I even set log level to TRACE
logging.level.org.springframework=TRACE
But still found no prod2 string in the output log...
Solved
The problem is solved.
There is another spring's XML containing this line:
<context:property-placeholder location="classpath*:*.properties"/>
It is the culprit. After commenting out this line, everything works fine.
P.S.: This is an evolving app, from pure spring app, with spring's XML setting, and the above line. Then wrapped in MVC, and then spring-boot . Everything works fine in 1.5.x, but in 2.x, boot truly loaded all .properties files and override all value one by one.
Please update your pom.xml without the profiles section. As per boot maven plugin doc, you should only provide active profile in the section.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<!--<profile>dev</profile>
<profile>prod</profile> you are setting active profile via command line args-->
</profiles>
</configuration>
</plugin>
Since, you are passing via command line args you dont need to give it there.. You may look at these beautiful tutorials.
https://www.mkyong.com/spring-boot/spring-boot-profiles-example/
https://www.baeldung.com/spring-profiles
Please let me know if it works.
I tried with the latest Spring Boot(v2.0.4.RELEASE) and the profile are getting loaded as expected.
pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<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.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>dev</profile>
<profile>prod</profile>
</profiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
TestController.java:
package com.example.demo.TestController;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by Raj Rathore on 27-Aug-18
*/
#RestController
#RequestMapping("/test")
public class TestController {
#Value("${profile}")
String profile;
#GetMapping("/profile")
public String getProfile() {
return profile;
}
}
application-dev.poperties:
profile=dev profile
application-pord.poperties:
profile=prod profile
Then by using the mvn spring-boot:run -Dspring-boot.run.profiles=dev the dev profile is loaded :
com.example.demo.DemoApplication : The following profiles are active: dev
Output : (http://localhost:8080/test/profile)
dev profile
OK , The problem is solved.
There is another spring's XML containing this line :
<context:property-placeholder location="classpath*:*.properties"/>
It is the culprit. After commenting out this line , everything works fine.
P.S. : This is an evolving app , from pure spring app , with spring's XML setting , and the above line. Then wrapped in MVC , and then spring-boot . Everything works fine in 1.5.x , but in 2.x , boot truly loaded all .properties files and override all value one by one.
Maybe there are some subtle changes on parsing .properties from spring boot 1.5.x to 2.x.

Resources