In this demo, I will draft a cli tool with two actions:
- read a file content
- use the file content to call free HTTP API for Breaking Bad quote
This is a basic two-steps scenario which can be extended into a chain of actions to accomplish a specific tasks.
In this task, we will see:
- Dependency management by Jbang tool (lines with
//DEPS
) - Reuse source files (a response model Quote.java is defined on share directory and Jbang includes it during compiling task)
Installation:
- JBang by bash script
- IntelliJ IDEA plugin
curl -Ls https://sh.jbang.dev | bash -s - app setup
IntelliJ plugin installation:
Figure: Jbang plugin - version 0.23.0
Demo script (GitHub repo)
Script objectives:
- Develop with Java 11 SDK
- Read a file with Breaking Bad characters (file is included as characters.txt)
- Call http API for character’s quote (Breaking Bad Quote API)
- Write result to console log
Dependency management
Jbang will handle those maven dependencies for us.
//DEPS info.picocli:picocli:4.6.3
//DEPS com.konghq:unirest-java:3.14.1
//DEPS com.konghq:unirest-object-mappers-gson:3.14.1
Share class files to compiler
Jbang will include java class files under directory model. In this directory, I have a POJO class file defining response model from API
//SOURCES models
Here is the Quote.java
package models;
public class Quote {
String quote;
String author;
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = quote;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
Full script:
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS info.picocli:picocli:4.6.3
//DEPS com.konghq:unirest-java:3.14.1
//DEPS com.konghq:unirest-object-mappers-gson:3.14.1
//SOURCES models
import kong.unirest.GenericType;
import kong.unirest.Unirest;
import models.Quote;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
@Command(name = "bbquote", mixinStandardHelpOptions = true, version = "BreakingBadCli 0.1",
description = "BreakingBadCli made with jbang")
class bbquote implements Callable<Integer> {
@Parameters(index = "0", description = "input file with characters")
private Path path;
public static void main(String... args) {
int exitCode = new CommandLine(new bbquote()).execute(args);
System.exit(exitCode);
}
@Override
public Integer call() throws Exception {
var characters = Files.readAllLines(path);
characters.forEach(character -> {
var res = Unirest.get("https://api.breakingbadquotes.xyz/v1/quotes/50")
.asObject(new GenericType<List<Quote>>() {
})
.getBody();
var filteredQuote = res.stream()
.filter(item -> item.getAuthor().contains(character))
.collect(Collectors.toList());
if (filteredQuote.size() > 0) {
System.out.println(character + " once says...");
filteredQuote.forEach(quote -> System.out.println("..." + quote.getQuote()));
}
});
return 0;
}
}
Jbang usage:
Open a terminal at src/main/java then issue those commands to build and use the cli:
cd src/main/java
jbang app install bbquote.java
bbquote characters.txt
Sample output:
Jess once says...
...Hey, tell your douchebag brother-in-law to head towards the light
...You add plus a douchebag to a minus douchebag and you get, Like, Zero Douchebags.
...Fire in the hole, bitch!
...Yeah, bitch! Magnets!
...You don’t want a criminal lawyer. You want a criminal lawyer.
...Seriously? "Hello Kitty"?
...Did you just bring a bomb into a hospital?
...So roll me further bitch!
...You're my free pass... bitch!
Hank once says...
...I will put you under the jail.