JPOS Channel Example Introduction

This project demonstrates how to build JPOS client and server applications using the ActiveSpaces Transactions Channel Framework Service. The primary goal of the project is to show how a protocol-specific API such as JPOS can be easily integrated into a ActiveSpaces Transactions-based application.

The JPOS API provides a facility for sending and receiving ISO-8583 financial transaction messages. JPOS provides various ways to implement ISO-8583 clients and servers. This example implements a simple JPOS server using the org.jpos.iso.ISOServer facility. The server accepts connections from any simple TCP/IP client, and processes XML-encoded ISO-8583 messages received over the connection. This example also implements a JPOS client, and demonstrates instances of the server and client exchanging ISO-8583 messages.

The client and server facilities are each implemented as a distinct ActiveSpaces Transactions Service, and associated Endpoint classes, each of which represents a single client/server connection. Each ActiveSpaces Transactions Service provides an administrative entity that can be monitored and managed via the standard ActiveSpaces Transactions management tools. Each Service can be used independent of the other - for example, ClientService can be used to build client JPOS applications which connect to other 3rdparty ISO-8583 servers.

Please see the enclosed source, javadoc, and example class descriptions.

JPOS Server Service Overview

The main control point of the example server is the ServerService class, which manages the lifecycle of the server. The server uses a Listener class to encapsulate the actual JPOS service. The JPOS network service is provided by an instance of org.jpos.iso.ISOServer, a class which implements a network listener, and an internal thread pool which is used to service ISO-8583 messages received on client connections. Each inbound message is delivered to the example's Listener, which routes the message to the example's ServerApplication application handler. The ServerService class allows the application to specify the network port to be used by the Listener to receive connections. It also provides automatic selection of an available port, when a port of 0 is specified.

The JPOS ISOServer facility hides client connections, and essentially presents a message-based protocol. Consequently, the example Service uses a single Endpoint and Session to route inbound messages to the application handler. The same Endpoint/Session pair is used to route outbound messages, which are delivered to the client by JPOS via the ISOMsg and ISOSource classes.

The JPOS ISOServer facility supports a variety of wire protocols, via the configuration of an ISOPackager to be used by the ISOServer. Each ISOPackager provides encoding/decoding of ISO-8583 messages processed by the ISOServer. The ServerService class allows applications to specify the ISOPackager to use by its ISOServer. To keep things simple, this example configures its ISOServer to use text-based XML ISO-8583 messages, and can therefore be used with any simple TCP/IP client, such as telnet.

JPOS Client Service Overview

The client facility is controlled via the ClientService class. This class implements a createEndpoint() operation, which creates a connection to a specified ISO-8583 network server. The connection is encapsulated in a ClientEndpoint instance, which is then used by the application to send ISO-8583 messages to the server. Response messages received from the server are delivered by ClientEndpoint to the application handler configured for the endpoint, or the global Application handler.

The createEndpoint() operation allows the application to specify the ISOPackager to be used by a given connection, in much the same way that is done by ServerService. In addition, createEndpoint() also allows the application to specify the org.jpos.iso.ISOChannel to be used by the connection. The combination of an ISOChannel and ISOPackager provide support for a variety of vendor-specific encoding variants of the ISO-8583 wire protocol.

Internally, ClientEndpoint uses an org.jpos.iso.ISOMUX instance to handle the actual network I/O to the remote server, and an ISORequestListener (implemented by ClientListener) to process response messages received from the server. Those response messages are delivered to the application as a ActiveSpaces Transactions message.

Usage

The example implements a very simple JPOS server, which supports TCP/IP client connections, and a simple JPOS client, which connects to the example's JPOS server.

The Main class creates and starts a ServerService instance using a listener port number of 7070. Here is the Maven command to start the server:

mvn -Dcom.kabira.fluency.administrationPort=2000 \
      -Dcom.kabira.fluency.hostName=kabira-server.local \
      compile deploy:exec

NOTE: kabira-server.local only works on OS X. Other platforms may use a different name or have to specify an IP address.

