In our largest jPOS implementation, we faced the challenge of supporting direct connections from approximately 3,400 store locations across the United States. [A recently concluded acquisition will add an additional 1,800 locations.] Each of these locations has, behind the scenes, up to a dozen POS origination points at its largest stores. Though the store systems software there can aggregate some transactions within the same connection, the dynamics of the connection model is that our in-place jPOS implementation has to support intensive I/O - hundreds of thousands of temporary connections are serviced each hour.
An additional challenge is that the transactions being serviced aren't ISO8583-based (they're Visa Gen 2, or 'VG2' as I call it), meaning we had to expand beyond jPOS' roots as a servicer of that industry-standard payment systems message format.
To meet these intensive I/O needs, Alejandro implemented Server and Session components based on Java New I/O. As noted in Wikipedia, New I/O "is usually called NIO, is a collection of Java Programming language APIs that offer features for intensive I/O operations."
We have a Server element that listens to the stores like this:
<ev-server class="org.jpos.ev.Server" logger="Q2"> In our server.java program, we import the following Java packages:
import java.util.Set; We break the ISO8583 chains by making use of jPOS' FSDMsg component to read the VG2 requests into FSDMsg's XML definitions. For example, a Debit message is handled and parsed into its constituent parts by our v2-base.xml:
<?xml version="1.0" encoding="UTF-8"?> You can see 'record-format' and 'application type are our keys here. A 'G0' is a debit, and that invokes the next part of the XML model, which is called v2-G0.xml and looks like this:
<?xml version="1.0" encoding="UTF-8"?> <schema id='G0'> You can see that we require some more parsing (see lines marked with 'key') based on the transaction-code (because the Debit purchase looks different than the Debit reversal) and the card-id-source (because the real-time auth request looks different than some items in which a manager-override is invoked). As a result, the last part of the applicable model used to handle the VG2 Debit purchase is called v2-G093A.xml and looks like this:
<?xml version="1.0" encoding="UTF-8"?> <schema> I started off writing this post about how we used Java New I/O (java.nio) to solve our intensive I/O challenges. But you can see that NIO + FSDMsg can be used together to solve those situations where your I/O challenges go beyond ISO8583.
<property name="port" value="33000" />
<property name="space" value="tspace:default" />
<property name="queue" value="RACEV.TXN" />
<property name="timeout" value="60000" />
</ev-server>
import java.util.Iterator;
import java.io.IOException;
import java.io.EOFException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
<schema>
<field id="header" type="B" length="4" />
<field id="record-format" type="A" length="1" key="true" />
<field id="application-type" type="A" length="1" key="true" />
<field id="field-sep-1" type="K" length="1">.</field>
</schema>
<field id="acquirer-bin" type="N" length="6" />
<field id="message-version" type="N" length="2" />
<field id="shift-number" type="N" length="5" />
<field id="merchant-number" type="N" length="4" />
<field id="store-number" type="N" length="5" />
<field id="terminal-number" type="N" length="4" />
<field id="category-code" type="N" length="4" />
<field id="country-code" type="N" length="3" />
<field id="city-code" type="A" length="5" />
<field id="timezone-differential" type="N" length="3" />
<field id="transaction-code" type="A" length="2" key="true" />
<field id="terminal-serial-number" type="N" length="8" />
<field id="encryption-indicator" type="A" length="1">
<field id="transaction-sequence-number" type="N" length="4" />
<field id="card-id-source" type="A" length="1" key="true" />
</schema>
<field id="account-entry-mode" type="A" length="1" />
<field id="magnetic-strip-info" type="AFS" length="40" />
<field id="cid-device-attached" type="A" length="1" />
<field id="pin-action-code" type="A" length="1" />
<field id="pin-function-code" type="A" length="1" />
<field id="pin-length" type="A" length="2" />
<field id="pin-block" type="A" length="2" />
<field id="encrypted-pin-block" type="A" length="16" />
<field id="pin-dukpt-ksn" type="AFS" length="16" />
<field id="amount" type="AFS" length="14" />
<field id="additional-amount" type="AFS" length="14" />
<field id="register-number" type="A" length="2" />
<field id="tran-id" type="A" length="7" />
<field id="tender-attempt-indicator" type="A" length="1" />
<field id="tender-number" type="A" length="4" />
<field id="tender-attempt" type="A" length="4" />
</schema>
Comments