A simple command-line argument parser for Java applications that relies on records.

Overview

RecordArgs

A simple command-line argument parser for Java applications that relies on records. Specifically, it uses their component names to parse command line arguments, their canonical constructors to create instances, and their immutability to let you freely pass them around without fear of unwanted changes.

Getting started

  1. Create a record like this one:
    record ServerArgs(String url, int port) { }
  2. Make the record public and export its package or keep it encapsulated and open the package (optionally just to dev.nipafx.args).
  3. Pass command-line arguments in this form:
    java [...] --url localhost --port 8080
    
  4. Call Args:
    public static void main(String[] args) throws ArgsException {
    	ServerArgs serverArgs = Args.parse(args, ServerArgs.class);
    }

In most cases, the passed arguments must alternative between an argument's name (prefixed by --) and its value. A value must be defined for all arguments that aren't of a container type (see below).

Argument names

The arg record's component names define the argument names. So for a record like the following ...

record ServerArgs(String url, int port) { }

... the arguments --url and --port are parsed.

Simple arguments

An argument name must in most cases be followed by exactly one value that can be parsed to the argument's type. Supported simple types are:

  • String, Path
  • Integer, int, Long, long
  • Float, float, Double, double
  • Boolean, boolean (only values "true" and "false")

Boolean arguments

The boolean types are an exception to the rule that an argument name must always be followed by a type. If no value is given, true is assumed.

For example, in this situation ...

record ServerArgs(String url, boolean createLog) { }

... the following arguments could be parsed ...

java [...] --url localhost:8080 --createLog
java [...] --createLog --url localhost:8080

... and serverArgs.createLog() would return true.

Container arguments

Beyond that, the following container types are supported:

  • Optional<VALUE>, where VALUE is any of the simple types above (but no OptionalInt, OptionalLong, OptionalDouble)
  • List<VALUE>, where VALUE is any of the simple types above
  • Map<KEY, VALUE>, where KEY and VALUE are any of the simple types above

Container types are always optional.

Optional arguments

Arguments of type Optional are optional (talk about good naming!). Given the following command ...

java [...] --url localhost

... this arg record would lead to an exception during parsing because port wasn't defined:

record ServerArgs(String url, int port) { }

To allow port to be optional, use Optional:

record ServerArgs(String url, Optional<Integer> port) { }

List arguments

Arguments of type List accept one or more arguments. If not mentioned, they are empty, which makes them optional as well. That means for the following arg record ...

record ServerArgs(List<String> urls, boolean createLog) { }

... any of the following command lines are acceptable:

java [...] --createLog
java [...] --createLog --urls localhost
java [...] --createLog --urls localhost 127.0.0.1
java [...] --urls localhost 127.0.0.1 --createLog

While just mentioning a list argument without providing a value ...

java [...] --urls --createLog

... could be parsed to the empty list, this non-sensical command is instead interpreted as a mistake and leads to an exception.

Map arguments

Arguments of type Map accept one or more key-value pair of the form key=value. If not mentioned, they are empty, which makes them optional as well. That means for the following arg record ...

record ServerArgs(Map<Integer, String> numbers, boolean createLog) { }

... any of the following command lines are acceptable:

java [...] --createLog
java [...] --createLog --numbers 1=one
java [...] --createLog --numbers 1=one 2=two 3=three
java [...] --numbers 1=one 2=two 3=three --createLog

While just mentioning a map argument without providing a value ...

java [...] --numbers --createLog

... could be parsed to the empty map, this non-sensical command is instead interpreted as a mistake and leads to an exception.

Comments
  • Allow multiple args records

    Allow multiple args records

    At the moment, Args.parse accepts a single type and returns an instance of it. Instead, it could accept several types and return one instance for each. This would benefit applications with many arguments or apps/frameworks with a desire to split responsibilities for args between different parts of the code.

    enhancement 
    opened by nipafx 2
  • Allow collection arguments

    Allow collection arguments

    Allow multiple values in a sequence to be assigned to the same argument, which would hence have to be of a collection type. List is obvious, Set would be possible as well (would that entail silently dropping duplicate entries?) - Map would be interesting (is each value a key-value pair that is split by =?).

    enhancement 
    opened by nipafx 0
  • Create single-letter abbreviations for options

    Create single-letter abbreviations for options

    Instead of requiring users to specify with --argName, use the first letter for an abbreviated option like -a. Unlike field names, their abbreviations can collide, though, so something needs to be figured out there (next upper-case letter if exists; otherwise next letter?). It could also be helpful to allow chaining multiple boolean abbreviates to activate them all, e.g. -abc to set boolean arg, boolean beta, and boolean canopy to true.

    enhancement 
    opened by nipafx 0
  • Use MethodHandles.Lookup for reflection

    Use MethodHandles.Lookup for reflection

    Instead of (implicitly) requiring the user to open the package containing the record for reflection, make them pass MethodHandles.Lookup, which is much more reliable.

    bug 
    opened by nipafx 0
  • Catch and wrap constructor exception

    Catch and wrap constructor exception

    By catching exceptions thrown by the constructor and rethrowing that with a library-specific exception, developers can verify input in the constructor and easily surface problems to the user by outputting their exception's message.

    ArgsException should probably be renamed to, e.g., ArgsParseException.

    enhancement 
    opened by nipafx 0
Owner
Nicolai Parlog
Nicolai is a Java enthusiast with a passion for learning and sharing. He's a Java Developer Advocate at Oracle and organizer of Accento.
Nicolai Parlog
Some utility classes around java records

record-util Some utility classes around java records On the menu MapTrait Transform any record to a java.util.Map just by implementing the interface M

Rémi Forax 32 Apr 6, 2022
JavaOTTF - Official OTTF parser and composer for JVM languages

JavaOTTF Official OTTF parser and composer for JVM languages. Documentation Please refer to the Wiki Section. Installation Maven Add repository into p

Open Timetable 2 Nov 21, 2022
JDK main-line development

Welcome to the JDK! For build instructions please see the online documentation, or either of these files: doc/building.html (html version) doc/buildin

OpenJDK 14.8k Dec 29, 2022
💥 Crasher - open source dump/crash server for different programming languages (used for crash analysis in various applications)

Crashser Crasher - open source dump/crash server for different programming languages (used for crash analysis in various applications). Supported lang

Balun Vladimir 14 Oct 6, 2022
A gradle plugin for developing javaagent applications.

Javaagent Packing A gradle plugin for developing javaagent applications. Why this plugin Fast packing all dependencies Used many dependencies? Javaage

微莹·纤绫 0 May 13, 2022
Simple JVM Profiler Using StatsD and Other Metrics Backends

statsd-jvm-profiler statsd-jvm-profiler is a JVM agent profiler that sends profiling data to StatsD. Inspired by riemann-jvm-profiler, it was primaril

Etsy, Inc. 330 Oct 30, 2022
Simple Anti-Dump to slow down and annoy attackers.

Anti-Dump A simple Anti-Dump to slow down and annoy attackers. Usage Copy the class into your mod or loader. Rename any instances of dummy/class/path

null 47 Dec 25, 2022
Simple, Scalable. Trace-Recorder is a trace recorder.

Trace-Recorder It's Scalable. Simple, Scalable, High-Powered. Trace-Recorder is a trace recorder, mainly in order to better record the source code flo

WangCai 40 Dec 24, 2022
One file java script for visualizing JDK flight recorder execution logs as flamegraphs without any dependencies except Java and a browser.

Flamegraph from JFR logs Simple one file Java script to generate flamegraphs from Java flight recordings without installing Perl and the Brendan Gregg

Billy Sjöberg 17 Oct 2, 2022
JVM Explorer is a Java desktop application for browsing loaded class files inside locally running Java Virtual Machines.

JVM Explorer JVM Explorer is a Java desktop application for browsing loaded class files inside locally running Java Virtual Machines. Features Browse

null 109 Nov 30, 2022
A Java agent that rewrites bytecode to instrument allocation sites

The Allocation Instrumenter is a Java agent written using the java.lang.instrument API and ASM. Each allocation in your Java program is instrumented;

Google 438 Dec 19, 2022
Java memory allocation profiler

Aprof - Java Memory Allocation Profiler What is it? The Aprof project is a Java Memory Allocation Profiler with very low performance impact on profile

Devexperts 211 Dec 15, 2022
Sampling CPU and HEAP profiler for Java featuring AsyncGetCallTrace + perf_events

async-profiler This project is a low overhead sampling profiler for Java that does not suffer from Safepoint bias problem. It features HotSpot-specifi

null 5.8k Jan 3, 2023
BTrace - a safe, dynamic tracing tool for the Java platform

btrace A safe, dynamic tracing tool for the Java platform Version 2.1.0 Quick Summary BTrace is a safe, dynamic tracing tool for the Java platform. BT

btrace.io 5.3k Jan 9, 2023
Fork of tagtraum industries' GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Sun's / Oracle's java 1.6+ garbage collector logs (including G1 collector)

GCViewer 1.36 GCViewer is a little tool that visualizes verbose GC output generated by Sun / Oracle, IBM, HP and BEA Java Virtual Machines. It is free

null 4.1k Jan 4, 2023
Java Agent for Memory Measurements

Overview Jamm provides MemoryMeter, a Java agent for all Java versions to measure actual object memory use including JVM overhead. Use To use MemoryMe

Jonathan Ellis 624 Dec 28, 2022
Get Method Sampling from Java Flight Recorder Dump and convert to FlameGraph compatible format.

Note: Travis has removed the support for Oracle JDK 8. Therefore the build status is removed temporarily. Converting JFR Method Profiling Samples to F

M. Isuru Tharanga Chrishantha Perera 248 Dec 16, 2022
Tool for creating reports from Java Flight Recorder dumps

jfr-report-tool Tool for creating reports from Java Flight Recorder dumps. Influenced by https://github.com/chrishantha/jfr-flame-graph . Kudos to @ch

Lari Hotari 50 Oct 28, 2022
Log analyser / visualiser for Java HotSpot JIT compiler. Inspect inlining decisions, hot methods, bytecode, and assembly. View results in the JavaFX user interface.

JITWatch Log analyser and visualiser for the HotSpot JIT compiler. Video introduction to JITWatch video Slides from my LJC lightning talk on JITWatch

AdoptOpenJDK 2.8k Jan 3, 2023