question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GraalVM Native Image does not include MixIn options

See original GitHub issue

I’m very new in both picocli (fantastic tool!) and GraalVM. I’m using a Mixin to reuse options across multiple sub-commands. This works as expected when running the app with Java. When packaging the app with GraalVM native image, the Mixin options are missing.

  • Expected result: my CLI app should offer the same options, regardless of whether the app is run via Java or packaged via GraalVM

  • Actual result: the app does not offer reusable mixin options when packaged via GraalVM

Some versions:

Java: 1.8 OS: Fedora 30 Building with: Gradle 5.6.3 Picocli: 4.0.4 GraalVM: 19.0.2.1

This is the main Command Line (just pulls-in various sub-commands):

@Command(
    synopsisSubcommandLabel = "COMMAND",
    subcommands = {
        CreateCommand.class,
        DeleteCommand.class,
        ListCommand.class
    }
)
public class App implements Callable<Integer> {
    /**
     * Runs the application.
     * @param args Command line arguments.
     */
    public static void main(String[] args) {
        System.exit(
            new CommandLine(new App())
                .setCaseInsensitiveEnumValuesAllowed(true)
                .execute(args)
        );
    }

    @Override
    public Integer call() {
        System.out.println("Missing sub-command");
        return -1;
    }
}

This is the list command:

@Command(
    name = "list",
    description = {"Lists the available repositories"}
)
class ListCommand implements Callable<Integer> {
    @Mixin
    private ProviderMixin providerMixin;

    @Override
    public Integer call() throws IOException {
        System.out.println(
            String.format(
                "owner %s username %s password %s provider %s",
                providerMixin.getOwner(),
                providerMixin.getUsername(),
                providerMixin.getPassword(),
                providerMixin.getProvider()
            )
        );
        return 0;
    }
}

and this is the mixin:

public class ProviderMixin {
    @CommandLine.Option(
        names = {"--owner"},
        required = true,
        description = {"The owner of the repository"}
    )
    private String owner;

    @CommandLine.Option(
        names = {"--username"},
        required = true,
        description = {"The username to access the git provider API"}
    )
    private String username;

    @CommandLine.Option(
        names = {"--password"},
        required = true,
        description = {"The password to access the git provider API"}
    )
    private String password;

    @CommandLine.Option(
        names = {"--provider"},
        required = true,
        description = {"The provider of the git repository (${COMPLETION-CANDIDATES})"}
    )
    private GitProvider provider;

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public GitProvider getProvider() {
        return provider;
    }

    public void setProvider(GitProvider provider) {
        this.provider = provider;
    }
}

The GitProvider is an enum.

I have Gradle configured regarding the annotation processor:

dependencies {
    // This dependency is used by the application.
    implementation "info.picocli:picocli:4.0.4"
    annotationProcessor "info.picocli:picocli-codegen:4.0.4"
}

compileJava {
    options.compilerArgs += ["-Aproject=${project.name}"]
}

Note that I had to remove from compilerArgs the ${project.group}/ that is mentioned in the documentation.

When I build the project, I see that I have a reflect-config.json which indeed lacks the mixin fields.

  {
    "name" : "instarepo.ListCommand",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true
  }

Direct option fields (not via a mixin) are included:

{
    "name" : "instarepo.CreateCommand",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true,
    "fields" : [
      { "name" : "description" },
      { "name" : "language" },
      { "name" : "name" }
    ]
  }

This is the output of my cli app generated by GraalVM (it lacks the mixin options):

[ngeor@localhost instarepo]$ ./build/graal/instarepo create --help
Missing required options [--name=<name>, --description=<description>, --language=<language>]
Usage: <main class> create --description=<description> --language=<language>
                           --name=<name>
Creates a new git repository
      --description=<description>
                      The description of the repository
      --language=<language>
                      The language of the repository
      --name=<name>   The name of the repository

and this is the output when I run it with Java (it has the extra options that are offered via the mixin):

[ngeor@localhost instarepo]$ gradle run --args="create --help"

Missing required options [--name=<name>, --owner=<owner>, --username=<username>, --password=<password>, --provider=<provider>, --description=<description>, --language=<language>]
Usage: <main class> create --description=<description> --language=<language>
                           --name=<name> --owner=<owner> --password=<password>
                           --provider=<provider> --username=<username>
Creates a new git repository
      --description=<description>
                        The description of the repository
      --language=<language>
                        The language of the repository
      --name=<name>     The name of the repository
      --owner=<owner>   The owner of the repository
      --password=<password>
                        The password to access the git provider API
      --provider=<provider>
                        The provider of the git repository (GITHUB, BITBUCKET)
      --username=<username>
                        The username to access the git provider API

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:16 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
ngeorcommented, Nov 2, 2019

Ok… with the help of this article I was able to solve the TLS issue:

  • add option "--enable-https" to the configuration of the graal-gradle plugin
  • copy the libsunec.so from the GraalVM distribution into my app (which means my app is no longer a single executable, but it needs this shared library as well)
1reaction
remkopcommented, Nov 4, 2019

I’m closing this ticket because there is no more work remaining for the “Mixins on GraalVM” problem, but we can continue to discuss further here or on a new ticket if you like.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Native Image Options - GraalVM
The native-image builder needs to provide the classpath for all classes using the ... The options passed to native-image are evaluated left-to-right.
Read more >
Native Image Options - GraalVM
Native Image Options. To ahead-of-time compile your Java application into a native executable, provide the classpath for all classes using the -cp option...
Read more >
Native Image Compatibility and Optimization Guide - GraalVM
Because the native image builder generates a native executable, users must use native debuggers and monitoring tools (such as GDB or VTune) rather...
Read more >
Issue with picocli and GraalVM native-image - Stack Overflow
The application works fine when I run it via IntelliJ or a simple java -jar command. I tried a few things, as removing...
Read more >
the file in the editor is not runnable intellij - Muskoka 411
One idea is to add a separate different option (that could be named ... gradle-graal plugin by Palantir, or the graalvm-native-image plugin by...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found