Skip to content

Code: Java‐based Tooling

Michaela Iorga edited this page Feb 2, 2024 · 1 revision

Java-based Tooling

How do I invoke Java dependencies directly from a pom.xml file?

In several places across our stack we make use of Java-based tooling such as Saxon and Calabash. The version of these tools can be pinned using POM files, such as the one present in the build/ directory. Below is a simple template script that can be used to invoke a Java dependency directly from a POM file.

#!/usr/bin/env bash

# Fail early if an error occurs
set -Eeuo pipefail

if ! [ -x "$(command -v mvn)" ]; then
  echo 'Error: Maven (mvn) is not in the PATH, is it installed?' >&2
  exit 1
fi

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
OSCAL_DIR="${SCRIPT_DIR}/../../../.." # Edit this to resolve to the OSCAL root from the script's directory
POM_FILE="${OSCAL_DIR}/build/pom.xml"
# Grab any additional files relative to the root OSCAL directory (like stylesheets)

MAIN_CLASS="net.sf.saxon.Transform" #edit this to target your application's main class. below are a few examples:
# XML Calabash: "com.xmlcalabash.drivers.Main"
# Saxon: "net.sf.saxon.Transform"

# Perform any argument processing here, such as preselecting stylesheets in Saxon, etc.
# Note here "${*// /\\ }" is a shell expansion that escapes spaces within arguments.
# For more information, see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
ARGS=${*// /\\ }

mvn \
    -f "$POM_FILE" \
    exec:java \
    -Dexec.mainClass="$MAIN_CLASS" \
    -Dexec.args="$ARGS"

Note that this template is often extended to parse arguments directly. See an example of this in the profile resolution Saxon wrapper.

This approach has several key advantages:

  1. The script can refer to resources invariably to the user's current working directory, making it more portable.
  2. The user does not have to worry about downloading, copying, or otherwise managing any of the Java dependencies.
  3. A lot of the complexity of consuming stylesheets and other operations can be hidden from the user, making our stack more approachable.