QServer Tutorial
Let's write a simple QServer with a 0800 auto-responder.
Add QServer XML descriptor
In src/dist/deploy
add a file 50_qserver.xml
<qserver logger="Q2" name="qserver">
<attr name="port" type="java.lang.Integer">${qserver.port}</attr>
<channel class="org.jpos.iso.channel.XMLChannel"
logger="Q2"
packager="org.jpos.iso.packager.XMLPackager" />
</qserver>
Edit cfg/default.yml
In src/dist/cfg/default.yml
add the following configuration:
qserver:
port: 10000
Build and Run
gradle installApp && bin/q2
will start the server, and you'll see a message like this:
<log realm="qserver-10000.server" at="2024-09-26T15:28:32.779165"
trace-id="686f293a36144952849fa3b84ebcfe43">
<info>
Listen[port=10000, bindAddr=null, permits=100, backlog=5]
</info>
</log>
now telnet localhost 10000
and you'll see:
<log realm="qserver-10000.server.session" at="2024-09-26T15:29:06.162668"
trace-id="686f293a36144952849fa3b871e9f625">
<info>
SessionStart[connections=1, permits=100, info=Socket[addr=/127.0.0.1,port=52014,localport=10000]]
</info>
</log>
close the connection:
<log realm="qserver-10000.server.session/127.0.0.1:52014" at="2024-09-26T15:29:39.581750"
trace-id="686f293a36144952849fa3b871e9f625">
<info>
SessionEnd[connections=1, permits=100, info=Socket[addr=/127.0.0.1,port=52014,localport=10000]]
</info>
</log>
Troubleshooting telnet on Windows
Telnet allows you to establish a basic socket connection with a server, in this case to port 10000. However, when used without specifying a port, Telnet defaults to port 23. During the initial connection on port 23, Telnet negotiates terminal capabilities with the server, such as ANSI support, the number of columns, rows, etc. On Unix systems, Telnet is smart enough to skip this negotiation if you're not using the default port (23). Unfortunately, this is not the case on Windows, where the client still sends negotiation packets to the server, which doesn't expect them and interprets them as garbage. The solution is to use Putty, or better yet, Netcat. For this example, you can use the command nc localhost 10000.
Understanding the configuration
In the previous configuration, we used ${qserver.port}
as defined in cfg/default.yml
to demonstrate how this works. This could have been an environment variable like QSERVER_PORT
, or simply the number 10000 (or any port you choose) directly in the configuration file. Additionally, other configuration parameters, such as the channel and packager, can also be sourced from the YAML file, for example:
qserver:
channel: org.jpos.iso.channel.XMLChannel
packager: org.jpos.iso.packager.XMLPackager
and then changing the XML descriptor to:
<qserver logger="Q2" name="qserver">
<attr name="port" type="java.lang.Integer">${qserver.port}</attr>
<channel class="${qserver.channel}"
logger="Q2"
packager="${qserver.packager}" />
</qserver>
It's also a good idea to have an enabled
attribute, i.e.:
<qserver logger="Q2" name="qserver" enabled="${qserver.enabled:false}"">
<attr name="port" type="java.lang.Integer">${qserver.port}</attr>
<channel class="${qserver.channel}"
logger="Q2"
packager="${qserver.packager}" />
</qserver>
so that you can enable it by adding the property to the YAML file, or setting it as an environment variable QSERVER_ENABLED=true
.
Fire an XML message
From your telnet session, copy and paste the following XML fragment:
<isomsg>
<field id="0" value="2800" />
<field id="11" value="000001" />
<field id="70" value="301" />
</isomsg>
and press enter.
On the server, you'd see something like this:
<log realm="channel/127.0.0.1:52478" at="2024-09-26T16:14:25.858719" lifespan="5367ms" trace-id="686f293a36144952849fa3b871e9f625">
<receive>
<isomsg direction="incoming">
<!-- org.jpos.iso.packager.XMLPackager -->
<field id="0" value="2800"/>
<field id="11" value="000001"/>
<field id="70" value="301"/>
</isomsg>
</receive>
</log>
that shows you that the message has been well received.