From 40b7e02793184c377391d501dd5c843a31e1d1e4 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 24 Apr 2018 15:44:59 +0200 Subject: [PATCH] Polish "Add support for environment variables" Closes gh-12800 --- .../src/main/asciidoc/howto.adoc | 8 --- .../boot/loader/tools/RunProcess.java | 8 +-- .../main/java/org/test/SampleApplication.java | 8 ++- .../boot/maven/AbstractRunMojo.java | 26 ++++------ .../boot/maven/EnvVariables.java | 50 +++++++------------ .../springframework/boot/maven/RunMojo.java | 5 +- .../springframework/boot/maven/StartMojo.java | 9 ++-- .../apt/examples/run-env-variables.apt.vm | 50 +++++++++++++++++++ .../src/site/apt/examples/run-with-env.apt.vm | 43 ---------------- .../src/site/apt/index.apt | 4 +- .../src/site/apt/usage.apt.vm | 11 ++-- .../src/site/site.xml | 2 +- .../boot/maven/EnvVariablesTests.java | 22 +++----- 13 files changed, 105 insertions(+), 141 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-env-variables.apt.vm delete mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-with-env.apt.vm diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc index 75cbcda8a4..7e43d55146 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -2771,14 +2771,6 @@ See {spring-boot-maven-plugin-site}/examples/run-debug.html[this example] for mo details. -[[howto-set-env-maven-run]] -=== Run Spring Boot Application with Environment variables Started with Maven -To set up the environment variables to a Spring Boot application that was started with Maven, you -can use the `environmentVariables` property of the {spring-boot-maven-plugin-site}[maven plugin]. - -See {spring-boot-maven-plugin-site}/examples/run-with-env.html[this example] for more -details. - [[howto-build-an-executable-archive-with-ant]] === Build an Executable Archive from Ant without Using `spring-boot-antlib` diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java index e8b460cc7b..36f4ba5dfd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java @@ -69,12 +69,8 @@ public class RunProcess { return run(waitForProcess, Arrays.asList(args), Collections.emptyMap()); } - public int run(boolean waitForProcess, String[] args, Map environmentVariables) throws IOException { - return run(waitForProcess, Arrays.asList(args), environmentVariables); - } - - protected int run(boolean waitForProcess, Collection args, Map environmentVariables) - throws IOException { + public int run(boolean waitForProcess, Collection args, + Map environmentVariables) throws IOException { ProcessBuilder builder = new ProcessBuilder(this.command); builder.directory(this.workingDirectory); builder.command().addAll(args); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/it/run-envargs/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/it/run-envargs/src/main/java/org/test/SampleApplication.java index 044ec36035..c60eabec39 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/it/run-envargs/src/main/java/org/test/SampleApplication.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/it/run-envargs/src/main/java/org/test/SampleApplication.java @@ -18,7 +18,6 @@ package org.test; public class SampleApplication { - public static void main(String[] args) { assertEnvValue("ENV1", "5000"); assertEnvValue("ENV2", "Some Text"); @@ -26,14 +25,13 @@ public class SampleApplication { assertEnvValue("ENV4", ""); System.out.println("I haz been run"); - } - - static void assertEnvValue(String envKey, String expectedValue) { + private static void assertEnvValue(String envKey, String expectedValue) { String actual = System.getenv(envKey); if (!expectedValue.equals(actual)) { - throw new IllegalStateException("env property [" + envKey + "] mismatch (got [" + actual + "], expected [" + expectedValue + "]"); + throw new IllegalStateException("env property [" + envKey + "] mismatch " + + "(got [" + actual + "], expected [" + expectedValue + "]"); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java index 6c2e76ea13..74767347c5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java @@ -24,7 +24,6 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -118,12 +117,12 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { private Map systemPropertyVariables; /** - * List of Environment variables that should be associated with the forked process used to run the - * application. - *

NOTE: the use of Environment variables means that processes will be started by forking a - * new JVM. + * List of Environment variables that should be associated with the forked process + * used to run the application. NOTE: the use of Environment variables means that + * processes will be started by forking a new JVM. + * @since 2.1 */ - @Parameter(property = "spring-boot.run.environmentVariables") + @Parameter private Map environmentVariables; /** @@ -231,7 +230,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { return (this.environmentVariables != null && !this.environmentVariables.isEmpty()); } - private boolean hasWorkingDirectorySet() { return this.workingDirectory != null; } @@ -273,22 +271,19 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { private void doRunWithForkedJvm(String startClassName) throws MojoExecutionException, MojoFailureException { List args = new ArrayList<>(); - Map envVariables = new LinkedHashMap<>(); addAgents(args); addJvmArgs(args); addClasspath(args); args.add(startClassName); addArgs(args); - addEnvironmentVariables(envVariables); - runWithForkedJvm(this.workingDirectory, args, envVariables); + runWithForkedJvm(this.workingDirectory, args, determineEnvironmentVariables()); } - /** * Run with a forked VM, using the specified command line arguments. * @param workingDirectory the working directory of the forked JVM * @param args the arguments (JVM arguments and application arguments) - * @param environmentVariables the environment variables; + * @param environmentVariables the environment variables * @throws MojoExecutionException in case of MOJO execution errors * @throws MojoFailureException in case of MOJO failures */ @@ -316,27 +311,24 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { return runArguments; } - /** * Resolve the environment variables to use. - * * @return a {@link EnvVariables} defining the environment variables */ protected EnvVariables resolveEnvVariables() { return new EnvVariables(this.environmentVariables); } - private void addArgs(List args) { RunArguments applicationArguments = resolveApplicationArguments(); Collections.addAll(args, applicationArguments.asArray()); logArguments("Application argument(s): ", this.arguments); } - private void addEnvironmentVariables(Map environmentVariables) { + private Map determineEnvironmentVariables() { EnvVariables envVariables = resolveEnvVariables(); - environmentVariables.putAll(envVariables.asMap()); logArguments("Environment variable(s): ", envVariables.asArray()); + return envVariables.asMap(); } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java index 0ee67f00e9..a38d4876e1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java @@ -29,53 +29,39 @@ import java.util.Map; */ class EnvVariables { - private static final String SPACE = "="; - private static final String NO_VALUE = ""; + private final Map variables; - private final Map args = new LinkedHashMap<>(); - - EnvVariables(Map args) { - this.args.putAll(getArgs(args)); + EnvVariables(Map variables) { + this.variables = parseEnvVariables(variables); } - Map asMap() { - return Collections.unmodifiableMap(this.args); - } - - String[] asArray() { - List args = new ArrayList<>(this.args.size()); - for (Map.Entry arg : this.args.entrySet()) { - args.add(arg.getKey() + SPACE + arg.getValue()); - } - return args.toArray(new String[args.size()]); - } - - - private Map getArgs(Map args) { - + private static Map parseEnvVariables(Map args) { if (args == null || args.isEmpty()) { return Collections.emptyMap(); } - Map result = new LinkedHashMap<>(); for (Map.Entry e : args.entrySet()) { - if (hasText(e.getKey())) { + if (e.getKey() != null) { result.put(e.getKey(), getValue(e.getValue())); } } return result; } - private String getValue(String value) { - if (hasText(value)) { - return value; + private static String getValue(String value) { + return (value != null ? value : ""); + } + + public Map asMap() { + return Collections.unmodifiableMap(this.variables); + } + + public String[] asArray() { + List args = new ArrayList<>(this.variables.size()); + for (Map.Entry arg : this.variables.entrySet()) { + args.add(arg.getKey() + "=" + arg.getValue()); } - return NO_VALUE; + return args.toArray(new String[0]); } - private boolean hasText(String source) { - return source != null && !source.trim().isEmpty(); - } - - } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java index 6231252c6b..cf75bd6b50 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java @@ -66,14 +66,15 @@ public class RunMojo extends AbstractRunMojo { } @Override - protected void runWithForkedJvm(File workingDirectory, List args, Map environmentVariables) + protected void runWithForkedJvm(File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException { try { RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString()); Runtime.getRuntime() .addShutdownHook(new Thread(new RunProcessKiller(runProcess))); - int exitCode = runProcess.run(true, args.toArray(new String[0]), environmentVariables); + int exitCode = runProcess.run(true, args, environmentVariables); if (exitCode == 0 || exitCode == EXIT_CODE_SIGINT) { return; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java index 5760e04f90..151981c6c2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java @@ -47,7 +47,6 @@ import org.springframework.boot.loader.tools.RunProcess; * stopped after. * * @author Stephane Nicoll - * @author Dmytro Nosan * @since 1.3.0 * @see StopMojo */ @@ -90,7 +89,8 @@ public class StartMojo extends AbstractRunMojo { private final Object lock = new Object(); @Override - protected void runWithForkedJvm(File workingDirectory, List args, Map environmentVariables) + protected void runWithForkedJvm(File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException, MojoFailureException { RunProcess runProcess = runProcess(workingDirectory, args, environmentVariables); try { @@ -102,12 +102,13 @@ public class StartMojo extends AbstractRunMojo { } } - private RunProcess runProcess(File workingDirectory, List args, Map environmentVariables) + private RunProcess runProcess(File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException { try { RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString()); - runProcess.run(false, args.toArray(new String[0]), environmentVariables); + runProcess.run(false, args, environmentVariables); return runProcess; } catch (Exception ex) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-env-variables.apt.vm b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-env-variables.apt.vm new file mode 100644 index 0000000000..855fc8a329 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-env-variables.apt.vm @@ -0,0 +1,50 @@ + ----- + Using environment variables + ----- +Dmytro Nosan + ----- + 2018-04-08 + ----- + + Environment variables can be specified using the <<>> attribute. + The following sets the 'ENV1', 'ENV2', 'ENV3', 'ENV4' env variables: + +--- + + ... + + ... + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + 5000 + Some Text + + + + + ... + + ... + + ... + + ... + +--- + + If the value is empty or not defined (i.e. <<<>>>), the env variable is set + with an empty String as the value. + + Any String typed Maven variable can be passed as system properties. Any attempt to pass + any other Maven variable type (e.g. a <<>> or a <<>> variable) will cause the + variable expression to be passed literally (unevaluated). + + Environment variables defined this way take precedence over existing values. + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-with-env.apt.vm b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-with-env.apt.vm deleted file mode 100644 index 7bbe5b7b93..0000000000 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/run-with-env.apt.vm +++ /dev/null @@ -1,43 +0,0 @@ - ----- - Specify environment variables - ----- -Dmytro Nosan - ----- - 2018-04-08 - ----- - - The environmnet variables to use for a particular application can be specified using the <<>> - argument. The following configuration enables the 'ENV1', 'ENV2', 'ENV3', 'ENV4' env variables: - ---- - - ... - - ... - - ... - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - 5000 - Some Text - - - - - ... - - ... - - ... - - ... - ---- - - Note that since you specified some Environment variables, the process is forked automatically. - - diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt index 5ed3cc8a37..22fa6c63ca 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt @@ -54,14 +54,14 @@ Spring Boot Maven Plugin * {{{./examples/run-system-properties.html}Using system properties}} + * {{{./examples/run-env-variables.html}Using environment variables}} + * {{{./examples/it-random-port.html}Random port for integration tests}} * {{{./examples/it-skip.html}Skip integration tests}} * {{{./examples/run-profiles.html}Specify active profiles}} - * {{{./examples/run-with-env.html}Specify Environment variables}} - * {{{./examples/build-info.html}Generate build information}} * {{{./examples/custom-layout.html}Custom layout}} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm index 1bf825f0ad..f7cc89ed06 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm @@ -140,11 +140,12 @@ mvn spring-boot:run If you need to specify some JVM arguments (i.e. for debugging purposes), you can use the <<>> parameter, see {{{./examples/run-debug.html}Debug the application}} - for more details. There is also explicit support - {{{./examples/run-system-properties.html}for system properties}} and - {{{./examples/run-with-env.html}environment variables}}. As a convenience, the profiles - to enable are handled by a specific property (<<>>), see - {{{./examples/run-profiles.html}Specify active profiles}}. + for more details. There is also explicit support for + {{{./examples/run-system-properties.html}system properties}} and + {{{./examples/run-env-variables.html}environment variables}}. + + As a convenience, the profiles to enable are handled by a specific property ( + <<>>), see {{{./examples/run-profiles.html}Specify active profiles}}. Spring Boot 1.3 has introduced <<>>, a module to improve the development-time experience when working on Spring Boot applications. To enable it, just add the following diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml index e0000dd907..89218fd978 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml @@ -12,10 +12,10 @@ + - diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/EnvVariablesTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/EnvVariablesTests.java index 595fe24b7a..21242e19b7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/EnvVariablesTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/EnvVariablesTests.java @@ -22,6 +22,7 @@ import java.util.Map; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; /** * Tests for {@link EnvVariables}. @@ -33,40 +34,29 @@ public class EnvVariablesTests { @Test public void asNull() { Map args = new EnvVariables(null).asMap(); - assertThat(args).hasSize(0); + assertThat(args).isEmpty(); } - @Test public void asArray() { assertThat(new EnvVariables(getTestArgs()).asArray()) - .contains("key=My Value") - .contains("key1= tt ") - .contains("key2=") - .contains("key3="); + .contains("key=My Value", "key1= tt ", "key2= ", "key3="); } @Test public void asMap() { - assertThat(new EnvVariables(getTestArgs()).asMap()) - .containsEntry("key", "My Value") - .containsEntry("key1", " tt ") - .containsEntry("key2", "") - .containsEntry("key3", ""); + assertThat(new EnvVariables(getTestArgs()).asMap()).containsExactly( + entry("key", "My Value"), entry("key1", " tt "), entry("key2", " "), + entry("key3", "")); } - private Map getTestArgs() { Map args = new LinkedHashMap<>(); args.put("key", "My Value"); - //should not be trimmed args.put("key1", " tt "); args.put("key2", " "); args.put("key3", null); return args; } - - - }