Skip to main content

QServer Tutorial

git checkout qserver

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.