Skip to main content

LogonManager Tutorial

Where to work

The code for this tutorial lives under tutorials/logon-manager. It requires the qserver tutorial running on port 10000:

# Terminal 1 — server
./gradlew :tutorials:qserver:installApp
./tutorials/qserver/build/install/qserver/bin/q2

# Terminal 2 — logon manager
./gradlew :tutorials:logon-manager:installApp
./tutorials/logon-manager/build/install/logon-manager/bin/q2

What is LogonManager?

In production ISO-8583 environments, a TCP connection to an acquirer or a switch is not immediately usable. The remote host requires a logon sequence before it will process financial transactions:

  1. Sign-On (field 70 = 001) — establishes the session.
  2. Echo test (field 70 = 301) — periodic keep-alive to prove the link is still alive.
  3. Sign-Off (field 70 = 002) — clean termination when the connection closes.

LogonManager automates this entire lifecycle on top of a QMUX. It manages one or more MUXes, each running an independent Runner thread that monitors the channel state and drives the logon/echo/logoff cycle.

Architecture

The Runner never uses an explicit timer or scheduler. Instead it relies entirely on Space TTL entries as self-expiring flags:

Space keySet whenExpires after
logon-manager.logon.<ready>.<name>Logon succeedslogon-interval (default 24h)
logon-manager.echo.<ready>.<name>Echo succeedsecho-interval (default 60s)

When either entry expires, the next loop iteration will trigger the appropriate action automatically.

XML descriptor

Add src/dist/deploy/30_logon_manager.xml:

<logon-manager class="org.jpos.tutorial.LogonManager" logger="Q2" name="logon-manager">
<property name="mux" value="upstream" />
<property name="timeout" value="30000" />
<property name="logon-interval" value="86400000" /> <!-- 24 hours -->
<property name="echo-interval" value="60000" /> <!-- 1 minute -->
<property name="initial-delay" value="1000" />

<logon>
<field id="0" value="2800" />
<field id="70" value="001" /> <!-- Sign-On -->
</logon>
<echo>
<field id="0" value="2800" />
<field id="70" value="301" /> <!-- Echo test -->
</echo>
<logoff>
<field id="0" value="2800" />
<field id="70" value="002" /> <!-- Sign-Off -->
</logoff>
</logon-manager>

Configuration reference

PropertyDefaultDescription
muxName of the QMUX to use (repeatable for multi-link setups)
timeout30000Milliseconds to wait for a response before declaring failure
logon-interval86400000How long a successful logon is valid (ms). After expiry, re-logon is triggered
echo-interval60000How long between echo requests (ms)
initial-delay1000Pause after a successful logon before starting echos

Message templates

Each of <logon>, <echo>, and <logoff> contains <field> elements. Field id="0" sets the MTI; all others set ISO fields by number. Fields 7 (datetime) and 11 (STAN) are always added automatically by buildMsg() at send time — do not include them in the template.

Deploy file ordering

The three deploy files follow the standard naming convention:

10_channel.xml         ← ChannelAdaptor  (channels:  10_xxx)
20_qmux.xml ← QMUX (muxes: 20_xxx)
30_logon_manager.xml ← LogonManager (post-mux: 30_xxx)

Build and Run

With qserver running on port 10000:

./gradlew :tutorials:logon-manager:installApp
./tutorials/logon-manager/build/install/logon-manager/bin/q2

Within the first few seconds you should see:

<log realm="logon-manager-upstream" at="...">
<info>Logon OK — upstream (session=Thu Mar 10 17:30:01 UYT 2026)</info>
</log>

Then every 60 seconds:

<log realm="logon-manager-upstream" at="...">
<info>Echo OK — upstream</info>
</log>

When you stop the process (Ctrl-C or bin/stop):

<log realm="logon-manager-upstream" at="...">
<info>Logging off upstream</info>
</log>

The next page covers the Runner loop and the reconnect behaviour in detail.