• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2<html> <head>
3<title>JCommander</title>
4
5<!--
6<link rel="stylesheet" href="testng.css" type="text/css" />
7-->
8
9      <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
10      <link type="text/css" rel="stylesheet" href="http://jcommander.org/jcommander.css"  />
11      <script type="text/javascript" src="http://beust.com/prettify.js"></script>
12
13      <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
14      <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
15      <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
16      <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
17      <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
18      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
19      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
20      <script type="text/javascript" src="http://beust.com/toc.js"></script>
21      <script type="text/javascript">
22        SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
23        SyntaxHighlighter.defaults['gutter'] = false;
24        SyntaxHighlighter.all();
25      </script>
26</head>
27
28<table width="100%">
29  <tr>
30    <td align="center">
31<h1>JCommander</h1>
32<h2>Because life is too short to parse command line parameters</h2>
33<h3>
34  <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
35  <input type="hidden" name="cmd" value="_donations">
36  <input type="hidden" name="business" value="cedric@beust.com">
37  <input type="hidden" name="lc" value="US">
38  <input type="hidden" name="item_name" value="Cedric Beust">
39  <input type="hidden" name="no_note" value="0">
40  <input type="hidden" name="currency_code" value="USD">
41  <input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_LG.gif:NonHostedGuest">
42  <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
43  <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
44  </form>
45</h3>
46    </td>
47  </tr>
48  <tr>
49    <td align="right">
50      Created: July 13th, 2010
51    </td>
52  </tr>
53  <tr>
54    <td align="right">
55      Last updated: January 14th, 2015
56    </td>
57  </tr>
58  <tr><td align="right"><a href="mailto:cedric@beust.com">C&eacute;dric Beust</a></td></tr>
59</table>
60
61<h2>Table of contents</h2>
62<div id="table-of-contents">
63</div>
64
65
66
67<h2><a class="section" name="Overview">Overview</a></h2>
68
69JCommander is a very small Java framework that makes it trivial to parse command line parameters.
70<p>
71You annotate fields with descriptions of your options:
72
73<pre class="brush: java">
74import com.beust.jcommander.Parameter;
75
76public class JCommanderExample {
77  @Parameter
78  private List&lt;String&gt; parameters = new ArrayList&lt;String&gt;();
79
80  @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
81  private Integer verbose = 1;
82
83  @Parameter(names = "-groups", description = "Comma-separated list of group names to be run")
84  private String groups;
85
86  @Parameter(names = "-debug", description = "Debug mode")
87  private boolean debug = false;
88}
89</pre>
90
91and then you simply ask JCommander to parse:
92
93<pre class="brush: java">
94JCommanderExample jct = new JCommanderExample();
95String[] argv = { "-log", "2", "-groups", "unit" };
96new JCommander(jct, argv);
97
98Assert.assertEquals(jct.verbose.intValue(), 2);
99</pre>
100
101<h2><a class="section" name="Types_of_options">Types of options</a></h2>
102
103The fields representing your parameters can be of any type. Basic types (<tt>Integer</tt>, <tt>Boolean</tt/>., etc...) are supported by default and you can write type converters to support any other type (<tt>File</tt>, etc...).
104
105<h4>Boolean</h4>
106
107When a <tt>Parameter</tt> annotation is found on a field of type <tt>boolean</tt> or <tt>Boolean</tt>, JCommander interprets it as an option with an <em>arity</em> of 0:
108
109<pre class="brush: java">
110@Parameter(names = "-debug", description = "Debug mode")
111private boolean debug = false;
112</pre>
113
114Such a parameter does not require any additional parameter on the command line and if it's detected during parsing, the corresponding field will be set to <tt>true</tt>.
115
116<p>
117
118  If you want to define a boolean parameter that's <tt>true</tt> by default, you can declare it as having an arity of 1. Users will then have to specify the value they want explicitly:
119
120  <pre class="brush: java">
121    @Parameter(names = "-debug", description = "Debug mode", arity = 1)
122    private boolean debug = true;
123  </pre>
124
125  Invoke with either of:
126
127  <pre class="brush: plain">
128    program -debug true
129    program -debug false
130  </pre>
131
132<h4>String, Integer, Long</h4>
133
134When a <tt>Parameter</tt> annotation is found on a field of type <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>, <tt>Long</tt> or <tt>long</tt>, JCommander will parse the following parameter and it will attempt to cast it to the right type:
135
136<pre class="brush: java">
137@Parameter(names = "-log", description = "Level of verbosity")
138private Integer verbose = 1;
139</pre>
140
141<pre class="brush: plain">
142java Main -log 3
143</pre>
144
145will cause the field <tt>verbose</tt> to receive the value 3, however:
146
147<pre class="brush: plain">
148java Main -log test
149</pre>
150
151will cause an exception to be thrown.
152
153<h4>Lists</h4>
154
155When a <tt>Parameter</tt> annotation is found on a field of type <tt>List</tt>, JCommander will interpret it as an option that can occur multiple times:
156
157<pre class="brush: java">
158@Parameter(names = "-host", description = "The host")
159private List&lt;String&gt; hosts = new ArrayList&lt;String&gt;();
160</pre>
161
162will allow you to parse the following command line:
163
164<pre class="brush: plain">
165java Main -host host1 -verbose -host host2
166</pre>
167
168When JCommander is done parsing the line above, the field <tt>hosts</tt> will contain the strings "host1" and "host2".
169
170<h4>Password</h4>
171
172If 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 <tt>password</tt> and JCommander will then ask you to enter it in the console:
173
174<pre class="brush: java">
175public class ArgsPassword {
176  @Parameter(names = "-password", description = "Connection password", password = true)
177  private String password;
178}
179</pre>
180
181When you run your program, you will get the following prompt:
182
183<pre class="brush: plain">
184Value for -password (Connection password):
185</pre>
186
187You will need to type the value at this point before JCommander resumes.
188
189<h4>Echo Input</h4>
190
191In Java 6, by default, you will not be able to see what you type for passwords entered at the prompt (Java 5 and lower will always show the password).  However, you can override this by setting <tt>echoInput</tt> to "true" (default is "false" and this setting only has an effect when <tt>password</tt> is "true"):
192<pre class="brush: java">
193public class ArgsPassword {
194  @Parameter(names = "-password", description = "Connection password", password = true, echoInput = true)
195  private String password;
196}
197</pre>
198
199<h2><a class="section" name="Custom_types">Custom types</a></h2>
200
201<h3>By annotation</h3>
202
203By 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... To achieve this, you can write a type converter by implementing the following interface:
204
205<pre class="brush: java">
206public interface IStringConverter&lt;T&gt; {
207  T convert(String value);
208}
209</pre>
210
211For example, here is a converter that turns a string into a <tt>File</tt>:
212
213<pre class="brush: java">
214public class FileConverter implements IStringConverter&lt;File&gt; {
215  @Override
216  public File convert(String value) {
217    return new File(value);
218  }
219}
220</pre>
221
222Then, all you need to do is declare your field with the correct type and specify the converter as an attribute:
223
224<pre class="brush: java">
225@Parameter(names = "-file", converter = FileConverter.class)
226File file;
227</pre>
228
229JCommander ships with a few common converters (e.g. one that turns a comma separated list into a <tt>List&lt;String&gt;)</tt>.
230
231<h3>By factory</h3>
232
233If the custom types you use appear multiple times in your application, having to specify the converter in each annotation can become tedious. To address this, you can use an <tt>IStringConverterFactory</tt>:
234
235<pre class="brush: java">
236public interface IStringConverterFactory {
237  &lt;T&gt; Class&lt;? extends IStringConverter&lt;T&gt;&gt; getConverter(Class&lt;T&gt; forType);
238}
239</pre>
240
241For example, suppose you need to parse a string representing a host and a port:
242
243<pre class="brush: plain">
244java App -target example.com:8080
245</pre>
246
247You define the holder class :
248
249<pre class="brush: java">
250public class HostPort {
251  private String host;
252  private Integer port;
253}
254</pre>
255
256and the string converter to create instances of this class:
257
258<pre class="brush: java">
259class HostPortConverter implements IStringConverter&lt;HostPort&gt; {
260  @Override
261  public HostPort convert(String value) {
262    HostPort result = new HostPort();
263    String[] s = value.split(":");
264    result.host = s[0];
265    result.port = Integer.parseInt(s[1]);
266
267    return result;
268  }
269}
270</pre>
271
272The factory is straightforward:
273
274<pre class="brush: java">
275public class Factory implements IStringConverterFactory {
276  public Class&lt;? extends IStringConverter&lt;?&gt;&gt; getConverter(Class forType) {
277    if (forType.equals(HostPort.class)) return HostPortConverter.class;
278    else return null;
279  }
280</pre>
281
282You can now use the type <tt>HostPort</tt> as a parameter without any <tt>converterClass</tt> attribute:
283
284<pre class="brush: java">
285public class ArgsConverterFactory {
286  @Parameter(names = "-hostport")
287  private HostPort hostPort;
288}
289</pre>
290
291
292All you need to do is add the factory to your JCommander object:
293
294<pre class="brush: java">
295  ArgsConverterFactory a = new ArgsConverterFactory();
296  JCommander jc = new JCommander(a);
297  jc.addConverterFactory(new Factory());
298  jc.parse("-hostport", "example.com:8080");
299
300  Assert.assertEquals(a.hostPort.host, "example.com");
301  Assert.assertEquals(a.hostPort.port.intValue(), 8080);
302</pre>
303
304
305Another advantage of using string converter factories is that your factories can come from a dependency injection framework.
306
307<h2><a class="section" name="Parameter_validation">Parameter validation</a></h2>
308
309You can ask JCommander to perform early validation on your parameters by providing a class that implements the following interface:
310
311<pre class="brush:java">
312public interface IParameterValidator {
313 /**
314   * Validate the parameter.
315   *
316   * @param name The name of the parameter (e.g. "-host").
317   * @param value The value of the parameter that we need to validate
318   *
319   * @throws ParameterException Thrown if the value of the parameter is invalid.
320   */
321  void validate(String name, String value) throws ParameterException;
322}
323
324</pre>
325
326Here is an example implementation that will make sure that the parameter is a positive integer:
327
328<pre class="brush:java">
329public class PositiveInteger implements IParameterValidator {
330 public void validate(String name, String value)
331      throws ParameterException {
332    int n = Integer.parseInt(value);
333    if (n < 0) {
334      throw new ParameterException("Parameter " + name + " should be positive (found " + value +")");
335    }
336  }
337}
338</pre>
339
340Specify the name of a class implementing this interface in the <tt>validateWith</tt> attribute of your <tt>@Parameter</tt> annotations:
341
342<pre class="brush:java">
343@Parameter(names = "-age", validateWith = PositiveInteger.class)
344private Integer age;
345</pre>
346
347Attempting to pass a negative integer to this option will cause a <tt>ParameterException</tt> to be thrown.
348
349
350<h2><a class="section" name="Main_parameter">Main parameter</a></h2>
351So far, all the <tt>@Parameter</tt> annotations we have seen had defined an attribute called <tt>names</tt>. You can define one (and at most one) parameter without any such attribute. This parameter needs to be a <tt>List&lt;String&gt;</tt> and it will contain all the parameters that are not options:
352
353<pre class="brush: java">
354@Parameter(description = "Files")
355private List&lt;String&gt; files = new ArrayList&lt;String&gt;();
356
357@Parameter(names = "-debug", description = "Debugging level")
358private Integer debug = 1;
359</pre>
360
361will allow you to parse:
362
363<pre class="brush: plain">
364java Main -debug file1 file2
365</pre>
366
367and the field <tt>files</tt> will receive the strings "file1" and "file2".
368
369<h2><a class="section" name="Private_parameters">Private parameters</a></h2>
370
371Parameters can be private:
372
373<pre class="brush: java">
374public class ArgsPrivate {
375  @Parameter(names = "-verbose")
376  private Integer verbose = 1;
377
378  public Integer getVerbose() {
379    return verbose;
380  }
381}
382</pre>
383
384<pre class="brush: java">
385ArgsPrivate args = new ArgsPrivate();
386new JCommander(args, "-verbose", "3");
387Assert.assertEquals(args.getVerbose().intValue(), 3);
388</pre>
389
390<h2><a class="section" name="Separators">Parameter separators</a></h2>
391
392By default, parameters are separated by spaces, but you can change this setting to allow different separators:
393
394<pre class="brush: plain">
395java Main -log:3
396</pre>
397
398or
399
400<pre class="brush: plain">
401java Main -level=42
402</pre>
403
404You define the separator with the <tt>@Parameters</tt> annotation:
405
406<pre class="brush: java">
407@Parameters(separators = "=")
408public class SeparatorEqual {
409  @Parameter(names = "-level")
410  private Integer level = 2;
411}
412</pre>
413
414
415
416
417
418<h2><a class="section" name="Multiple_descriptions">Multiple descriptions</a></h2>
419
420You can spread the description of your parameters on more than one
421class. For example, you can define the following two classes:
422
423<p>
424
425<h3 class="sourcetitle">ArgsMaster.java</h3>
426<pre class="brush: java">
427public class ArgsMaster {
428  @Parameter(names = "-master")
429  private String master;
430}
431</pre>
432
433<h3 class="sourcetitle">ArgsSlave.java</h3>
434<pre class="brush: java">
435public class ArgsSlave {
436  @Parameter(names = "-slave")
437  private String slave;
438}
439</pre>
440
441and pass these two objects to JCommander:
442
443<pre class="brush: java">
444ArgsMaster m = new ArgsMaster();
445ArgsSlave s = new ArgsSlave();
446String[] argv = { "-master", "master", "-slave", "slave" };
447new JCommander(new Object[] { m , s }, argv);
448
449Assert.assertEquals(m.master, "master");
450Assert.assertEquals(s.slave, "slave");
451</pre>
452
453
454<h2><a class="section" name="Syntax">@ syntax</a></h2>
455
456JCommander supports the @ syntax, which allows you to put all your options into a file and pass this file as parameter:
457
458<p>
459
460<div class="sourcetitle">/tmp/parameters</div>
461<pre class="brush: plain">
462-verbose
463file1
464file2
465file3
466</pre>
467<pre class="brush: plain">
468java Main @/tmp/parameters
469</pre>
470
471<h2><a class="section" name="Arities">Arities (multiple values for parameters)</a></h2>
472
473<h3><a class="section" name="fixed-arities" indent="..">Fixed arities</a></h3>
474
475If some of your parameters require more than one value, such as the
476following example where two values are expected after <tt>-pairs</tt>:
477
478<pre class="brush: plain">
479java Main -pairs slave master foo.xml
480</pre>
481
482then you need to define your parameter with the <tt>arity</tt>
483attribute and make that parameter a <tt>List&lt;String&gt;</tt>:
484
485<pre class="brush: java">
486@Parameter(names = "-pairs", arity = 2, description = "Pairs")
487private List&lt;String&gt; pairs;
488</pre>
489
490You don't need to specify an arity for parameters of type
491<tt>boolean</tt> or <tt>Boolean</tt> (which have a default arity of 0)
492and of types <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>,
493<tt>Long</tt> and <tt>long</tt> (which have a default arity of 1).
494
495<p>
496Also, note that only <tt>List&lt;String&gt;</tt> is allowed for
497parameters that define an arity. You will have to convert these values
498yourself if the parameters you need are of type <tt>Integer</tt> or
499other (this limitation is due to Java's erasure).
500
501<h3><a class="section" name="variable-arities" indent="..">Variable arities</a></h3>
502
503You can specify that a parameter can receive an indefinite number of parameters, up to the next option. For example:
504
505<pre class="brush: java">
506program -foo a1 a2 a3 -bar
507program -foo a1 -bar
508</pre>
509
510Such a parameter must be of type <tt>List&lt;String&gt;</tt> and have the boolean <tt>variableArity</tt> set to <tt>true</tt>
511
512<pre class="brush: java">
513@Parameter(names = "-foo", variableArity = true)
514public List&lt;String&gt; foo = new ArrayList&lt;String&gt;();
515</pre>
516
517<h2><a class="section" name="Multiple_option_names">Multiple option names</a></h2>
518
519You can specify more than one option name:
520
521<pre class="brush: java">
522
523  @Parameter(names = { "-d", "--outputDirectory" }, description = "Directory")
524  private String outputDirectory;
525
526</pre>
527
528will allow both following syntaxes:
529
530<pre class="brush: plain">
531java Main -d /tmp
532java Main --outputDirectory /tmp
533</pre>
534
535<h2><a class="section" name="Other option configurations">Other option configurations</a></h2>
536
537You can configure how options are looked up in a few different ways:
538
539<ul>
540  <li><tt>JCommander#setCaseSensitiveOptions(boolean)</tt>: specify whether options are case sensitive. If you call this method with <tt>false</tt>, then <tt>"-param"</tt> and
541    <tt>"-PARAM"</tt> are considered equal.
542  </li>
543  <li><tt>JCommander#setAllowAbbreviatedOptions(boolean)</tt>: specify whether users can
544    pass abbreviated options. If you call this method with <tt>true</tt> then users
545    can pass <tt>"-par"</tt> to specify an option called <tt>-param</tt>. JCommander will
546    throw a <tt>ParameterException</tt> if the abbreviated name is ambiguous.
547  </li>
548</ul>
549
550<h2><a class="section" name="Required_and_optional">Required and optional parameters</a></h2>
551
552If some of your parameters are mandatory, you can use the
553<tt>required</tt> attribute (which default to <tt>false</tt>):
554
555<pre class="brush: java">
556
557  @Parameter(names = "-host", required = true)
558  private String host;
559
560</pre>
561
562If this parameter is not specified, JCommander will throw an exception
563telling you which options are missing.
564
565<h2><a class="section" name="Default_values">Default values</a></h2>
566
567The most common way to specify a default value for your parameters is to initialize the field at declaration time:
568
569<pre class="brush: java">
570private Integer logLevel = 3;
571</pre>
572
573For more complicated cases, you might want to be able to reuse identical default values across several main classes or be able to specify these default values in a centralized location such as a .properties or an XML fie. In this case, you can use an <tt>IDefaultProvider</tt>
574
575<pre class="brush: java">
576public interface IDefaultProvider {
577  /**
578   * @param optionName The name of the option as specified in the names() attribute
579   * of the @Parameter option (e.g. "-file").
580   *
581   * @return the default value for this option.
582   */
583  String getDefaultValueFor(String optionName);
584}
585</pre>
586
587By passing an implementation of this interface to your <tt>JCommander</tt> object, you can now control which default value will be used for your options. Note that the value returned by this method will then be passed to a string converter, if any is applicable, thereby allowing you to specify default values for any types you need.
588
589<p>
590
591For example, here is a default provider that will assign a default value of 42 for all your parameters except "-debug":
592
593<pre class="brush: java">
594private static final IDefaultProvider DEFAULT_PROVIDER = new IDefaultProvider() {
595  @Override
596  public String getDefaultValueFor(String optionName) {
597    return "-debug".equals(optionName) ? "false" : "42";
598  }
599};
600
601// ...
602
603JCommander jc = new JCommander(new Args());
604jc.setDefaultProvider(DEFAULT_PROVIDER);
605</pre>
606
607<h2><a class="section" name="Help_parameter">Help parameter</a></h2>
608
609If one of your parameters is used to display some help or usage, you need use the <tt>help</tt> attribute:
610
611<pre class="brush: java">
612  @Parameter(names = "--help", help = true)
613  private boolean help;
614</pre>
615
616If you omit this boolean, JCommander will instead issue an error message when it tries to validate your command and it finds that you didn't specify some of the required parameters.
617
618<h2><a class="section" name="Complex">More complex syntaxes (commands)</a></h2>
619
620Complex tools such as <tt>git</tt> or <tt>svn</tt> understand a whole set of commands, each of which with their own specific syntax:
621
622<pre class="brush: plain">
623  git commit --amend -m "Bug fix"
624</pre>
625
626Words such as "commit" above are called "commands" in JCommander, and you can specify them by creating one arg object per command:
627
628<pre class="brush: java">
629@Parameters(separators = "=", commandDescription = "Record changes to the repository")
630private class CommandCommit {
631
632  @Parameter(description = "The list of files to commit")
633  private List&lt;String&gt; files;
634
635  @Parameter(names = "--amend", description = "Amend")
636  private Boolean amend = false;
637
638  @Parameter(names = "--author")
639  private String author;
640}
641</pre>
642
643<pre class="brush: java">
644@Parameters(commandDescription = "Add file contents to the index")
645public class CommandAdd {
646
647  @Parameter(description = "File patterns to add to the index")
648  private List&lt;String&gt; patterns;
649
650  @Parameter(names = "-i")
651  private Boolean interactive = false;
652}
653</pre>
654
655Then you register these commands with your JCommander object. After the parsing phase, you call <tt>getParsedCommand()</tt> on your JCommander object, and based on the command that is returned, you know which arg object to inspect (you can still use a main arg object if you want to support options before the first command appears on the command line):
656
657<pre class="brush: java">
658CommandMain cm = new CommandMain();
659JCommander jc = new JCommander(cm);
660
661CommandAdd add = new CommandAdd();
662jc.addCommand("add", add);
663CommandCommit commit = new CommandCommit();
664jc.addCommand("commit", commit);
665
666jc.parse("-v", "commit", "--amend", "--author=cbeust", "A.java", "B.java");
667
668Assert.assertTrue(cm.verbose);
669Assert.assertEquals(jc.getParsedCommand(), "commit");
670Assert.assertTrue(commit.amend);
671Assert.assertEquals(commit.author, "cbeust");
672Assert.assertEquals(commit.files, Arrays.asList("A.java", "B.java"));
673</pre>
674
675<h2><a class="section" name="Exceptions">Exception</a></h2>
676
677Whenever JCommander detects an error, it will throw a
678<tt>ParameterException</tt>. Note that this is a Runtime Exception,
679since your application is probably not initialized correctly at this
680point.
681
682
683<h2><a class="section" name="Usage">Usage</a></h2>
684
685You can invoke <tt>usage()</tt> on the <tt>JCommander</tt> instance that you used to parse your command line in order to generate a summary of all the options that your program understands:
686
687<pre class="brush: plain">
688Usage: &lt;main class&gt; [options]
689  Options:
690    -debug          Debug mode (default: false)
691    -groups         Comma-separated list of group names to be run
692  * -log, -verbose  Level of verbosity (default: 1)
693    -long           A long number (default: 0)
694</pre>
695
696You can customize the name of your program by calling <tt>setProgramName()</tt> on your <tt>JCommander</tt> object.
697
698Options preceded by an asterisk are required.
699
700<h2><a class="section" name="Hiding">Hiding parameters</a></h2>
701
702If you don't want certain parameters to appear in the usage, you can mark them as "hidden":
703
704<pre class="brush: java">
705@Parameter(names = "-debug", description = "Debug mode", hidden = true)
706private boolean debug = false;
707</pre>
708
709<h2><a class="section" name="Internationalization">Internationalization</a></h2>
710
711You can internationalize the descriptions of your parameters.
712
713<p>
714
715First you use the <tt>@Parameters</tt> annotation at the top of your class to define the name of your message bundle, and then you use the <tt>descriptionKey</tt> attribute instead of <tt>description</tt> on all the <tt>@Parameters</tt> that require translations. This <tt>descriptionKey</tt> is the key to the string into your message bundle:
716
717<h3 class="sourcetitle">I18N.java</h3>
718<pre class="brush:java">
719@Parameters(resourceBundle = "MessageBundle")
720private class ArgsI18N2 {
721  @Parameter(names = "-host", description = "Host", descriptionKey = "host")
722  String hostName;
723}
724</pre>
725
726Your bundle needs to define this key:
727
728<br>
729
730<h3 class="sourcetitle">MessageBundle_fr_FR.properties</h3>
731<pre class="brush: plain">
732host: H&ocirc;te
733</pre>
734
735JCommander will then use the default locale to resolve your descriptions.
736
737<h2><a class="section" name="Parameter_delegates">Parameter delegates</a></h2>
738
739If you are writing many different tools in the same project, you will probably find that most of these tools can share configurations. While you can use inheritance with your objects to avoid repeating this code, the restriction to single inheritance of implementation might limit your flexibility. To address this problem, JCommander supports parameter delegates.
740
741<p>
742
743When JCommander encounters an object annotated with <tt>@ParameterDelegate</tt> in one of your objects, it acts as if this object had been added as a description object itself:
744
745<pre class="brush: java">
746class Delegate {
747  @Parameter(names = "-port")
748  private int port;
749}
750
751class MainParams {
752  @Parameter(names = "-v")
753  private boolean verbose;
754
755  @ParametersDelegate
756  private Delegate delegate = new Delegate();
757}
758</pre>
759
760The example above specifies a delegate parameter <tt>Delegate</tt> which is then referenced in <tt>MainParams</tt>. You only need to add a <tt>MainParams</tt> object to your JCommander configuration in order to use the delegate:
761
762<pre class="brush: java">
763MainParams p = new MainParams();
764new JCommander(p).parse("-v", "-port", "1234");
765Assert.assertTrue(p.isVerbose);
766Assert.assertEquals(p.delegate.port, 1234);
767</pre>
768
769<h2><a class="section" name="DynamicParameters">Dynamic parameters</a></h2>
770
771JCommander allows you to specify parameters that are not known at compile time, such as <tt>"-Da=b -Dc=d"</tt>. Such parameters are specified with the <tt><a href="apidocs/com/beust/jcommander/DynamicParameter.html">@DynamicParameter</a></tt> annotation and must be of type <tt>Map&lt;String, String&gt;</tt>. Dynamic parameters are allowed to appear multiple times on the command line:
772
773<pre class="brush: java">
774@DynamicParameter(names = "-D", description = "Dynamic parameters go here")
775private Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
776</pre>
777
778You can specify a different assignment string than <tt>=</tt> by using the attribute <tt>assignment</tt>.
779
780<h2><a class="section" name="Scala">JCommander in Scala</a></h2>
781
782Here is a quick example of how to use JCommander in Scala (courtesy of Patrick Linskey):
783
784<pre class="brush: java">
785import java.io.File
786import com.beust.jcommander.{JCommander, Parameter}
787import collection.JavaConversions._
788
789object Main {
790  object Args {
791    // Declared as var because JCommander assigns a new collection declared
792    // as java.util.List because that's what JCommander will replace it with.
793    // It'd be nice if JCommander would just use the provided List so this
794    // could be a val and a Scala LinkedList.
795    @Parameter(
796      names = Array("-f", "--file"),
797      description = "File to load. Can be specified multiple times.")
798    var file: java.util.List[String] = null
799  }
800
801  def main(args: Array[String]): Unit = {
802    new JCommander(Args, args.toArray: _*)
803    for (filename <- Args.file) {
804      val f = new File(filename)
805      printf("file: %s\n", f.getName)
806    }
807  }
808}
809</pre>
810
811<h2><a class="section" name="Groovy">JCommander in Groovy</a></h2>
812
813Here is a quick example of how to use JCommander in Groovy (courtesy of Paul King):
814
815
816<pre class="brush: java">
817import com.beust.jcommander.*
818
819class Args {
820  @Parameter(names = ["-f", "--file"], description = "File to load. Can be specified multiple times.")
821  List&lt;String&gt; file
822}
823
824new Args().with {
825  new JCommander(it, args)
826  file.each { println "file: ${new File(it).name}" }
827}
828</pre>
829
830<h2><a class="section" name="More_examples">More examples</a></h2>
831
832TestNG uses JCommander to parse its own command line, here is <a href="http://github.com/cbeust/testng/blob/master/src/main/java/org/testng/CommandLineArgs.java">its definition file</a>.
833
834<h2><a class="section" name="Mailing_list">Mailing list</a></h2>
835
836Join the <a href="http://groups.google.com/group/jcommander">JCommander Google group</a> if you are interested in discussions about JCommander.
837
838<h2><a class="section" name="Javadocs">Javadocs</a></h2>
839
840The Javadocs for JCommander can be found <a href="apidocs/">here</a>.
841
842<h2><a class="section" name="License">License</a></h2>
843
844JCommander is released under the <a
845href="https://github.com/cbeust/jcommander/blob/master/license.txt">Apache 2.0</a> license.
846
847<h2><a class="section" name="Download">Download</a></h2>
848
849You can download JCommander from the following locations:
850
851<ul>
852  <li><a href="http://github.com/cbeust/jcommander">Source on github</a></li>
853  <li>If you are using Maven, add the following dependency to your <tt>pom.xml</tt>:
854
855  <pre class="brush: xml">
856
857<dependency>
858  &lt;groupId&gt;com.beust&lt;/groupId&gt;
859  &lt;artifactId&gt;jcommander&lt;/artifactId&gt;
860  &lt;version&gt;1.30&lt;/version&gt;
861</dependency>
862  </pre>
863
864</ul>
865
866</body>
867
868<script type="text/javascript" src="http://beust.com/toc.js"></script>
869<script type="text/javascript"> generateToc(); </script>
870
871</html>
872