Create an spring-boot command-line java application compatible with Windows/Linux/Mac
Published on

Create an spring-boot command-line java application compatible with Windows/Linux/Mac

Authors

Creating a spring-boot command-line java application

Typically, when creating an executable spring boot application, we'll need to add the following to the pom.xml file. The configuration and mainClass are essential, as they will tell the maven about the class that we want to run.

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <mainClass>com.codingjump.App</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

It's always good to use spring-boot-starter-parent, as you don't need to worry about the versions for dependencies, as it will take care of it.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.6.4</version>
</parent>

So your pom.xml file should look like this; please update the application details per your requirement in the lines highlighted below.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.codingjump</groupId>
  <artifactId>command-line-app</artifactId>
  <version>1.0</version>

  <name>command-line-app</name>
  <url>https://www.codingjump.com</url>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.4</version>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <configuration>
            <mainClass>com.codingjump.App</mainClass>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
App.java
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("Hello World!");
        // Your code here
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

If you want your command-line application to be a single file, it would be best to create a JAR file with all the dependencies. This is the best way to make an executable JAR file in Spring Boot.

mvn package spring-boot:repackage

This command will create a JAR file with all the dependencies in the Target folder.

To run this JAR file, you'll need to run it in bash or command prompt or any other shell-like below:

  java -jar target/command-line-app-1.0-SNAPSHOT.jar

So now, in any operating system, you can run this JAR file with the same command; it will work without any issue. But if you want this executable JAR file to be run from anywhere. You can do this by adding the following to your .bashrc or .zshrc file.

  export PATH=$PATH:~/Downloads/command-line-app-1.0-SNAPSHOT.jar

If on windows, you can do this by adding the following to your user environment variable PATH.

  setx PATH=%PATH%;~/Downloads/command-line-app-1.0-SNAPSHOT.jar

Even after adding to your PATH variable, you'll still need to type this long command to run the JAR file, which doesn't look like a friendly command-line tool.

$ java -jar command-line-app-1.0-SNAPSHOT.jar

Wrapper BAT/SH files for executable JAR

For running your executable JAR file, you can use a wrapper file, i.e., a batch file or a shell script. For the user, it will look like he is running a command-line tool, but it is running the JAR file.

Windows Wrapper BAT file

Let's say you create a batch file with the name your-app.bat, then the user can run it by typing this command: your-app

your-app.bat
@ECHO OFF
java -jar %~command-line-app-1.0.jar %*

Here %~dp0 provides the current directory where the batch file is located.

As you'd be running this command-line exe in different folders/paths, %~dp0 will provide the correct path to command-line-app-1.0.jar. Likewise, %* will pass on all the command line arguments to your JAR file.

Mac OS / Linux Wrapper SH file

For the Mac OS and Linux, it's a little bit more complicated, but still, you can achieve the same results.

Let's say we create a shell script with the name your-app.sh, then the user can run it by typing this command: your-app

your-app.sh
#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
java -jar $BASEDIR/command-line-app-1.0.jar $*

Likewise, $BASEDIR will provide the current directory where the shell script is located. And $* will pass on all the command line arguments to your JAR file.

You'll still need to call using the your-app.sh command to run the JAR file even after doing this.

To skip the .sh extension, you have to update your .bashrc or .zshrc file with an alias.

alias your-app='your-app.sh'

Now you can use the your-app command to run the JAR file in your shell.

Using Apache Commons CLI for command line arguments

As you're creating a spring-boot command-line application for taking arguments from the command line, you can use commons-cli library, which is maintained by Apache.

You'll need to add the below into your pom.xml file dependencies.

<dependency>
  <groupId>commons-cli</groupId>
  <artifactId>commons-cli</artifactId>
  <version>1.5.0</version>
</dependency>

In your main class, you can use the following code to take the arguments from the command line.

App.java
public class App {
  public static void main(String[] args) {
    options = new Options();

    CommandLineParser parser = new DefaultParser();
    CommandLine cmd;

    options.addOption(/* short option format */ "o", /* long option format */ "your-option",  /* true means argument required, otherwise false */ true, "Description of your option");
    cmd = parser.parse(options, args);

    String yourOption = cmd.getOptionValue("your-option");

    System.out.println(yourOption); // Prints your option value
  }
}

Here is an example of how you can use the above option in the command line.

> java App -o "Hello World!"
Hello World!

Get the user directory path in java

Sometimes you'd want to get the path from which the user runs the command-line tool. For example, you might want to use this path for reading/writing files, etc. In Java, you can use the following code to get the user directory path.

System.getProperty("user.dir");

The above code work on both Windows and Mac OS.

Conclusion

Hope this article helped you to get started with building Spring Boot command-line application. Let me know if you have any questions or updates. I'd love to hear from you.