Skip to main content


Setup your jPOS development environment

In this segment, we'll walk you through the essential steps to create a robust jPOS development environment. This includes installing and configuring Java, setting up Gradle as your build tool, and familiarizing yourself with the fundamental directory structure of a jPOS project. Whether you are a seasoned developer or new to the jPOS world, this guide is designed to provide you with a smooth and informative setup experience. By the end of this section, you'll have a fully prepared environment, ready for effective jPOS development.


This tutorial is structured around a central Git repository, accessible here. Every tutorial section is located within its own distinct branch.

The only tools you need to have installed are:

and even these tools are not mandatory. You have the option to download snapshots of each branch directly through your web browser, or utilize tools such as degit. Additionally, if you prefer, you can manually install the necessary Java and Gradle versions without using SDKMan.

Clone repository

git clone

At this point, your checked out branch will be main.

Set SDK Environment

jPOS requires Java and Gradle installed in your development environment.

This tutorial uses SDKMan for that, but of course, you can install them manually by other means.


We will also show you how to develop jPOS based applications using Maven, should it be your build tool of choice. However, to streamline the learning process, we kindly ask that you follow along using Gradle. Who knows, you might find yourself enjoying the experience!

Now run:

sdk env

This command will read the Java and Gradle versions from the file .sdkmanrc, that looks like this:


If the given version of Java or Gradle is not installed, the sdk env command will tell you how to run sdk install in order to get them.

After running sdk env, you can check your Java and Gradle version using the commands:

java -version && gradle --version

You will see output like this:

openjdk version "21.0.1" 2023-10-17

Gradle 8.4

Build time: 2023-10-04 20:52:13 UTC
Revision: e9251e572c9bd1d01e503a0dfdf43aedaeecdc3f

Seeking assistance

Up until this stage, the setup process is generally straightforward, and abundant resources are available from the SDKMan and Gradle communities. However, as you delve deeper into the intricacies of jPOS, keep in mind that while jPOS is a stable and robust project, these tutorials are dynamic, constantly updated to reflect the latest developments. Should you encounter any inaccuracies or unclear explanations, remember that it might not be a shortcoming on your part, but rather an aspect we need to address. We encourage you to reach out for assistance. You can connect with us via the jPOS users mailing list, our Slack and Discord channels, or directly email support at for further clarification. See the resources page for details.

Smoke Tests

In the following sections we'll explain every single line of this jPOS setup, but for the time being, let's run a couple of smoke tests:

Check Gradle Tasks


gradle tasks

And you should see a jPOS section that reads like this:

JPOS tasks
dist - Generates jPOS distribution (Tar).
distnc - Generates jPOS distribution without configuration (Tar).
installApp - Installs jPOS based application.
run - Runs a jPOS based application.
viewTests - Open a browser with the tests results
zip - Generates jPOS distribution (Zip).
zipnc - Generates jPOS distribution without configuration (Zip).

Run from Gradle

gradle run

Should show you something like this:

<log realm="Q2.system" at="2023-11-10T17:34:08.543173">
Q2 started, deployDir=/home/jpos/tutorial/build/install/tutorial/deploy, environment=default

It's uncommon for us to execute jPOS directly from Gradle. Typically, we opt for a local installation to conduct swift tests during the development phase (installApp task), or we create a complete distribution intended for deployment in other environments (dist and distnc tasks). This brief test is designed to verify that your installation has been set up correctly.

You stop the run using CTRL-C.

Build distribution

gradle dist

This will create a full distribution in the build/distributions directory. The filename will look something like this:


Content looks like this:

$ tar ztvf build/distributions/tutorial-0.0.1-SNAPSHOT.tar.gz

drwxr-xr-x 0 0 0 0 Nov 10 17:46 tutorial-0.0.1-SNAPSHOT/
drwxr-xr-x 0 0 0 0 Nov 10 15:45 tutorial-0.0.1-SNAPSHOT/bin/
-rwxr-xr-x 0 0 0 80 Nov 10 15:44 tutorial-0.0.1-SNAPSHOT/bin/start
-rwxr-xr-x 0 0 0 204 Nov 10 15:44 tutorial-0.0.1-SNAPSHOT/bin/stop
-rwxr-xr-x 0 0 0 376 Nov 10 15:44 tutorial-0.0.1-SNAPSHOT/bin/q2
drwxr-xr-x 0 0 0 0 Nov 10 15:52 tutorial-0.0.1-SNAPSHOT/deploy/
-rw-r--r-- 0 0 0 484 Nov 10 15:52 tutorial-0.0.1-SNAPSHOT/deploy/00_logger.xml
-rw-r--r-- 0 0 0 204 Nov 10 15:47 tutorial-0.0.1-SNAPSHOT/deploy/99_sysmon.xml
drwxr-xr-x 0 0 0 0 Nov 10 15:45 tutorial-0.0.1-SNAPSHOT/cfg/
-rw-r--r-- 0 0 0 0 Nov 10 15:45 tutorial-0.0.1-SNAPSHOT/cfg/default.yml
drwxr-xr-x 0 0 0 0 Nov 10 16:48 tutorial-0.0.1-SNAPSHOT/log/
-rw-r--r-- 0 0 0 0 Nov 10 16:48 tutorial-0.0.1-SNAPSHOT/log/.gitkeep
-rw-r--r-- 0 0 0 956 Nov 10 17:30 tutorial-0.0.1-SNAPSHOT/tutorial-0.0.1-SNAPSHOT.jar
drwxr-xr-x 0 0 0 0 Nov 10 17:46 tutorial-0.0.1-SNAPSHOT/lib/
-rw-r--r-- 0 0 0 1309179 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/jpos-3.0.0-SNAPSHOT.jar
-rw-r--r-- 0 0 0 475256 Jun 6 2015 tutorial-0.0.1-SNAPSHOT/lib/org.osgi.core-6.0.0.jar
-rw-r--r-- 0 0 0 331605 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/snakeyaml-1.30.jar
-rw-r--r-- 0 0 0 87144 Feb 28 2014 tutorial-0.0.1-SNAPSHOT/lib/jdbm-1.0.jar
-rw-r--r-- 0 0 0 3518946 Mar 7 2019 tutorial-0.0.1-SNAPSHOT/lib/je-18.3.12.jar
-rw-r--r-- 0 0 0 327806 Dec 8 2021 tutorial-0.0.1-SNAPSHOT/lib/jdom2-
-rw-r--r-- 0 0 0 65507 Feb 28 2014 tutorial-0.0.1-SNAPSHOT/lib/javatuples-1.2.jar
-rw-r--r-- 0 0 0 994664 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/jline-3.21.0.jar
-rw-r--r-- 0 0 0 389033 Apr 6 2017 tutorial-0.0.1-SNAPSHOT/lib/bsh-2.0b6.jar
-rw-r--r-- 0 0 0 53820 Jan 7 2019 tutorial-0.0.1-SNAPSHOT/lib/commons-cli-1.4.jar
-rw-r--r-- 0 0 0 4550214 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/bcprov-jdk15to18-1.71.jar
-rw-r--r-- 0 0 0 336712 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/bcpg-jdk14-1.71.jar
-rw-r--r-- 0 0 0 41125 Jul 21 2022 tutorial-0.0.1-SNAPSHOT/lib/slf4j-api-1.7.36.jar
-rw-r--r-- 0 0 0 173763 Mar 15 2020 tutorial-0.0.1-SNAPSHOT/lib/HdrHistogram-2.1.12.jar
-rw-r--r-- 0 0 0 4018779 Oct 31 09:41 tutorial-0.0.1-SNAPSHOT/lib/bcprov-jdk14-1.71.jar

To deploy jPOS in your target environment, such as /opt/local/jpos:

  • transfer the tarball file there.
  • unpack it with the command tar zxvf tutorial-0.0.1-SNAPSHOT.tar.gz.
  • Navigate to the extracted directory using cd /opt/local/jpos/tutorial-0.0.1, and launch jPOS by running bin/q2.

This process is typical for jPOS deployment. For a more efficient development workflow, you want to use the installApp Gradle task. This task builds the distribution and automatically extracts it into the build/install/<projectname> directory, simplifying and speeding up the development cycle.


In Gradle, you can abbreviate task names to streamline your workflow, provided that your abbreviation is unambiguous. For example, the installApp task can be shortened to iA. Thus, executing gradle iA in your terminal is equivalent to running gradle installApp. This feature is particularly useful for frequently used tasks, saving time and reducing keystrokes.

In order to generate a distribution, extract it, and run it, you can:

gradle installApp && build/install/tutoria/bin/q2

We use a handy bin/q2 script that shortens the previous command a little bit and looks like this:

exec build/install/${PWD##*/}/bin/q2 "$@"

This basically executes the q2 command available in the build/install/<projectname>/bin/q2. Here ${PWD##*/} expands to the current working directory, that usually matches the project name.

With that script at hand, building and running jPOS in the development environment is as simple as:

gradle iA && bin/q2

You can alias g=gradle and copy bin/q2 to a directory of choice within your $PATH (i.e. $HOME/bin) so you can call g iA && q2.


While the previous diagram is not technicaly correct (installApp doesn't create a tar.gz distribution, it does it on the fly), in practice, that's basically what happens when you call it.

Run Q2

We can now run bin/q2 to start Q2 in the foreground (you can stop it with `Ctrl-C``).

You can execute bin/q2 --help to view the startup options, which are displayed as follows. Each of these options will be covered in detail in later sections.

usage: Q2
-C,--config <arg> Configuration bundle
-c,--command <arg> Command to execute
-d,--deploydir <arg> Deployment directory
-e,--encrypt <arg> Encrypt configuration bundle
-E,--environment <arg> Environment name.
Can be given multiple times (applied in
order, and values may override previous
-Ed,--envdir <arg> Environment file directory, defaults to
-h,--help Usage information
-i,--cli Command Line Interface
-n,--name <arg> Optional name (defaults to 'Q2')
-Nd,--no-dynamic Disables dynamic classloader
-Ns,--no-scan Disables deploy directory scan
-p,--pid-file <arg> Store project's pid
-r,--recursive Deploy subdirectories recursively
-s,--ssh Enable SSH server
-sa,--ssh-authorized-keys <arg> Path to authorized key file (defaults
to 'cfg/authorized_keys')
-sh,--ssh-host-key-file <arg> SSH host key file, defaults to
-sp,--ssh-port <arg> SSH port (defaults to 2222)
-su,--ssh-user <arg> SSH user (defaults to 'admin')
-v,--version Q2's version

If for example you call bin/q2 --cli you'll get into jPOS' command line interface. Pressing tab will show you the available commands:

calcluhn echo license shownr sysmon version
clr env logger_benchmark shutdown tail whoami
date exit man sleep tmmon
deploy help mem smconsole tzcheck
dumpmetrics install obf ssm uptime

you can play with some commands, like env, version, shownr (show NameRegistrar), or enter a "subsystem" that are basically a group of commands that can share context. One example is the ssm (software security module). When you call it, the prompt changes from q2> to ssm> and if you press the tab key, you can see the available subcommands, e,g,:

ck     cvv    fk     gc     ik     init   ke
Understanding CLI Commands: An Early Insight into jPOS Extensibility

jPOS includes a small set of CLI (Command Line Interface) commands, offering both practical utilities and demonstrative examples. Key utilities like ssm (Software Security Module CLI) are highly functional, while others such as sysmon (SystemMonitor) and shownr (show NameRegistrar) serve as illustrative examples. The core takeaway is the extensibility of jPOS: the org.jpos.q2.cli package hosts a fully pluggable framework. This framework empowers you to craft custom CLI commands, seamlessly integrating with jPOS's comprehensive suite of components, thus enhancing the versatility and functionality of your jPOS applications.

Typical jPOS applications often interface with databases, HSMs, key vaults, and remote hosts. For specific tasks like system setup, database updates and migrations, or cryptography debugging, access to a secure, functioning system is crucial. Using standalone command line scripts for these tasks can pose security risks if they're written separately, as they need access to sensitive configurations. However, developing a CLI command within jPOS ensures that it benefits from the system's existing security measures. This approach significantly reduces the likelihood of security breaches, maintaining the integrity of your system while performing necessary operations.

Many jPOS-EE modules have their set of CLI commands and subsystems, for example, the flyway integration module has a very handy flyway command that you can use to inspect the status of the database, run a migration, etc.

You may have observed the --ssh option. This feature enables you to use SSH to connect to an active Q2 instance and access a CLI prompt for executing commands. This functionality is particularly beneficial for integrating with your administrative processes and tools like Ansible, Rundeck, and others.