How to pass JVM options from bootRun

JavaGradleSpring Boot

Java Problem Overview


I'm developing simple Spring web application that communicates with remote host and I would like to test it locally behind corporate proxy. I use "Spring Boot" gradle plugin and the question is how can I specify proxy settings for JVM?

I have try several ways to do it:

  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"

But it seems like none of them work - "NoRouteToHostException" throws in "network" code. Also, I have added some extra code to debug JVM start arguments:

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

And only one argument was printed: "-Dfile.encoding=UTF-8".

If I set system property in code:

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

Everything works just fine!

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

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

Solution 3 - Java

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

Solution 4 - Java

@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.

Solution 5 - Java

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

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

Solution 6 - Java

It seems to work:

bootRun {
    systemProperties "property1": "value1", "property2": "value2"
}

Solution 7 - Java

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

Solution 8 - Java

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

Solution 9 - Java

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"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEvgenyView Question on Stackoverflow
Solution 1 - JavageoandView Answer on Stackoverflow
Solution 2 - JavaMarvin FrommholdView Answer on Stackoverflow
Solution 3 - Javasuman jView Answer on Stackoverflow
Solution 4 - JavaRishik DharView Answer on Stackoverflow
Solution 5 - JavaCristian BotizaView Answer on Stackoverflow
Solution 6 - JavalevsaView Answer on Stackoverflow
Solution 7 - JavaEvelino BomitaliView Answer on Stackoverflow
Solution 8 - JavaKevin-PrichardView Answer on Stackoverflow
Solution 9 - JavaDave KraczoView Answer on Stackoverflow