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

If a @Command-annotated method is in a class extending a @Command-annotated superclass, things break (another subcommand named [method] already exists for command [command]) #619

Closed
BeeeWall opened this issue Feb 1, 2019 · 6 comments
Milestone

Comments

@BeeeWall
Copy link

BeeeWall commented Feb 1, 2019

Example:

SuperClass.java

import picocli.CommandLine.Command;

@Command(name="super")
public class SuperClass implements Runnable {

	@Override
	public void run() {
		// TODO: Implement this method
	}
	
}

SubClass.java

import picocli.CommandLine.Command;

@Command(name="sub")
public class SubClass extends SuperClass {
	
	@Command(name="method")
	public void method() {}
}

Main.java

import picocli.CommandLine;
import picocli.CommandLine.Command;

@Command(name="main", subcommands= {SuperClass.class, SubClass.class})
public class Main implements Runnable {

	@Override
	public void run() {
		// TODO: Implement this method
	}

	public static void main(String[] args) {
		CommandLine.run(new Main(), "");
	}
}

The error

picocli.CommandLine$InitializationException: Another subcommand named 'method' already exists for command 'sub'
	at picocli.CommandLine$Model$CommandSpec.addSubcommand(CommandLine.java:3697)
	at picocli.CommandLine$Model$CommandSpec.addMethodSubcommands(CommandLine.java:3740)
	at picocli.CommandLine$Model$CommandReflection.initSubcommands(CommandLine.java:5950)
	at picocli.CommandLine$Model$CommandReflection.updateCommandAttributes(CommandLine.java:5930)
	at picocli.CommandLine$Model$CommandReflection.updateCommandAttributes(CommandLine.java:5914)
	at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:5884)
	at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:3580)
	at picocli.CommandLine.<init>(CommandLine.java:185)
	at picocli.CommandLine.toCommandLine(CommandLine.java:2254)
	at picocli.CommandLine.access$8300(CommandLine.java:142)
	at picocli.CommandLine$Model$CommandReflection.initSubcommands(CommandLine.java:5937)
	at picocli.CommandLine$Model$CommandReflection.updateCommandAttributes(CommandLine.java:5930)
	at picocli.CommandLine$Model$CommandReflection.updateCommandAttributes(CommandLine.java:5914)
	at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java:5884)
	at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java:3580)
	at picocli.CommandLine.<init>(CommandLine.java:185)
	at picocli.CommandLine.<init>(CommandLine.java:164)
	at picocli.CommandLine.run(CommandLine.java:1863)
	at picocli.CommandLine.run(CommandLine.java:1794)
	at Main.main(Main.java:13)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.aide.ui.build.java.RunJavaActivity$1.run(SourceFile:108)
	at java.lang.Thread.run(Thread.java:764)

It works if I remove the @Command annotation from SuperClass, or it works if I turn method() into a class and add it to SubClass's subcommands, but not with SuperClass being a @Command and method() being a method.

@BeeeWall
Copy link
Author

BeeeWall commented Feb 1, 2019

Oops, app screwed up and deleted my description. I've added an example now.

@BeeeWall
Copy link
Author

BeeeWall commented Feb 2, 2019

If anyone else needs to find a way around this, I figured something out. I moved the annotation from SuperClass to an inner class and added InnerClass as a mixin. Everything inherits as it should, and annotated methods work.

Edit: it does mean SuperClass probably? isn't runnable, since you can't put an annotation with a name on it. But since I was just using it for a template class rather than a real one, it works.

Edit 2: or maybe it's called a nested class? I just said inner because it's inside the other, but I think it's actually called a nested class?

@remkop remkop added this to the 3.9.4 milestone Feb 2, 2019
@remkop
Copy link
Owner

remkop commented Feb 2, 2019

Thank you reporting this! This is a bug: while walking the class hierarchy, picocli should get attributes from the superclass, including @Command methods from the superclass, but it instead of looking at the methods of the superclass, it accidentally was getting methods from its own class.

I will have a fix for this soon.

remkop added a commit that referenced this issue Feb 2, 2019
@remkop
Copy link
Owner

remkop commented Feb 2, 2019

I pushed a fix to the r3.9.x branch. There was a merge conflict when I tried to integrate this in master which I didn’t have time to resolve now. I’ll merge into master later.

remkop added a commit that referenced this issue Feb 2, 2019
@remkop
Copy link
Owner

remkop commented Feb 2, 2019

Fixed in the master branch as well as the r3.9.x branch now.
Please verify.

@remkop
Copy link
Owner

remkop commented Feb 17, 2019

Picocli 3.9.4 with a fix for this issue has been released. Enjoy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants