Setup
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.
Requirements
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:
- Git
- SdkMan
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 https://github.com/jpos/tutorial.git
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 (versions may vary):
java=23.0.x
gradle=8.xx
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 (your version may vary):
openjdk version "23" 2024-09-17
...
...
------------------------------------------------------------
Gradle 8.10.1
------------------------------------------------------------
...
...
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 jpos.org 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
Run:
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">
<info>
Q2 started, deployDir=/home/jpos/tutorial/build/install/tutorial/deploy, environment=default
</info>
</log>
...
...
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:
build/distributions/tutorial-0.0.1-SNAPSHOT.tar.gz
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-2.0.6.1.jar
-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 runningbin/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:
#!/bin/sh
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
ones)
-Ed,--envdir <arg> Environment file directory, defaults to
cfg
-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
'cfg/hostkeys.ser'
-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:
q2>
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
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 posture. 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.