Customizing your Gateway
Table of Contents
Create a project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Test run . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Gateway Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Adding your custom code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
How to get help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
This tutorial assumes that you have successfully completed the
IMPORTANT
Implementing a jPOS Gateway tutorial.
The jPOS Gateway tutorial shows you how to use an out-of-the-box binary distribution of jPOS to
build an ISO-8583 gateway, but real world implementations usually require adding custom business
logic, for validation, routing, logging, etc.
This tutorial will show you how to do that by creating a Java project that will use jPOS as a
dependency.
1
Create a project
Visit the jPOS-template Github page and download or clone the jPOS-template. Let’s call our project
gateway. We use the clone command here, but downloading the ZIP is basically the same thing.
git clone [Link] gateway ①
cd gateway
rm -fr .git ②
① Visit jPOS-template and clone or download it.
② If you cloned it, you may want to get rid of the .git reference and git init your own.
2
Test run
gradle installApp ①
build/install/gateway/bin/q2 ②
① Build the project and install it in the build/install directory
② Run it in the foreground using the bin/q2 start-up script
If you don’t have Gradle installed in your system, you can use the provided Gradle
TIP wrapper by calling ./gradlew instead of your default gradle. It’s a good idea to install a
recent version of Gradle in your development environment, though.
The dist target creates a binary distribution in the build/distributions directory, that can be
expanded in a staging directory and run from there. The installApp target is basically the same as
calling gradle dist and then exploding the tarball in a working directory, in this case build/install.
You can install a handy q2 script like the following in your PATH:
#!/bin/bash
TIP exec build/install/${PWD##*/}/bin/q2 "$*"
Then you can call gradle iA && q2 to build and run instead of gradle iA &&
build/install/gateway/bin/q2. Please note iA is a shortcut for installApp.
Once you run q2, you’ll see something like this:
<log realm="[Link]" at="2017-05-06T[Link].419">
<info>
Q2 started, deployDir=/Users/apr/tutorials/gateway/build/install/gateway/deploy
</info>
</log>
...
...
Stop the system using Ctrl-C, you are now ready for the next step, but before that, we’d like you to
understand why this work the way it works.
When we call gradle dist to build a binary distribution with a directory structure similar to the one
you’ve seen in the previous tutorial, or call gradle installApp to build the distribution and then
expand it in the build/install directory, the following takes place:
• The jPOS standard directory structure gets created in the build/install/<projectname>/
directory (in this case build/install/gateway).
• The src/dist/deploy and src/dist/cfg directories get copied to their destination directory in
build/install/gateway/deploy and build/install/gateway/cfg directories. Same goes for the
3
src/dist/bin directory that contains the q2, start and stop scripts (and .BAT for Windows users)
• And finally, the main jar in the build/install/gateway directory named after the project name
and version (defined in the main [Link] file).
So if we go to the build/install/gateway directory, we’ll see a jar like this:
[Link]
If we analyze its content (using jar tvf [Link]) we’ll see something like this:
0 Sun May 21 [Link] ART 2017 META-INF/
498 Sun May 21 [Link] ART 2017 META-INF/[Link]
126 Sun May 21 [Link] ART 2017 [Link]
83 Sun May 21 [Link] ART 2017 [Link]
If we expand it and take a look at the META-INF/[Link] file we’ll see something like this:
Manifest-Version: 1.0
Implementation-Title: gateway
Implementation-Version: 2.1.0
Class-Path: lib/[Link] lib/[Link] lib/jdbm-1 ①
.[Link] lib/[Link] lib/[Link] lib/[Link]
lib/[Link] lib/[Link] lib/[Link]
lib/[Link] lib/[Link] lib/sshd-core-
[Link] lib/[Link] lib/[Link] lib/Hd
[Link]
Main-Class: [Link].q2.Q2 ②
① The main jar contains a reference to its dependencies which are available in the lib directory.
② We designate [Link].q2.Q2 as our main class.
That little jar, which for now has no compiled classes is the reason we can launch Q2 just by calling:
java -jar [Link]
which is basically what the bin/q2 script does (it just adds a few switches and defaults).
4
Gateway Configuration
Now go back to the Implementing a jPOS Gateway tutorial and place the QServer, ChannelAdaptor,
MUX and TransactionManager configurations presented there but instead of using the deploy
directory, you should use the src/dist/deploy directory.
For your convenience, you can follow the following script:
cd src/dist/deploy
wget [Link]
wget [Link]
wget [Link]
wget [Link]
cd ../../..
Now, when you call gradle installApp && build/install/gateway/bin/q2 you’d be able to run exactly
the same configuration shown in the Gateway tutorial, with a nice difference, you’re building from
the sources, and you can add your custom code to the classpath.
At this point, we suggest you fire a message following the instructions from the gateway tutorial,
just to make sure everything works alright before moving to the next section.
5
Adding your custom code
Adding your custom code is simple now, just create a directory src/main/java and place them there.
You probably want to use an IDE, so you can try something like this:
mkdir -p src/main/java
gradle idea # (or gradle eclipse if you wish)
and you’d be ready to open [Link] project.
Let’s add for example a TransactionParticipant.
Right now, our the TM configuration (src/dist/deploy/30_txnmgr.xml) looks like this:
<txnmgr class="[Link]" logger="Q2">
<property name="queue" value="TXNMGR"/>
<property name="sessions" value="2"/>
<property name="max-sessions" value="128"/>
<property name="debug" value="true"/>
<participant class="[Link]"/>
<participant class="[Link]"/>
</txnmgr>
Just the QueryHost and SendResponse participants. Let’s add a SelectDestination participant that
would allow you to route a transaction to different endpoints.
Create a directory src/main/java/org/jpos/tutorial where your [Link] code will
sit:
mkdir -p src/main/java/org/jpos/tutorial
Now edit a file [Link] with code like this:
6
package [Link];
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class SelectDestination implements TransactionParticipant, Configurable {
Configuration cfg;
@Override
public int prepare(long id, Serializable context) {
Context ctx = (Context) context;
ISOMsg m = (ISOMsg) [Link]([Link]());
if (m != null && ([Link](2) || [Link](35))) {
try {
Card card = [Link]().isomsg(m).build();
String s = [Link]("bin." + [Link](), null);
if (s != null) {
[Link]([Link](), s);
}
} catch (InvalidCardException ignore) {
// use default destination
}
}
return PREPARED | NO_JOIN | READONLY;
}
public void setConfiguration (Configuration cfg) {
[Link] = cfg;
}
}
Now go back to 30_txnmgr.xml and add a new participant just before QueryHost:
<participant class="[Link]">
<property name="bin.411111" value="MYMUX" />
</participant>
Now if you send a regular message to port 8000 as instructed in the Gateway tutorial, the message
would go to the configured jPOS-AUTORESPONDER MUX, but if you care to add a field 2 (Primary
Account Number) with a value of 4111111111111111 (valid LUHN, configured BIN 411111), then you
won’t get a response, but if you check the log/[Link] you’ll see something like this:
7
RESULT:
<result>
<fail>
[MISCONFIGURED_ENDPOINT] [Link] MUX '[Link]' not
found
</fail>
</result>
The system tried to route the transaction to a non existent MUX called MYMUX.
If you add it (20_mymux_mux.xml pointed to a channel), you should be able to get the router going.
8
How to get help
If you have questions while trying this tutorial, feel free to contact support@[Link], we’ll be
happy to help.
If you want online assistance, you can join the jPOS Slack, please request an invite.