Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected arguments in main #65

Closed
akabanov57 opened this issue Jan 28, 2019 · 8 comments · Fixed by #153
Closed

unexpected arguments in main #65

akabanov57 opened this issue Jan 28, 2019 · 8 comments · Fixed by #153
Labels
bug Something isn't working

Comments

@akabanov57
Copy link

Hello,
plugin version - "1.4.0",
git - "gradle-modules-plugin-example",
project - "greater.runner'.
If we add to Runner.main(String[] args)
for (String arg: args) {
System.out.println(arg);
}
and run application, than we will find in output:
-Dfile.encoding=UTF-8
-Duser.country=US
-Duser.language=en
-Duser.variant
greeter.runner/examples.Runner
Hello and welcome!
It seems these arguments should not be.

@mirko-lelansky
Copy link

I have related problems in combination with the cli library "picocli" and java modules. The problem are the standard start script generators templates of gradle see "unixStartScript" and "windowsStartScript". At the very end of the templates there is the substitution of the variables. If you use the classpath the cmd should be something like this java -classpath ... mainClassName but with the module path that will be something like this java --module-path ... --module mainModule. The plugin adds these options as additional JVM arguments. That means that the plugin generates something like this java --module-path ... --module mainModule --classpath ... mainClassName. The JVM module system starts the application normally with "module-path" and "module" but the "mainClassName" will be the first argument of your application "args". The other outputs are system properties which comes from the substitution, too.

@paulbakker
Copy link
Collaborator

Thanks for explaining the cause @mirko-lelansky, that will be helpful for fixing this issue.

@jochembroekhoff
Copy link

The current version (1.5.0) still appears to be affected.

I'm facing the same issue, also using Picocli.

@mkmatis
Copy link

mkmatis commented Jun 23, 2019

Does anyone know if there is any way to work around this issue until it's fixed?

@FranciscoPombal
Copy link

FranciscoPombal commented Sep 2, 2019

This issue has been reported in the Gradle forums:
https://discuss.gradle.org/t/help-configuring-build-for-java-9-modules-extraneaous-command-line-arguments-passed-to-application/32970

EDIT: also confirmed still an issue as of version 1.6.0 of this plugin

@paulbakker
Copy link
Collaborator

paulbakker commented Sep 2, 2019

This should be fixed in the 1.6.0 release that went out on September 2nd. Please re-open if there are still issues.

@tlinkowski
Copy link
Collaborator

tlinkowski commented Sep 3, 2019

There are many things at work here - I'll try to get them in some order.

Reports

  1. As linked above, Bradley Hunter reported on Gradle Forms an issue about gradle run. Apparently, this issue may still occur due to how JVM treats arguments supplied to it after --module-path and/or --module args (it's described well in the Gradle issue linked above).

  2. @brunoborges reported on Twitter his inability to debug a modularized JVM app (--debug-jvm not working). According to this tweet, removing Gradle Modules Plugin makes --debug-jvm work, so there's high chance it's something in our plugin.

Tests introduced by Serban

Tests introduced in #105 by @siordache cover startscripts only, i.e. they cover gradle installDist task + calling *.bat/sh manually:

@ParameterizedTest
@ValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"})
void smokeTestRunStartScripts(String projectName) {
var result = GradleRunner.create()
.withProjectDir(new File(projectName + "/"))
.withPluginClasspath(pluginClasspath)
.withGradleVersion(GRADLE_VERSION)
.withArguments("-c", "smoke_test_settings.gradle", "clean", ":greeter.startscripts:installDist", "--info", "--stacktrace")
.forwardOutput()
.build();
assertTasksSuccessful(result, "greeter.startscripts", "installDist");
String binDir = projectName + "/greeter.startscripts/build/install/demo/bin";
SmokeTestAppContext ctx = SmokeTestAppContext.ofAliceAndBobAtHome(Path.of(binDir));
assertEquals("MainDemo: welcome home, Alice and Bob!", ctx.getAppOutput("demo"));
assertEquals("Demo1: welcome home, Alice and Bob!", ctx.getAppOutput("demo1"));
assertEquals("Demo2: welcome home, Alice and Bob!", ctx.getAppOutput("demo2"));
}

There are no similar tests for direct gradle run followed by some extra arguments like --debug-jvm:

@ParameterizedTest
@ValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"})
void smokeTest(String projectName) {
var result = GradleRunner.create()
.withProjectDir(new File(projectName + "/"))
.withPluginClasspath(pluginClasspath)
.withGradleVersion(GRADLE_VERSION)
.withArguments("-c", "smoke_test_settings.gradle", "clean", "build", "run", "--stacktrace")
.forwardOutput()
.build();
assertTasksSuccessful(result, "greeter.api", "build");
assertTasksSuccessful(result, "greeter.provider", "build");
assertTasksSuccessful(result, "greeter.provider.test", "build");
assertTasksSuccessful(result, "greeter.runner", "build", "run");
}

nor for gradle runDemoN (where runDemoN is a custom modular task of type ModularJavaExec):

@ParameterizedTest
@ValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"})
void smokeTestRunDemo(String projectName) {
var result = GradleRunner.create()
.withProjectDir(new File(projectName + "/"))
.withPluginClasspath(pluginClasspath)
.withGradleVersion(GRADLE_VERSION)
.withArguments("-c", "smoke_test_settings.gradle", "clean", "build",
":greeter.javaexec:runDemo1", ":greeter.javaexec:runDemo2", "--info", "--stacktrace")
.forwardOutput()
.build();
assertTasksSuccessful(result, "greeter.javaexec", "runDemo1", "runDemo2");
}

What we can do

We could start by extending Serban's tests to all those run tasks (both unmodular run as weel as modular runDemoN).

I think -Dgreeting.addition=home should be passed to GradleRunner.withArguments(), once as the first argument, once as the last one, to see what happens. We could also test how passing --debug-jvm behaves.

Finally, I think only when we understand the problem fully, we can start thinking about potential solutions.

Related issues

@tlinkowski tlinkowski reopened this Sep 3, 2019
@FranciscoPombal
Copy link

@paulbakker

This should be fixed in the 1.6.0 release that went out on September 2nd. Please re-open if there are still issues.

See my edit in the comment above, the issue is still present as of 1.6.0

@tlinkowski

  1. @brunoborges reported on Twitter his inability to debug a modularized JVM app (--debug-jvm not working). According to this tweet, removing Gradle Modules Plugin makes --debug-jvm work, so there's high chance it's something in our plugin.

--debug-jvm does not work due to the same problem outlined in that Gradle Forums post; the --debug-jvm just makes Gradle append the following flags to the flags passed to the JVM:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

Since these flags will also come after the --module flag, the JVM ignores them and they get passed to the application. This happens with or without the plugin (as of plugin version 1.6.0). Here is the workaround I use, in a configuration without the plugin (basically force Gradle to prepend the flags, to make sure they come before --module):

tasks.named<JavaExec>("run") {
    inputs.property("moduleName", moduleName)

    val jvmArgsList = mutableListOf(
                        "--module-path", getClasspath().getAsPath(),
                        "--module", "$moduleName/$mainClassName"
                    )

    // FIXME: dirty workaround for --debug-jvm being broken. run with:
    // ./gradlew -PdebugWorkaround run
    if(project.hasProperty("debugWorkaround")){
        jvmArgsList.add(0, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")
    }

    doFirst {
        jvmArgs(jvmArgsList)
        setClasspath(files())
    }
}

Not sure how the plugin could do something similar, but I hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants