picocli
picocli copied to clipboard
GraalVM: Options from superclass not visible
I have an abstract base command class that defines an ArgGroup as follows:
public abstract class AbstractSomeBaseCommand implements Runnable {
@ArgGroup(heading = "Some arg group:%n", order = 1000)
@Getter private MyArgGroup argGroup;
private static class MyArgGroup {
// This option is not recognized by picocli for concrete command subclasses when running as native image
@Option(names = {"--someOption", "-s"}, required = false, defaultValue = "default")
@Getter private String someOption;
}
...
}
This base class is extended by an actual command class, defining some additional options or argument groups. When running as a normal jar file (or from within my IDE), all options from both base class and actual command class are properly recognized by Picocli.
However, when running as a GraalVM native image, Picocli doesn't recognize the options defined in the abstract base class; they do not show up in the help output, and you get an 'Unknown option' error when trying to use these options from the base class.
A similar issue can be seen with argument group classes that extend from some other class (also if the base class is not abstract). In the following example, again the options from MyArgGroupNonAbstractBaseClass are not recognized in the native image:
@ArgGroup(heading = "My xyz options:%n", order = 1000)
@Getter private MyArgGroup argGroup;
// Any options defined in MyArgGroupNonAbstractBaseClass are not visible when running as native image
private static class MyArgGroup extends from MyArgGroupNonAbstractBaseClass {
@Option(names = {"--extra-option", "-e"}, required = false, defaultValue = "default")
@Getter private String extraOption;
}
Any idea on how this can be fixed?
Can you try making the annotated fields protected
instead of private
?
Can you try making the annotated fields
protected
instead ofprivate
?
Thanks, I'll try that and let you know the results. In the meantime I did try using the default access modifier together with Micronauts @ReflectiveAccess
annotation for the affected fields , however this results in the following stacktrace:
Error: Exception in thread "main" picocli.CommandLine$InitializationException: Could not access or modify mixin member com.myapp.cli.session.command.consumer.LoginSessionConsumerMixin com.myapp.cli.session.command.logout.AbstractSessionLogoutCommand.loginSessionConsumerMixin: java.lang.NoSuchMethodException: com.myapp.cli.session.command.consumer.LoginSessionConsumerMixin.<init>()
at picocli.CommandLine$Model$CommandReflection.buildMixinForMember(CommandLine.java:11612)
at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedTypedMembers(CommandLine.java:11487)
at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedFields(CommandLine.java:11466)
at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:11399)
at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:6202)
at picocli.CommandLine.<init>(CommandLine.java:227)
at picocli.CommandLine.<init>(CommandLine.java:221)
at com.myapp.cli.MyApp.addSubcommands(MyApp.java:52)
at com.myapp.cli.MyApp.addSubcommands(MyApp.java:54)
at com.myapp.cli.MyApp.addSubcommands(MyApp.java:44)
at com.myapp.cli.MyApp.execute(MyApp.java:36)
at com.myapp.cli.MyApp.main(MyApp.java:85)
Caused by: java.lang.NoSuchMethodException: com.myapp.cli.session.command.consumer.LoginSessionConsumerMixin.<init>()
at java.lang.Class.getConstructor0(DynamicHub.java:3349)
at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2553)
at picocli.CommandLine$DefaultFactory.create(CommandLine.java:5489)
at io.micronaut.configuration.picocli.MicronautFactory.create(MicronautFactory.java:74)
at picocli.CommandLine$Model$CommandReflection.buildMixinForMember(CommandLine.java:11604)
... 11 more
LoginSessionConsumerMixin
is (as the name implies) used as an @Mixin
in an abstract class, so at least picocli seems to see this mixin now. LoginSessionConsumerMixin
doesn't declare any constructors, so not sure why picocli can't find a no-arg constructor...
Can you try making the annotated fields
protected
instead ofprivate
?Thanks, I'll try that and let you know the results.
Tried making all relevant option & mixin fields protected, but unfortunately those options are still not being recognized by picocli when running in GraalVM native image. I also noticed that for example @ParentCommand
doesn't get properly injected when defined in an (abstract) superclass of the actual command implementation.
Can you show your class and the generated reflect.json
?
(Edited) In the meantime I've been able to make this work by declaring Micronaut's @ReflectiveAccess
annotation at class-level (rather than field-level) for the affected classes, allowing picocli to use reflection to call the default constructors of these classes and then inject the appropriate fields.
It does seem a bit cumbersome though having to annotate almost every picocli-related class with @ReflectiveAccess
if that class can potentially be used in a class hierarchy. I'm also wondering whether this has any negative consequences; I'm assuming that GraalVM disables reflection by default for a reason.
So although this is working now, I still have some questions:
- Any idea why
@ReflectiveAccess
is needed? - Could this be related to programmatically registering the commands and subcommands (based on the idea in #1442), rather than declaratively?
- Would it be possible to add support for Micronaut's
@Introspected
annotation instead (somewhat similar to how Micronaut configures Jackson's ObjectMapper with support for the classes generated by the@Introspected
annotation)? Although it would still be a bit cumbersome to add these annotations, I think this might be better than using reflection. - Any other suggestions for improving this?
Thanks!
Could this be related to programmatically registering the commands and subcommands (based on the idea in Bottom-up sub-commands declaration #1442), rather than declaratively?
Yes definitely.
The annotation processor only processes the annotations. Any other relationships are not detected and will not be represented in the generated reflect.json
.
Would it be possible to add support for Micronaut's
@Introspected
annotation (...)
Recently I have very little time to spend on picocli, so if there is a workaround then let's go with that.
Looking somewhat closer at this, I seems like picocli is including @Command
-annotated classes in reflect-config.json, but fails to also add any superclasses of those command classes. Is this something that can be fixed easily?
Manually adding @ReflectiveAccess
adds these superclasses to the Micronaut-generated reflect-config.json files, allowing picocli to function correctly, but it's not ideal.
If superclasses have picocli annotations then those superclasses should also be included in the reflect.json
generated by the annotation processor. Are you saying that this is not the case?
Depends on what you mean with 'if superclasses have picocli annotations'; the class itself doesn't have any picocli annotations but the fields do. See example below.
Base class:
@ReflectiveAccess
public abstract class AbstractSessionLoginCommand<C> extends AbstractCommandWithLoginSessionHelper implements Runnable {
@ArgGroup(heading = "Optional login session name:%n", order = 1000)
@Getter protected LoginSessionNameOptions loginSessionNameOptions;
private static class LoginSessionNameOptions {
@Option(names = {"--login-session-name", "-n"}, required = false, defaultValue = "default")
@Getter protected String loginSessionName;
}
...
@Singleton @ReflectiveAccess
@SubcommandOf(SessionLoginRootCommand.class)
@Command(name = "dummy", description = "Login to MySystem", sortOptions = false)
public class MyLoginCommand extends AbstractSessionLoginCommand<MyConnectionConfig> {
@ArgGroup(exclusive = false, multiplicity = "1", heading = "Connection options:%n", order = 1)
@Getter private LoginConnectionOptions connectionOptions;
...
In the resulting jar file, META-INF/native-image/picocli-generated/reflect-config.json
contains entries for MyLoginCommand
and the appropriate inner classes defining ArgGroups. However it doesn't contain any entries for AbstractSessionLoginCommand
or its inner classes.
Current work-around is to add the @ReflectiveAccess
annotation to the base class in order to have Micronaut generate the appropriate reflection configuration, but obviously it would be much better if picocli handled this by itself.
I was able to reproduce the issue in a unit test. Investigating now...
Hmm... this may be a problem caused by incremental compilation.
In my test, if I only compile the concrete subclass, then the generated reflect-config.json
contains only entries for that class.
When I compile both the concrete subclass and the abstract superclass, the generated reflect-config.json
is correct and contains entries for both the concrete subclass and the abstract superclass. I updated the test to demonstrate this.
I am not sure how to make progress with this. Any ideas?
It's been a while since I last looked at this, but I think the problem was also present when doing a full, clean build. In my case though, the parent class was (most likely) in a separate Gradle module. So, by the time the subclass got compiled, the superclass would have been already compiled by a different javac invocation.
I'm not really familiar with all the ins and outs of Java compilation and annotation processors, so I wouldn't really know how to fix something like this. Can the annotation processor use reflection to inspect the superclass and generate the appropriate reflect-config.json
?
If the superclass is in a separate Gradle module, then one idea is to generate a separate reflect-config.json
for that module, by specifying the annotation processor for that module also.
To answer your question, yes I think it’s theoretically possible to climb the class hierarchy and inspect all child elements (and nested grandchild elements of the child elements, recursively) for picocli annotations. But that’s kind of what the annotation processor API is supposed to do for us. It appears to be a lot of work for something that should already be working: the annotation processor should already get callbacks for each picocli-annotated element in the superclass. So there’s something strange going on…
@remkop, some new information on this issue:
-
ReflectionConfigGenerator::generateReflectionConfig
seems to generate the correctreflect-config.json
(currently invoking this from a unit test in the main application module that has all other command modules declared as a dependency). - The annotation processor invoked from our Gradle build is missing a lot of entries in
reflect-config.json
For reference, the classes listed below are missing from reflect-config.json
generated by the Gradle build. It seems like this mostly affects (abstract) superclasses of command implementations, and any Mixins and ArgGroups that are referenced (only) from these superclasses. Potentially this also applies to (abstract) superclasses of Mixin and/or ArgGroup implementations. This also applies to abstract base classes located in the same module as the command implementation.
Any idea why this is happening?
-"com.fortify.cli.common.cli.cmd.AbstractFortifyCLICommand"
-"com.fortify.cli.common.cli.cmd.AbstractFortifyCLICommand$GenericOptionsArgGroup"
-"com.fortify.cli.common.cli.cmd.AbstractFortifyCLICommand$LogLevel"
-"com.fortify.cli.common.output.cli.cmd.basic.AbstractBasicOutputCommand"
-"com.fortify.cli.common.output.cli.cmd.unirest.AbstractUnirestOutputCommand"
-"com.fortify.cli.common.output.cli.mixin.BasicOutputHelperMixins$DeleteAll"
-"com.fortify.cli.common.output.cli.mixin.BasicOutputHelperMixins$Other"
-"com.fortify.cli.common.output.cli.mixin.BasicOutputHelperMixins$TableNoQuery"
-"com.fortify.cli.common.output.cli.mixin.BasicOutputHelperMixins$TableWithQuery"
-"com.fortify.cli.common.output.cli.mixin.BasicOutputHelperMixins$WaitFor"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Add"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Cancel"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Create"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Delete"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Disable"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Download"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Enable"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Get"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Import"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Install"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$List"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Other"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Set"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Start"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$TableNoQuery"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$TableWithQuery"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Uninstall"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Update"
-"com.fortify.cli.common.output.cli.mixin.UnirestOutputHelperMixins$Upload"
-"com.fortify.cli.common.output.cli.mixin.impl.OutputOptionsArgGroup"
-"com.fortify.cli.common.output.cli.mixin.impl.QueryOptionsArgGroup"
-"com.fortify.cli.common.output.cli.mixin.spi.AbstractOutputHelper"
-"com.fortify.cli.common.output.cli.mixin.spi.basic.AbstractBasicOutputHelper"
-"com.fortify.cli.common.output.cli.mixin.spi.unirest.AbstractUnirestOutputHelper"
-"com.fortify.cli.common.output.cli.mixin.writer.OutputWriterWithQueryFactoryMixin"
-"com.fortify.cli.common.output.cli.mixin.writer.StandardOutputWriterFactoryMixin"
-"com.fortify.cli.common.output.query.OutputQuery"
-"com.fortify.cli.common.output.query.OutputQueryConverter"
-"com.fortify.cli.common.output.writer.output.standard.OutputFormatConfig"
-"com.fortify.cli.common.output.writer.output.standard.OutputFormatConfigConverter"
-"com.fortify.cli.common.output.writer.output.standard.OutputFormatConfigConverter$OutputFormatIterable"
-"com.fortify.cli.common.output.writer.output.standard.VariableStoreConfig"
-"com.fortify.cli.common.output.writer.output.standard.VariableStoreConfigConverter"
-"com.fortify.cli.common.rest.cli.cmd.AbstractRestCallCommand"
-"com.fortify.cli.common.rest.cli.cmd.AbstractUnirestRunnerCommand"
-"com.fortify.cli.common.rest.cli.cmd.AbstractWaitForCommand"
-"com.fortify.cli.common.rest.cli.mixin.AbstractSimpleUnirestRunnerMixin"
-"com.fortify.cli.common.rest.cli.mixin.AbstractUnirestRunnerMixin"
-"com.fortify.cli.common.rest.cli.mixin.StandardWaitHelperProgressMonitorMixin"
-"com.fortify.cli.common.rest.cli.mixin.WaitHelperControlOptions"
-"com.fortify.cli.common.rest.cli.mixin.WaitHelperWaitOptions"
-"com.fortify.cli.common.rest.cli.mixin.WaitHelperWaitOptions$WaitHelperWaitOptionsArgGroup"
-"com.fortify.cli.common.rest.wait.WaitTimeoutAction"
-"com.fortify.cli.common.rest.wait.WaitUnknownOrFailureStateAction"
-"com.fortify.cli.common.rest.wait.WaitUnknownStateRequestedAction"
-"com.fortify.cli.common.session.cli.cmd.AbstractSessionCommand"
-"com.fortify.cli.common.session.cli.cmd.AbstractSessionListCommand"
-"com.fortify.cli.common.session.cli.cmd.AbstractSessionLoginCommand"
-"com.fortify.cli.common.session.cli.cmd.AbstractSessionLogoutCommand"
-"com.fortify.cli.common.session.cli.mixin.SessionNameMixin$AbstractSessionNameMixin"
-"com.fortify.cli.common.session.cli.mixin.SessionNameMixin$OptionalOption"
-"com.fortify.cli.common.session.cli.mixin.SessionNameMixin$OptionalOption$SessionNameArgGroup"
-"com.fortify.cli.common.session.cli.mixin.SessionNameMixin$OptionalParameter"
-"com.fortify.cli.common.session.cli.mixin.SessionNameMixin$OptionalParameter$SessionNameArgGroup"
-"com.fortify.cli.config.proxy.cli.mixin.AbstractProxyOptions"
-"com.fortify.cli.config.proxy.cli.mixin.AbstractProxyOptions$ProxyTargetHostsArgGroup"
-"com.fortify.cli.fod.app.cli.mixin.FoDAppResolverMixin$AbstractFoDAppResolverMixin"
-"com.fortify.cli.fod.app.cli.mixin.FoDAppTypeOptions$AbstractFoDAppType"
-"com.fortify.cli.fod.app.cli.mixin.FoDCriticalityTypeOptions$AbstractFoDCriticalityType"
-"com.fortify.cli.fod.app.cli.mixin.FoDSdlcStatusTypeOptions$AbstractFoDSdlcStatusType"
-"com.fortify.cli.fod.attribute.cli.mixin.FoDAttributeUpdateOptions$AbstractFoDAppAttributeUpdateMixin"
-"com.fortify.cli.fod.lookup.cli.mixin.FoDLookupTypeOptions$AbstractFoDLookupType"
-"com.fortify.cli.fod.microservice.cli.mixin.FoDAppAndMicroserviceNameResolverMixin$AbstractFoDAppAndMicroserviceNameResolverMixin"
-"com.fortify.cli.fod.microservice.cli.mixin.FoDAppMicroserviceResolverMixin$AbstractFoDAppMicroserviceResolverMixin"
-"com.fortify.cli.fod.microservice.cli.mixin.FoDAppMicroserviceUpdateOptions$AbstractFoDAppMicroserviceRenameMixin"
-"com.fortify.cli.fod.microservice.cli.mixin.FoDAppMicroserviceUpdateOptions$AbstractFoDAppMicroserviceUpdateMixin"
-"com.fortify.cli.fod.oss_scan.cli.mixin.FoDSbomFormatOptions$AbstractFoDSbomFormat"
-"com.fortify.cli.fod.output.cli.AbstractFoDOutputCommand"
-"com.fortify.cli.fod.release.cli.mixin.FoDAppAndRelNameResolverMixin$AbstractFoDAppAndRelNameResolverMixin"
-"com.fortify.cli.fod.release.cli.mixin.FoDAppMicroserviceRelResolverMixin$AbstractFoDAppMicroserviceRelResolverMixin"
-"com.fortify.cli.fod.release.cli.mixin.FoDAppRelResolverMixin$AbstractFoDAppRelResolverMixin"
-"com.fortify.cli.fod.release.cli.mixin.FoDDelimiterMixin"
-"com.fortify.cli.fod.rest.cli.mixin.FoDTimePeriodOptions$AbstractFoDTimePeriodType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDAnalysisStatusTypeOptions$AbstractFoDAnalysisStatusType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDAssessmentTypeOptions$AbstractFoDAssessmentType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDEntitlementPreferenceTypeOptions$AbstractFoDEntitlementPreferenceType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDInProgressScanActionTypeOptions$AbstractFoDEntitlementType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDRemediationScanPreferenceTypeOptions$AbstractFoDEntitlementType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDScanFormatOptions$AbstractFoDScanType"
-"com.fortify.cli.fod.scan.cli.mixin.FoDScanResolverMixin$AbstractFoDMultiScanResolverMixin"
-"com.fortify.cli.fod.scan.cli.mixin.FoDScanResolverMixin$AbstractFoDScanResolverMixin"
-"com.fortify.cli.fod.user.cli.mixin.FoDUserResolverMixin$AbstractFoDUserResolverMixin"
-"com.fortify.cli.fod.user_group.cli.mixin.FoDUserGroupResolverMixin$AbstractFoDUserGroupResolverMixin"
-"com.fortify.cli.sc_dast.output.cli.cmd.AbstractSCDastOutputCommand"
-"com.fortify.cli.sc_dast.scan.cli.cmd.AbstractSCDastScanOutputCommand"
-"com.fortify.cli.sc_dast.scan.cli.cmd.action.AbstractSCDastScanActionCommand"
-"com.fortify.cli.sc_dast.scan.cli.mixin.SCDastScanResolverMixin$AbstractSSCDastMultiScanResolverMixin"
-"com.fortify.cli.sc_dast.scan.cli.mixin.SCDastScanResolverMixin$AbstractSSCDastScanResolverMixin"
-"com.fortify.cli.sc_dast.scan_policy.cli.mixin.SCDastScanPolicyResolverMixin$AbstractSSCDastScanPolicyResolverMixin"
-"com.fortify.cli.sc_dast.scan_settings.cli.mixin.SCDastScanSettingsResolverMixin$AbstractSSCDastScanSettingsResolverMixin"
-"com.fortify.cli.sc_dast.sensor.cli.mixin.SCDastSensorResolverMixin$AbstractSSCDastSensorResolverMixin"
-"com.fortify.cli.sc_sast.output.cli.cmd.AbstractSCSastControllerOutputCommand"
-"com.fortify.cli.sc_sast.rest.cli.mixin.AbstractSCSastUnirestRunnerMixin"
-"com.fortify.cli.sc_sast.scan.cli.mixin.SCSastScanJobResolverMixin$AbstractSCSastMultiScanJobResolverMixin"
-"com.fortify.cli.sc_sast.scan.cli.mixin.SCSastScanJobResolverMixin$AbstractSCSastScanJobResolverMixin"
-"com.fortify.cli.ssc.app.cli.mixin.SSCAppResolverMixin$AbstractSSCAppResolverMixin"
-"com.fortify.cli.ssc.appversion.cli.mixin.SSCAppAndVersionNameResolverMixin$AbstractSSCAppAndVersionNameResolverMixin"
-"com.fortify.cli.ssc.appversion.cli.mixin.SSCAppVersionResolverMixin$AbstractSSCAppVersionResolverMixin"
-"com.fortify.cli.ssc.appversion.cli.mixin.SSCDelimiterMixin"
-"com.fortify.cli.ssc.appversion_artifact.cli.cmd.AbstractSSCAppVersionArtifactOutputCommand"
-"com.fortify.cli.ssc.appversion_artifact.cli.cmd.AbstractSSCAppVersionArtifactUploadCommand"
-"com.fortify.cli.ssc.appversion_artifact.cli.mixin.SSCAppVersionArtifactResolverMixin$AbstractSSCAppVersionArtifactResolverMixin"
-"com.fortify.cli.ssc.appversion_artifact.cli.mixin.SSCAppVersionArtifactResolverMixin$AbstractSSCAppVersionMultiArtifactResolverMixin"
-"com.fortify.cli.ssc.appversion_attribute.cli.mixin.SSCAppVersionAttributeUpdateMixin$AbstractSSCAppVersionAttributeUpdateMixin"
-"com.fortify.cli.ssc.appversion_filterset.cli.mixin.SSCAppVersionFilterSetResolverMixin$AbstractSSCFilterSetResolverMixin"
-"com.fortify.cli.ssc.appversion_user.cli.mixin.SSCAppVersionAuthEntityMixin$AbstractSSCAppVersionAuthEntityMixin"
-"com.fortify.cli.ssc.attribute_definition.cli.mixin.SSCAttributeDefinitionResolverMixin$AbstractSSCAttributeDefinitionResolverMixin"
-"com.fortify.cli.ssc.issue_template.cli.mixin.SSCIssueTemplateResolverMixin$AbstractSSCIssueTemplateResolverMixin"
-"com.fortify.cli.ssc.job.cli.mixin.SSCJobResolverMixin$AbstractSSCJobResolverMixin"
-"com.fortify.cli.ssc.output.cli.cmd.AbstractSSCOutputCommand"
-"com.fortify.cli.ssc.plugin.cli.mixin.SSCPluginResolverMixin$AbstractSSCPluginResolverMixin"
-"com.fortify.cli.ssc.report_template.cli.mixin.SSCReportTemplateResolverMixin$AbstractSSCReportTemplateResolverMixin"
-"com.fortify.cli.ssc.role.cli.mixin.SSCRoleResolverMixin$AbstractSSCRoleMixin"
-"com.fortify.cli.ssc.role_permission.cli.mixin.SSCRolePermissionResolverMixin$AbstractSSCRolePermissionMixin"
-"com.fortify.cli.ssc.token.cli.cmd.AbstractSSCTokenCommand"
-"com.fortify.cli.ssc.token.cli.mixin.SSCTokenCommandUrlConfigMixin"
-"com.fortify.cli.ssc.token.cli.mixin.SSCTokenCommandUrlConfigMixin$SSCUrlConfigOrSessionName"
-"com.fortify.cli.ssc.user.cli.mixin.SSCAuthEntityResolverMixin$AbstractSSCAuthEntityResolverMixin"
-"com.fortify.cli.state.variable.cli.mixin.VariableResolverMixin$AbstractRequiredVariableResolverMixin"
-"com.fortify.cli.state.variable.cli.mixin.VariableResolverMixin$AbstractVariableResolverMixin"
-"com.fortify.cli.tool.common.cli.cmd.AbstractToolInstallCommand"
-"com.fortify.cli.tool.common.cli.cmd.AbstractToolInstallCommand$DigestMismatchAction"
-"com.fortify.cli.tool.common.cli.cmd.AbstractToolListCommand"
-"com.fortify.cli.tool.common.cli.cmd.AbstractToolUninstallCommand"
Are you doing gradlew clean build
or using incremental builds?
Both clean and incremental builds show the same behavior. We normally build native binaries only from our GitHub Actions workflow, with a clean workspace, and the missing reflect-config.json
entries cause errors in those native binaries.
Are these abstract superclasses marked with the @Command
annotation?