Add jvmArguments property to maven plugin
The maven plugin now forks a new process when it starts a boot app. This makes remote debugging of the app impossible without the ability to pass extra JVM arguments. This commit adds a "jvmArguments" attribute to the RunMojo that defines additional JVM arguments to set on the forked process. Fixes gh-848
This commit is contained in:
parent
5249f54c5a
commit
a93784207e
|
@ -0,0 +1,31 @@
|
|||
<?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>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>run-jvmargs</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<jvmArguments>-Dfoo="value 1" -Dbar=value2</jvmArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
String foo = System.getProperty("foo");
|
||||
if (!"value 1".equals(foo)) {
|
||||
throw new IllegalStateException("foo system property mismatch (got [" + foo + "]");
|
||||
}
|
||||
String bar = System.getProperty("bar");
|
||||
if (!"value2".equals(bar)) {
|
||||
throw new IllegalStateException("bar system property mismatch (got [" + bar + "]");
|
||||
}
|
||||
System.out.println("I haz been run");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def file = new File(basedir, "build.log")
|
||||
return file.text.contains("I haz been run")
|
||||
|
|
@ -23,6 +23,7 @@ import java.net.URL;
|
|||
import java.security.CodeSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -38,6 +39,8 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
|
|||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactFeatureFilter;
|
||||
import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
|
||||
import org.codehaus.plexus.util.cli.CommandLineUtils;
|
||||
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
import org.springframework.boot.loader.tools.JavaExecutable;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
@ -87,6 +90,15 @@ public class RunMojo extends AbstractDependencyFilterMojo {
|
|||
@Parameter(property = "run.noverify")
|
||||
private Boolean noverify;
|
||||
|
||||
/**
|
||||
* JVM arguments that should be associated with the forked process used
|
||||
* to run the application. On command line, make sure to wrap multiple
|
||||
* values between quotes.
|
||||
* @since 1.1
|
||||
*/
|
||||
@Parameter(property = "run.jvmArguments")
|
||||
private String jvmArguments;
|
||||
|
||||
/**
|
||||
* Arguments that should be passed to the application. On command line use commas to
|
||||
* separate multiple arguments.
|
||||
|
@ -151,6 +163,7 @@ public class RunMojo extends AbstractDependencyFilterMojo {
|
|||
private void run(String startClassName) throws MojoExecutionException {
|
||||
List<String> args = new ArrayList<String>();
|
||||
addAgents(args);
|
||||
addJvmArgs(args);
|
||||
addClasspath(args);
|
||||
args.add(startClassName);
|
||||
addArgs(args);
|
||||
|
@ -163,10 +176,15 @@ public class RunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void addArgs(List<String> args) {
|
||||
for (String arg : this.arguments) {
|
||||
args.add(arg);
|
||||
private void addJvmArgs(List<String> args) {
|
||||
String[] jvmArgs = parseArgs(this.jvmArguments);
|
||||
Collections.addAll(args, jvmArgs);
|
||||
logArguments("JVM argument(s): ", jvmArgs);
|
||||
}
|
||||
|
||||
private void addArgs(List<String> args) {
|
||||
Collections.addAll(args, this.arguments);
|
||||
logArguments("Application argument(s): ", this.arguments);
|
||||
}
|
||||
|
||||
private void addClasspath(List<String> args) throws MojoExecutionException {
|
||||
|
@ -240,7 +258,7 @@ public class RunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void addResources(List<URL> urls) throws MalformedURLException, IOException {
|
||||
private void addResources(List<URL> urls) throws IOException {
|
||||
if (this.addResources) {
|
||||
for (Resource resource : this.project.getResources()) {
|
||||
File directory = new File(resource.getDirectory());
|
||||
|
@ -266,6 +284,36 @@ public class RunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void logArguments(String message, String[] args) {
|
||||
StringBuffer sb = new StringBuffer(message);
|
||||
for (String arg : args) {
|
||||
sb.append(arg).append(" ");
|
||||
}
|
||||
getLog().debug(sb.toString().trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments parameters and return individual arguments.
|
||||
*
|
||||
* @param arguments the arguments line to parse
|
||||
* @return the individual arguments
|
||||
*/
|
||||
static String[] parseArgs(String arguments) {
|
||||
if (arguments == null || arguments.trim().isEmpty()) {
|
||||
return new String[]{};
|
||||
}
|
||||
String args = arguments.replace('\n', ' ');
|
||||
args = args.replace('\t', ' ');
|
||||
|
||||
try {
|
||||
return CommandLineUtils.translateCommandline(args);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to parse arguments [" + arguments + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestArtifactFilter extends AbstractArtifactFeatureFilter {
|
||||
public TestArtifactFilter() {
|
||||
super("", Artifact.SCOPE_TEST);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
-----
|
||||
Debug the application
|
||||
-----
|
||||
Stephane Nicoll
|
||||
-----
|
||||
2014-05-14
|
||||
-----
|
||||
|
||||
The <<<run>>> goal forks a process for the boot application. It is possible to specify jvm arguments
|
||||
to that forked process. The following configuration suspend the process until a debugger has joined
|
||||
on port 5005
|
||||
|
||||
---
|
||||
<project>
|
||||
...
|
||||
<build>
|
||||
...
|
||||
<plugins>
|
||||
...
|
||||
<plugin>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<jvmArguments>
|
||||
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
|
||||
</jvmArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
...
|
||||
</plugin>
|
||||
...
|
||||
</plugins>
|
||||
...
|
||||
</build>
|
||||
...
|
||||
</project>
|
||||
---
|
||||
|
||||
These arguments can be specified on the command line as well, make sure to wrap that properly,
|
||||
that is:
|
||||
|
||||
---
|
||||
mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
|
||||
---
|
||||
|
||||
|
||||
|
|
@ -40,6 +40,8 @@ Spring Boot Maven Plugin
|
|||
|
||||
* {{{./examples/exclude-dependency.html}Exclude a dependency}}
|
||||
|
||||
* {{{./examples/run-debug.html}Debug the application}}
|
||||
|
||||
[]
|
||||
|
||||
|
||||
|
|
|
@ -99,6 +99,10 @@ Usage
|
|||
mvn spring-boot:run
|
||||
---
|
||||
|
||||
The application is forked in a separate process. If you need to specify some JVM arguments
|
||||
(i.e. for debugging purposes), you can use the <<<jvmArguments>>> parameter, see
|
||||
{{{./examples/run-debug.html}Debug the application}} for more details.
|
||||
|
||||
By default, any <<src/main/resources>> folder will be added to the application classpath
|
||||
when you run the application. This allows hot refreshing of resources which can be very
|
||||
useful when developing web applications. For example, you can work on HTML, CSS or JavaScipt
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<menu name="Examples">
|
||||
<item name="Custom repackage classifier" href="examples/repackage-classifier.html"/>
|
||||
<item name="Exclude a dependency" href="examples/exclude-dependency.html"/>
|
||||
<item name="Debug the application" href="examples/run-debug.html"/>
|
||||
</menu>
|
||||
<menu ref="reports"/>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class RunMojoTests {
|
||||
|
||||
@Test
|
||||
public void parseNull() {
|
||||
String[] args = RunMojo.parseArgs(null);
|
||||
assertNotNull(args);
|
||||
assertEquals(0, args.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseEmpty() {
|
||||
String[] args = RunMojo.parseArgs(" ");
|
||||
assertNotNull(args);
|
||||
assertEquals(0, args.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseDebugFlags() {
|
||||
String[] args = RunMojo.parseArgs("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005");
|
||||
assertEquals(2, args.length);
|
||||
assertEquals("-Xdebug", args[0]);
|
||||
assertEquals("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005", args[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseWithExtraSpaces() {
|
||||
String[] args = RunMojo.parseArgs(" -Dfoo=bar -Dfoo2=bar2 ");
|
||||
assertEquals(2, args.length);
|
||||
assertEquals("-Dfoo=bar", args[0]);
|
||||
assertEquals("-Dfoo2=bar2", args[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseWithNewLinesAndTabs() {
|
||||
String[] args = RunMojo.parseArgs(" -Dfoo=bar \n" +
|
||||
"\t\t -Dfoo2=bar2 ");
|
||||
assertEquals(2, args.length);
|
||||
assertEquals("-Dfoo=bar", args[0]);
|
||||
assertEquals("-Dfoo2=bar2", args[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quoteHandledProperly() {
|
||||
String[] args = RunMojo.parseArgs("-Dvalue=\"My Value\" ");
|
||||
assertEquals(1, args.length);
|
||||
assertEquals("-Dvalue=My Value", args[0]);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue