1

At the moment I'm wrangling with an existing Java project, my goal is to create a command line interface for passing arguments to it, to "run" it, so to speak.

I'm using the Apache commons cli library, like so:

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class CommandLineParameters {

  public static void main(String[] args) {
    CommandLineParser parser = new DefaultParser();
    Options options = new Options();

    options.addOption("a", "abc", true, "First Parameter");
    options.addOption("x", "xyz", true, "Second Parameter");
    options.addOption("h", "help", false, "Shows this Help");

    try {
      CommandLine commandLine = parser.parse(options, args);

      System.out.println(commandLine.getOptionValue("a"));
      System.out.println(commandLine.getOptionValue("x"));

      if (commandLine.hasOption("h")) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("CommandLineParameters", options);
      }

    } catch (ParseException e) {
      e.printStackTrace();
    }
  }
}

In Eclipse I can run this by modifying the Arguments passed to the Run Configurations..., however, what I would in fact like to do is, to be able to run this programme from a terminal shell, in an analogous way to "normal" terminal programmes such as grep, or ipconfig.

How can this be achieved using Java?

NOTE: I'm not trying to compile/build this programme from the command line, I'm trying to make an interface to the program in the command line.

12
  • 1
    If your asking about the command line syntax itself, the commands are java and javaw and they're described on the documentation page. Commented Dec 23, 2017 at 18:43
  • 5
    Your "note" makes no sense. You might want to give an example of "the program" and how you're trying to call it now. I suspect a big XY problem here. Commented Dec 23, 2017 at 18:46
  • 2
    You'd need to create a shell script to do that, so the answer depends on your operating system. Commented Dec 23, 2017 at 19:19
  • 1
    The idea is that you call the shell script, that then starts the JVM with your program and passes on the arguments. Commented Dec 23, 2017 at 19:22
  • 1
    No I mean you create a separate script that simply contains the command for running your program, and then you can put that script in your path variable (e.g. using your bash profile) Commented Dec 23, 2017 at 19:26

4 Answers 4

7

The provided answers describe how to build a jar that can be executed using java -jar command. The following article explains how to take such an 'executable' jar and convert it to a 'program' file executable by sh (so it can be invoked with ./program and not with java -jar program.jar): https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable

The idea is that a zip archive (and a jar is basically a flavor of a zip archive) may have an arbitrary prologue. The prologue is everything from the beginning of a file till zip file signature (4 characters, first two of which are 'PK'). When java reads a jar archive, it skips that prologue (everything before the signature).

So from the point of view of java, such a jar will be a valid jar. But if that prologue is a shell script, such a jar will also be a file that you can execute using a shell interpreter.

That means that you can prepend usual jar content with a shell script that will just invoke that java -jar with that same jar archive as an argument. And java will happily execute that jar ignoring the prologue.

The prologue in the article looks like this:

#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
    java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -jar $MYSELF "$@"
exit 1

It looks for java and starts it with the needed parameters. This is just an example, you can tune the algorithm used to find java command to make it suit your needs.

And the resulting file will consist of the concatenation of this launcher shell script and that jar file (containing main class and manifest) that should be run using java -jar.

Sign up to request clarification or add additional context in comments.

2 Comments

Is this solution cross-platform or OS dependent?
It relies on a shell script, so, technically, it won't work in pure Windows
1

I think your better option is to rewrite the other main method of the existing program to accept CLI args, but if you want to do so, either way, you need to compile the program to a class or jar file

And you run it like any other Java program from the CLI, but give it arguments like -h here. Note: you'll need to include a classpath for Apache Commons here.

java - cp <classpath> fully.qualified.CommandLineParameters -h

Or, if you have a JAR with a Main class attribute in its manifest and also includes Apache Commons (via an uber jar), there's no need to set the class name or classpath. Still, give the arguments, though

java -jar jarFile.jar -h

I want it to be an independent programme, accessed from the command line, such as ls

Open your bashrc and put in an alias or function. The fact of the matter is, you must invoke java, or you can use a different JVM scripting language like Groovy

$ cat my-ls
#!/usr/bin/env groovy 
println "Run my other program"
$ chmod +x my-ls

$ ./my-ls
Run my other program

2 Comments

that's not what I mean. I want it to be an independent programme, accessed from the command line, such as ls
Then java is the wrong programming language to use... Or you simply make an alias
0

That sure is possible. After parsing the parameters you can read from System.in and write to System.out. Here a very simple sample to convert input to uppercase - incomplete (error handling and such), just to show how to start:

package sf;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Sample {

    public static void main(String[] args) {
        processArguments(args);
        try {
            processInput(System.in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void processArguments(String[] args) {
        // whatever
    }

    private static void processInput(InputStream in) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line.toUpperCase());
        }
        in.close();
    }
}

and to execute it just use type like

java sf.Sample -a <input.txt >out.txt

the directory containing the sf directory where the Sample.class is located must be in the CLASSPATH or you must use the -cp option to the java command: How Classes are Found.

4 Comments

that's not what I mean. I want it to be an independent programme, accessed from the command line, such as ls
@s.matthew.english You mean you don't want to type "java -jar"? I'm not sure that's possible, you have to invoke the JVM interpreter.
I just want it to be a normal programme that can be called from the command line- it must be possible
@s.matthew.english "Normal programm"? You probably mean binary executable or a Shell-script. You can build a simple shell script with java -jar CommandLineParameters.jar --param1 -param2 ... If you will check the command line parameters then has this script more as one line. You asked for "How can this be achieved using Java?" - you have the answer
0

you should create an executable jar from your java code:

  1. In Eclipse Right click on your main file
  2. Choice Export->excecutable jar file
  3. fill out the form. Take for "Launch configuration" your running configuration from your test

Start your application from command line:

java -jar CommandLineParameters.jar --param1 -param2 ...

2 Comments

is there some way that I can add this jar to my path inside of my bash profile and then just call it from the terminal noramally as I can with ls or grep?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.