Version 1.1 of JCommander is now available, here are the new features:
Type converters
By default, JCommander parses the command line into basic types only (strings, booleans, integers and longs). Very often, your application actually needs more complex types, such as files, host names, lists, etc… You can now write your own type converters by implementing the following interface:
public interface IStringConverter<T> { T convert(String value); }
For example, here is a converter that turns a string into a File:
public class FileConverter implements IStringConverter<File> { @Override public File convert(String value) { return new File(value); } }
Then, all you need to do is declare your field with the correct type and specify the converter as an attribute:
@Parameter(names = "-file", converter = FileConverter.class) File file;
JCommander ships with a few common converters (e.g. one that turns a comma separated list into a List<String>.
Simple internationalization
The new @ResourceBundle annotation lets you specify the bundle to be used on your parameter class itself. After this, JCommander will use the default locale to resolve your string:
@ResourceBundle("MessageBundle") public class ArgsI18N2 { @Parameter(names = "-host", descriptionKey = "host") String hostName; }
Password parameters
If one of your parameters is a password or some other value that you do not wish to appear in your history or in clear, you can declare it of type password and JCommander will then ask you to enter it in the console:
public class ArgsPassword { @Parameter(names = "-password", description = "Connection password", password = true) public String password; }
When you run your program, you will get the following prompt:
Value for -password (Connection password):
You will need to type the value at this point before JCommander resumes.
Installation
JCommander is available either directly or from Maven:
com.beust jcommander 1.1
#1 by Christian Gruber on July 19, 2010 - 9:38 am
Um… couldn’t you have done:
public interfaceIConverter {
O convert(I inputValue)
}
I guess they’re all string converters, I suppose. Ahh never mind.
This is awesome, though. 🙂
#2 by Cedric on July 19, 2010 - 9:42 am
Unfortunately, no: attribute values need to be constants, so all I can pass is a class, not an object, and therefore, I would have no way of specifying the value I need to pass.
I did consider:
@Parameter(converterClass = A.class, converterParams = { “a”, 1 })
This is valid as long as the parameters are constant, but I thought it was a bit overkill and maybe too limited anyway.
#3 by Christian Gruber on July 19, 2010 - 9:49 am
Yeah, that makes sense… and I think the latter is overkill. I think you found the right balance.
Pingback: Pedro Newsletter 19.07.2010 « Pragmatic Programmer Issues – pietrowski.info
#4 by Jérôme on July 19, 2010 - 1:00 pm
Hi,
Why did you call your Interface IStringConverter and not just IConverter ? Do you plan or do you see cases where input value is not a String ?
#5 by Cedric on July 19, 2010 - 1:02 pm
I thought IConverter was a bit too generic…
#6 by Jérôme on July 19, 2010 - 1:07 pm
Fair enough 😉
Anyway thx for this new lib. I’ve always been surprised that there are only few libs to do command line parameters parsing.
I mainly use Args4j but JCommander has interesting functioanlities, will give it a try.
#7 by Mohamed Mansour on July 19, 2010 - 6:24 pm
I love your contributions Cedric. Thanks for the awesome work, keep it coming!
Pingback: Random Links #229 | YASDW - yet another software developer weblog
#8 by Hristo on July 20, 2010 - 7:23 pm
Hm … did u look at args4j (https://args4j.dev.java.net/)
#9 by Jake on July 21, 2010 - 3:16 am
Been looking for solution and found it. Thanks and great code.
#10 by Joel on July 22, 2010 - 2:57 am
Hi,
Nice work, two comments although.
– 1 –
In Main parameter doc section, there should be a boolean parameter named debug instead of verbose with “Debug mode” descirption, cf.
@Parameter(names = “-debug”, description = “Debugging level”)
public Integer verbose = 1;
– 2 –
It seems parsing List is not currently supported.
running the following code raises an exception.
Am I wrong somewhere ?
public class JCommanderTes {
@Parameter
public List parameters = Lists.newArrayList();
@Parameter(names = {“-log”, “-verbose”}, description = “Level of verbosity”)
public Integer verbose = 1;
@Parameter(names = “-groups”, description = “Comma-separated list of group names to be run”)
public String groups;
@Parameter(names = “-debug”, description = “Debug mode”)
public boolean debug = false;
@Parameter(names = “-host”, description = “The host”)
public List hosts = new ArrayList();
public static void main(String[] args) {
JCommanderTes jct = new JCommanderTes();
String[] argv = {“-log”, “2”, “-groups”, “unit”, “a”, “b”, “c”, “-host”, “host2”};
new JCommander(jct, argv);
}
}
Exception in thread “main” com.beust.jcommander.ParameterException: Don’t know how to convert host2 to type interface java.util.List (field: hosts)
at com.beust.jcommander.ParameterDescription.addValue(ParameterDescription.java:113)
at com.beust.jcommander.JCommander.parseValues(JCommander.java:266)
at com.beust.jcommander.JCommander.parse(JCommander.java:108)
at com.beust.jcommander.JCommander.(JCommander.java:81)
at north.spider.tests.unit.JCommanderTes.main(JCommanderTes.java:35)
#11 by Dedrick on July 23, 2010 - 11:02 am
Hi,
In your documentation the ability to hide arguments is shown; however, it is not found in the 1.1 release and the link to the jar file for 1.2-SNAPSHOT is currently unavailable.
When will you be deploying the next release with the hidden parameter feature?
#12 by Cedric on July 23, 2010 - 11:41 am
You’re right, I published the documentation too early, sorry about that.
I’m planning to release 1.2 in the next few days, but in the meantime, you can download it at http://beust.jcommander/jcommander-1.2-SNAPSHOT.jar, or build it directly from github.
You can actually even try it from Maven, just add the following to your pom.xml:
<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
and use 1.2-SNAPSHOT as the dependency version.