From time to time each of us have to create a small console application to perform a few tedious tasks that can be automated so we can concentrate on more creative ones instead. And every time I had to build such an app I struggled with passing options via command line parameters. Instead of concentrating on implementing logic, I had to create a parser, validator and so on. And in another console application I had to do the same… again and again. But thankfully it’s over.

Thanks to small library by Cédric Beust, creator of well-known Java testing framework TestNG. This time he created JCommander with a motto Because life is too short to parse command line parameters. But enough talking, let’s sit down and write some code.

A simple use case

At the begginning assume that we have to write an application to generate a timesheet report from a given month. So simplified use case is: connect to application where all data is stored and load what everything we need. To perform this operation we need four parameters: url to the application where data is stored, authentication token and of course number of month and year. So let’s create a settings class where all this data will be stored.

and our Main application class with main() method:

But how should we pass all stuff from command line parameters to the Settings class so it is automatically initialized with these values? It’s simple!

First we have to annotate fields in Settings class using @Parameter so JCommander will know how to map parameters from command line to fields.

Annotation we’ve added looks pretty straightforward. We define name of parameter and whether it is required or not. If we do not provide a token (which is required) in command line we will get something similar to:

And in next step we have to inform JCommander which object should be initialized with data extracted from command line. It’s a simple one-liner.

And that’s all. We have simple JCommander example working and all settings passed via command line params are now initialized in Settings object.

Some additional options

Multiple values

But then we receive some new feature requests. We have to generate report for a list of projects. It can be only one project but it can be more. So how can we implement it? Nothing difficult. We add List projects to our settings class and mark it as a required parameter.

Seeing a Collection JCommander will detect that it should expect multiple values for project parameter name. And if we call our console application with something like

we will get list of these names in projectCodes field.

Input validation

If we want to validate that month parameter is between 1 and 12 we can do it easily with just one method from interface IParameterValidator. In our case it will look like show below:

and we have to declare this validator using validateWith from @Parameter annotation:

Input conversion

Sometimes we need to have one of our options mapped to something more than a simple basic type. Let’s say that in our example console application user should provide type of report output he/she wants to get. It could be console output, pdf or xls file. So in out Settings class we have a enum OutputEnum with three allowed values:

But now JCommander doesn’t know how to work with our new enum class. We need to provide a converter. So let’s create one. And again, it’s easy 🙂 We have to implement one method from IStringConverter and throw ParameterException when something is wrong.

and when converter is ready, we should inform JCommander to use it on one of fields in Settings class with converter annotation parameter.

And now settings object will be correctly initialized with OutputEnum.

Summary

That’s all. I’ve shown some most useful features of JCommander, an easy tool to make parsing command line paramters a breeze. If you want some more info, please check official JCommander website or even dive into its source code on GitHub.