Grails Goodness: Creating A Fully Executable Jar
With Grails 3 we can create a so-called fat jar or war file.
To run our application we only have to use java -jar
followed by our archive file name and the application starts.
Another option is to create a fully executable jar or war file, which adds a shell script in front of the jar or war file so we can immediately run the jar or war file.
We don't have to use java -jar
anymore to run our Grails application.
The fully executable JAR file can only run on Unix-like systems and it is ready to be used as service using init.d
or systemd
.
To create a fully executable jar file for our Grails application we must add the following lines to our build.gradle
file:
// File: build.gradle
...
// Disable war plugin to create a jar file
// otherwise a fully executable war file
// is created.
//apply plugin: 'war'
...
springBoot {
// Enable the creation of a fully
// executable archive file.
executable = true
}
Next we execute the Gradle assemble
task to create the fully executable archive:
grails> assemble
...
:compileGroovyPages
:jar
:bootRepackage
:assemble
BUILD SUCCESSFUL
Total time: 5.619 secs
| Built application to build/libs using environment: production
grails>
We can find the executable archive file in the build/libs
directory.
Suppose our Grails application is called grails-full-executable-jar
and has version 0.1
we can execute the jar file grails-full-executable-jar-0.1.jar
:
$ cd build/libs
$ ./grails-full-executable-jar-0.1.jar
Grails application running at http://localhost:8080 in environment: production
The launch script that is prepended to the archive file can be changed by defining a new launch script with the springBoot
property embeddedLaunchScript
.
The default launch script that is used has some variable placeholders we can change using the embeddedLaunchScriptProperties
property.
For example the launch script can determine if the script is used to run the application standalone or as a Linux/Unix service and will act accordingly.
We can also set the mode
property to service
so it will always act like a Linux/Unix service.
Furthermore we can set some meta information for the launch script with several properties.
To learn more about the different options see the Spring Boot documentation.
// File: build.gradle
...
springBoot {
// Enable the creation of a fully
// executable archive file.
executable = true
// Set values for variable placeholders
// in the default launch script.
embeddedLaunchScriptProperties =
[initInfoDescription: project.description,
initInfoShortDescription: project.name,
initInfoProvides: jar.baseName,
mode: 'service']
}
After we have recreated the archive file we can check the launch script that is created:
$ head -n 55 build/libs/grails-full-executable-jar-0.1.jar
#!/bin/bash
#
# . _ _ _ _ _
# / / _'_ _ _ _(_)_ _ _ _ \ \ \
# ( ( )\_ | '_ | '_| | '_ \/ _\` | \ \ \ \
# \\/ _)| |_)| | | | | || (_| | ) ) ) )
# ' |_| ._|_| |_|_| |_\_, | / / / /
# =========|_|==============|_/=/_/_/_/
# :: Spring Boot Startup Script ::
#
### BEGIN INIT INFO
# Provides: grails-full-executable-jar
# Required-Start: $remote\_fs $syslog $network
# Required-Stop: $remote\_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: grails-full-executable-jar
# Description: Sample Grails Application
# chkconfig: 2345 99 01
### END INIT INFO
[[ -n "$DEBUG" ]] && set -x
# Initialize variables that cannot be provided by a .conf file
WORKING_DIR="$(pwd)"
# shellcheck disable=SC2153
[[ -n "$JARFILE" ]] && jarfile="$JARFILE"
[[ -n "$APP_NAME" ]] && identity="$APP_NAME"
# Follow symlinks to find the real jar and detect init.d script
cd "$(dirname "$0")" || exit 1
[[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0")
while [[ -L "$jarfile" ]]; do
[[ "$jarfile" =~ init.d ]] && init_script=$(basename "$jarfile")
jarfile=$(readlink "$jarfile")
cd "$(dirname "$jarfile")" || exit 1
jarfile=$(pwd)/$(basename "$jarfile")
done
jarfolder="$(dirname "$jarfile")"
cd "$WORKING_DIR" || exit 1
# Source any config file
configfile="$(basename "${jarfile%.*}.conf")"
# shellcheck source=/dev/null
[[ -r "${jarfolder}/${configfile}" ]] && source "${jarfolder}/${configfile}"
# Initialize PID/LOG locations if they weren't provided by the config file
[[ -z "$PID_FOLDER" ]] && PID_FOLDER="/var/run"
[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="/var/log"
! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp"
! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp"
# Set up defaults
[[ -z "$MODE" ]] && MODE="service" # modes are "auto", "service" or "run"
$ cd build/libs
$ ./grails-full-executable-jar.0.1.jar
Usage: ./grails-full-executable-jar-0.1.jar {start|stop|restart|force-reload|status|run}
$
Written with Grails 3.1.8.