The server will display:

==============================================
jposchannel started at port 7070.
To stop this application, stop the "jposchannel example" service.
==============================================

The example's Main() then goes on to run a simple JPOS client, via its runClient() operation. This operation creates a ClientService, and uses that service to create an instance of ClientEndpoint to connect to the example's server. The client then sends an ISO-8583 message to the server via the endpoint, and reads the response, which is delivered to the ClientApplication handler.

As runClient() executes, it will display the following output:

runClient(): creating client service ...
runClient(): starting client service ...
runClient(): creating client endpoint  connecting to server at port: 7070 ...
runClient(): Sending a message ...
runClient(): message sent ok ...
runClient(): all done!

The example's server receives the client message, which is delivered to the ServerApplication handler. That handler displays the contents of the ISO-8583 message sent by the client, and sends a response message, as follows:

ServerApplication: Received message from: jpos
Inbound MTI: 0800
Inbound Direction: INCOMING
Inbound Message dump:

        <isomsg direction="incoming">
                <field id="0" value="0800"/>
                <field id="3" value="000000"/>
                <field id="41" value="00000001"/>
                <field id="70" value="301"/>
        </isomsg>
Inbound ISOHeader Source: null
Inbound ISOHeader Destination: null
ServerApplication: Sending the response message ...

The channel receives the response message, and delivers it to the ClientApplication handler, which displays its contents:

ClientApplication: Received response from: client endpoint
ClientApplication: Response message dump: 
---> <isomsg direction="incoming">
--->   <field id="0" value="0810"/>
--->   <field id="3" value="000000"/>
--->   <field id="39" value="00"/>
--->   <field id="41" value="00000001"/>
--->   <field id="70" value="301"/>
---> </isomsg>

The example leaves the server running, so at this point, you can connect to the server with any network client (telnet, mconnect, netcat, etc.). Once connected, you can type in any XML-encoded ISO-8583 message, followed by a newline. The message will be sent to the Service, which will display a description of the message received, and return a modified version of the same message as a response. The client tool will receive and display the response message.

Here is an example client session, using telnet, connecting to port 7070:

> telnet 10.170.... 7070
Escape character is '^]'.

<isomsg> <field id="0" value="0800"/> <field id="3" value="333333"/> </isomsg>

<isomsg>
<field id="0" value="0810"/>
<field id="3" value="333333"/>
<field id="39" value="00"/>
</isomsg>

When the Service's application handler receives a message, it will display a description of the message, as follows:

Innbound MTI: 0800
Inbound Direction: INCOMING
Inbound Message dump:

<isomsg direction="incoming">
<field id="0" value="0800"/>
<field id="3" value="333333"/>
</isomsg>
Inbound ISOHeader Source: null
Inbound ISOHeader Destination: null

The Application handler then sets some response fields in the message, and sends that same message as a response. A real-world ISO-8583 application would implement business logic to service the inbound message and generate a corresponding response at this point.

In the following Kabira Manager view, the "jposchannel" Service is selected. The Endpoint created by the Service is displayed, along with some statistic information on the number of messages processed by the Service.

View of the "jposchannel" Service in Kabira Manager.

To shut down the application, stop the "jposchannel" service via the Kabira Manager, using the "stop" button.

The Endpoint view provides additional information on the activity seen by the Service:

View of the "jpos" Endpoint in Kabira Manager.

Select the named Session instance to show further details:

View of the "jpos:jpos" Session in Kabira Manager.

Dependencies

See the Dependencies page for information on the channel's dependencies.

For each dependency listed in the Project Dependencies section of the Dependencies page, the channel's POM (or parent POM) defines a property specifying the version of the dependency used by the channel. These properties can be overridden if there is a need to change the dependency versions used by the channel. The names of these properties are of the form com.tibco.groupId.artifactId.version where groupId and artifactId are the group id and artifact id of the dependency. For example, the property named com.tibco.com.tibco.ast.version specifies the version of the dependency with the group id of com.tibco and the artifact id of ast.