如何从 bootRun 传递 JVM 选项

我正在开发一个简单的 Spring Web 应用程序,它可以与远程主机进行通信,我想在公司代理的本地环境下进行测试。 我使用“ Spring Boot”gradle 插件,问题是 < strong > 如何为 JVM 指定代理设置?

我已经尝试了几种方法:

  1. gradle -Dhttp.proxyHost=X.X.X.X -Dhttp.proxyPort=8080 bootRun
  2. export JAVA_OPTS="-Dhttp.proxyHost=X.X.X.X -Dhttp.proxyPort=8080"
  3. export GRADLE_OPTS="-Dhttp.proxyHost=X.X.X.X -Dhttp.proxyPort=8080"

但它们似乎都不起作用——“ NoRouteToHostException”引入了“ network”代码。 另外,我还添加了一些额外的代码来调试 JVM start 参数:

    RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
for (String arg: arguments) System.out.println(arg);

而且只打印了一个参数: “-Dfile.coding = UTF-8”。

如果在代码中设置系统属性:

    System.setProperty("http.proxyHost", "X.X.X.X");
System.setProperty("http.proxyPort", "8080");

一切正常!

92845 次浏览

In gradle build script, define systemProperties for run task.

//to provide the properties while running the application using spring-boot's run task
run {
systemProperties['property name'] = 'value'
}

and gradle run should accept this value.

Or define a project level property as mentioned in http://forums.gradle.org/gradle/topics/how_can_i_provide_command_line_args_to_application_started_with_gradle_run

Original Answer (using Gradle 1.12 and Spring Boot 1.0.x):

The bootRun task of the Spring Boot gradle plugin extends the gradle JavaExec task. See this.

That means that you can configure the plugin to use the proxy by adding:

bootRun {
jvmArgs = "-Dhttp.proxyHost=xxxxxx", "-Dhttp.proxyPort=xxxxxx"
}

to your build file.

Of course you could use the systemProperties instead of jvmArgs

If you want to conditionally add jvmArgs from the command line you can do the following:

bootRun {
if ( project.hasProperty('jvmArgs') ) {
jvmArgs project.jvmArgs.split('\\s+')
}
}


gradle bootRun -PjvmArgs="-Dwhatever1=value1 -Dwhatever2=value2"

Updated Answer:

After trying out my solution above using Spring Boot 1.2.6.RELEASE and Gradle 2.7 I observed that it was not working as some of the comments mention. However, a few minor tweaks can be made to recover the working state.

The new code is:

bootRun {
jvmArgs = ["-Dhttp.proxyHost=xxxxxx", "-Dhttp.proxyPort=xxxxxx"]
}

for hard-coded arguments, and

bootRun {
if ( project.hasProperty('jvmArgs') ) {
jvmArgs = (project.jvmArgs.split("\\s+") as List)


}
}

for arguments provided from the command line

It seems to work:

bootRun {
systemProperties "property1": "value1", "property2": "value2"
}
bootRun {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}

This should pass all JVM options to the app started via bootRun.

bootRun {
args = ['myProgramArgument1', 'myProgramArgument2']
}

Using jvmArgs may cause JVM start issues. Using args allows you to pass your custom program arguments

@marvin, thanks for your post it was very helpful.

Sharing how I used it:

test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}

I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:

//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)

Doing this with gradle required that the system property provided at the time of running gradle build, shown here,

gradle build -Ddeep.test.run=true

was indeed passed through to the tests.

Hope this helps others trying out this approach for running tests conditionally.

I got into a similar problem, bootRun needed some parameters but I wouldn't feel like modifying bootRun as I want to keep some flexibility and stick to standard bootRun behaviour. My suggestion is to add some custom tasks (let's say bootRunDev, bootRunProxy) that extends bootRun, as described in the following code snippet

task bootRunPxy(type: org.springframework.boot.gradle.run.BootRunTask, dependsOn: 'build') {
group = 'Application'
doFirst() {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
systemProperty 'http.proxyHost', 'xxxxx'
systemProperty 'http.proxyPort', 'yyyyy'
}
}

I don't have an environment to exercise the script but I used this approach to pass profile to spring using the property spring.profiles.active. Credits should go to Karol Kaliński

It's worth mentioning, here, that some systems that use Gradle and Spring Boot are starting JVM outside of build.gradle, e.g. in a Dockerfile.

It's not pointless to mention this on a thread specifically about bootRun! I wound up here because this particular post is a magnet for searches about jvm options in the context of a Spring Boot app compiled / run under gradle. (All the advice I found for adding java.net.http.httpclient logging said "add it to bootRun's jvmArgs". Nothing happened, though.

So, if you happen to run your gradle-built Spring Boot app from a Docker container, you'll want to add your JVM params to an env var in your project's Dockerfile, like so, e.g.-

...
ENV JAVA_OPTS "${JAVA_OPTS} \
-server \
-Duser.timezone=UTC \
-XX:InitialRAMPercentage=50 \
-XX:MaxRAMPercentage=50 \
-Djavax.net.ssl.trustStorePassword=elvislives \
-Djavax.net.ssl.trustStoreProvider=BCFIPS \
-Djavax.net.ssl.trustStoreType=BCFKS \
-Djdk.internal.httpclient.debug=true \
-Djava.util.logging.manager=org.apache.logging.log4j2.jul.LogManager \
-Djdk.httpclient.HttpClient.log=errors,requests,headers,frames[:control:data:window:all..],content,ssl,trace,channel \
"
...


ENTRYPOINT java ${JAVA_OPTS} -cp app:app/lib/* com.mygreatcompany.theapp

For development as Docker Container add to run_script.sh as JAVA_OPTS

JAVA_OPTS="-XX:+UseG1GC -Xms512m -Xmx2048m --add-opens java.base/java.util=ALL-UNNAMED -Dspring.profiles.active=$PROFILE,discovery"