LogonManager Tutorial
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:
- Sign-On (field 70 =
001) — establishes the session. - Echo test (field 70 =
301) — periodic keep-alive to prove the link is still alive. - 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 key | Set when | Expires after |
|---|---|---|
logon-manager.logon.<ready>.<name> | Logon succeeds | logon-interval (default 24h) |
logon-manager.echo.<ready>.<name> | Echo succeeds | echo-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
| Property | Default | Description |
|---|---|---|
mux | — | Name of the QMUX to use (repeatable for multi-link setups) |
timeout | 30000 | Milliseconds to wait for a response before declaring failure |
logon-interval | 86400000 | How long a successful logon is valid (ms). After expiry, re-logon is triggered |
echo-interval | 60000 | How long between echo requests (ms) |
initial-delay | 1000 | Pause 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.