spring boot profiles not working correctly

687 views Asked by At

Hello I have a maven spring boot rest project. I want to add dev and prod configurations to it but it is not working.

Under /src/main/resources i created application.yaml, application-dev.yaml and application-prod.yaml

# application.yaml
spring:
  profiles:
    active: prod
# application-dev.yaml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:h2:mem:mydb
    username: sa
    password: password
    driverClassName: org.h2.Driver
# application-prod.yaml
server:
  port: 8099
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/WsDb
    username: postgres
    password: postgres
    driverClassName: org.postgresql.Driver

in pom.xml i have the following:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
...
</dependencies>
<build>
    <resources>
      <resource>
        <directory>/src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <spring.profiles.active>dev</spring.profiles.active>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>prod</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <version>${postgres.version}</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

when i run the application in Intellij Idea with debug configuration with the command mvn clean package spring-boot:run -Dspring.profiles.active = prod it says :

Test Phase output

The following 1 profile is active: "prod"   
Bootstrapping Spring Data JPA repositories in DEFAULT mode.  
Finished Spring Data repository scanning in 164 ms. Found 2 JPA repository interfaces.  
Replacing 'dataSource' DataSource bean with embedded version   
Starting embedded database: url='jdbc:h2:mem:4348112a-775e-4b78-a5b7-e5bcfdf21761  
HHH000204: Processing PersistenceUnitInfo [name: default]  

Run phase output

No active profile set, falling back to 1 default profile: "default"
Bootstrapping Spring Data JPA repositories in DEFAULT mode.
Finished Spring Data repository scanning in 116 ms. Found 2 JPA repository interfaces.
Tomcat initialized with port 8080 (http) 
Starting service [Tomcat]   
2

There are 2 answers

5
Easterwood On

As far as I can see the command line argument -Dspring.profiles.active=prod has no affect. The spring-boot plugin documentation describes how to activate the profiles.

mvn spring-boot:run -Dspring-boot.run.profiles=dev,local

In your project the prod profile is activated only because of the property spring.profiles.active in the application.yaml file. That has lured me onto the wrong ferry.

In the spring documentation there is also an example how to activate the spring profiles with maven profiles.

<project>
    <properties>
        <app.profiles>local,dev</app.profiles>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <profiles>${app.profiles}</profiles>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
4
velocity On

Problem solved! Below is a summary.

There were 2 problems:
The first Problem was that the application.yml, application-dev.yml and application-prod.yml were not getting copied into target and therefore had no effect. This was due to a build configuration i added:

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

This caused maven to no being able to find the resource files and therefore throw an Info message: INFO] skip non existing resourceDirectory C:\src\main\resources
To solve this problem i had to append with ${project.basedir} to the path

<directory>${project.basedir}/src/main/resources</directory>

After all this solution turned out not to be required, see @Easterwood's comments, removing the first / at the beginning of /src/main/resources solves the problem

<directory>src/main/resources</directory>

After this change maven could find the resource files and print [INFO] Copying 3 resources from src\main\resources to target\classes

The second problem was that Tests were run with the profile that was set through the command line with the parameter -Dspring.profiles.active=prod enter image description here

while the jar was run with default profile (the one that is set in application.yml through

spring:
   profiles: 
      active: dev

or the 'default' profile if none was specified in application.yml or the command line.

To solve this problem i had to set an environment variable in the debug configuration.

enter image description here

This is the same as

enter image description here

Update 20.12.2023

i renamed the maven variable spring.profiles.active to activeProfiles

<properties>
   <activeProfiles>dev</activeProfiles>
</properties>

and the corresponding profile properties setting

<profile>
   <id>dev</id>
   <properties>
      <activeProfiles>dev</activeProfiles>
    </properties>
<profile>

<profile>
    <id>prod</id>
    <properties>
        <activeProfiles>prod</activeProfiles>
    </properties>

now to select the profile i use -P parameter in the debug configuration

mvn clean spring-boot:run -Pdev

or

mvn clean spring-boot:run -Pprod

That sets the value of the maven variable activeProfiles accoding to the active profile (dev or prod), which gets replaced in the application.yml

spring:
  profiles:
    active: @activeProfiles@

also i had to add the h2 database dependency in pom.xml because spring boot is complaining that no driver was found during test phase.

<project>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
         </dependency>