catch32
catch32

Reputation: 18582

Pass environment variables to Spring Boot application with Maven

I am using Spring Boot 3.2.1.

I don't want to put sensitive data at config file as application.yml. So they are referring to environment variables.

Execution works fine at IntelliJ configuration settings for application (at Environment variables section).

However, it fails for maven execution from the console:

./mvnw -Ddemo-api-key=all56 -Ddemo-host=https://demo.api spring-boot:run

Here is exception details:

java.lang.IllegalArgumentException: Not enough variable values available to expand 'demo-host'
        at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:367) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
        at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:262) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
        at org.springframework.web.util.HierarchicalUriComponents$PathSegmentComponent.expand(HierarchicalUriComponents.java:960) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
        at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:434) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
        at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:52) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
        at org.springframework.web.util.UriComponents.expand(UriComponents.java:172) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]

Here is a snippet from application.yml:

car-parks-url: ${demo-host}/cap-ws/getCarParks?apiKey=${demo-api-key}

If I will put it higher at application.yml it works fine:

demo-api-key: all56
demo-host: https://demo.api

URL is formed correctly and all data are pulled fine.

Could not understand what is missed for passing it as the environment variables with maven?

Upvotes: 9

Views: 21906

Answers (2)

Conor Heffron
Conor Heffron

Reputation: 1

I agree with @Marco around the java/maven options posted & I often use the following to build & test spring boot apps via maven:

mvn clean package

mvn -DENV_VAR_1=<val1> \
  -DENV_VAR_2=<val2> \
  -DENV_VAR_3=<val3> \
  spring-boot:run

However, I recommend using a docker file for spring boot applications using 'Dockerfile' (base image with entry point and run 'java -jar /app.war' command), 'docker-compose.yml' (with environment section that maps env vars after assigning ports), & '.env' file that holds environment variables/values only for local runs.

docker-compose.yml

services:
  service_name:
    image: app_name
    ports:
      - "8080:8080"
    environment:
      ENV_VAR_1: ${ENV_VAR_1}
      ENV_VAR_2: ${ENV_VAR_2}
      ENV_VAR_3: ${ENV_VAR_3}

.env file contents:

ENV_VAR_1=<val1>
ENV_VAR_2=<val2>
ENV_VAR_3=<val3>

Run steps via local docker desktop environment.

docker image build -t <app_name> .
docker compose up -d
docker logs <container> -f

Upvotes: 0

Marco
Marco

Reputation: 587

It's not the same as:

java -jar -Ddemo-api-key=all56 -Ddemo-host=https://demo.api myApp.jar

Where you are passing env vars directly to your application.

If you do:

./mvnw -Ddemo-api-key=all56 \
-Ddemo-host=https://demo.api spring-boot:run

You are passing the vars to maven task and not to the application.

You could use:

 ./mvnw  spring-boot:run \
 -Dspring-boot.run.arguments="--demo-host=https://demo.api --demo-api-key=all56"

or

 ./mvnw  spring-boot:run -Dspring-boot.run.jvmArguments="\
 -Ddemo-host=https://demo.api -Ddemo-api-key=all56"

Those commands indicate that you what to pass those vars to Spring Boot application.

Additional resource:

Upvotes: 19

Related Questions