jPOS Extended Edition Software Development Kit
jPOS Extended Edition Software Development Kit
Version: 1.5.1
Version: 1.5.1
Table of Contents
Table of Contents
Foreword
Foreword ...iv...iv
1. Quick Start 1. Quick Start ... 11 1.1. Prerequisites 1.1. Prerequisites ... 11 1.2. Bootstrap 1.2. Bootstrap ... 11 1.3. Directory Structure 1.3. Directory Structure ... 22 1.4. Quick start 1.4. Quick start ... 33 1.5. Using jPOS-EE in IDE xyz
1.5. Using jPOS-EE in IDE xyz ... 44 1.6. Coding conventions
1.6. Coding conventions ... 55
2. Demo
2. Demo ModuleModuless ... 66 2.1. Splash 2.1. Splash ... 66 3. Support Modules 3. Support Modules ... 77 3.1. Hibernate 3.1. Hibernate ... 77 3.2. Jetty 3.2. Jetty ... 77 3.3. JPublish 3.3. JPublish ... 77 4. Core Modules 4. Core Modules ... 99 4.1. EE Core 4.1. EE Core ... 99 4.1.1. The DB Object 4.1.1. The DB Object ... 99 4.1.2. BLException 4.1.2. BLException ... 99 4.1.3. Constants 4.1.3. Constants ...9...9 4.1.4. Finders and Managers
4.1.4. Finders and Managers ... 1010 4.2. EE Entities
4.2. EE Entities ... 1010 4.2.1. SysConfig
4.2.1. SysConfig ... 1010 4.2.2. SysLog and SysLogEvent
4.2.2. SysLog and SysLogEvent ... 1111 4.2.3. ResultCode
4.2.3. ResultCode ... 1212 4.2.4. User, Props and Permissions
4.2.4. User, Props and Permissions ... 1313 4.2.5. Visitor 4.2.5. Visitor ... 1313 4.2.6. RevisionEntry 4.2.6. RevisionEntry ... 1414 4.2.7. Status 4.2.7. Status ... 1515 4.2.8. Merchants and Stores
4.2.8. Merchants and Stores ... 1616 4.2.9. Terminals and TerminalProfile
4.2.9. Terminals and TerminalProfile ... 1717 4.3. EE TXN 4.3. EE TXN ... 1818 4.3.1. The Context 4.3.1. The Context ... 1818 4.3.2. Debug participant 4.3.2. Debug participant ... 1919 4.3.3. Profiler and CheckPoint
4.3.3. Profiler and CheckPoint ... 2020 4.3.4. Notify 4.3.4. Notify ... 2020 5. Simulators 5. Simulators ... 2121 5.1. Server Simulator 5.1. Server Simulator ... 2121 5.2. Client Simulator 5.2. Client Simulator ... 2121 6. Experimental 6. Experimental... 2525 6.1. IRCLogger 6.1. IRCLogger ... 2525 6.2. QCluster 6.2. QCluster ... 2525 6.2.1. Dependencies 6.2.1. Dependencies ... 2727 6.3. Java Service Wrapper
6.3. Java Service Wrapper ... 2727 6.3.1. Credits 6.3.1. Credits ... 2727 6.4. HA Service 6.4. HA Service ... 2828 6.4.1. Credits 6.4.1. Credits ... 2828 6.5. ReplicatedSpace 6.5. ReplicatedSpace ... 2828
Table of Contents
Table of Contents
Foreword
Foreword ...iv...iv
1. Quick Start 1. Quick Start ... 11 1.1. Prerequisites 1.1. Prerequisites ... 11 1.2. Bootstrap 1.2. Bootstrap ... 11 1.3. Directory Structure 1.3. Directory Structure ... 22 1.4. Quick start 1.4. Quick start ... 33 1.5. Using jPOS-EE in IDE xyz
1.5. Using jPOS-EE in IDE xyz ... 44 1.6. Coding conventions
1.6. Coding conventions ... 55
2. Demo
2. Demo ModuleModuless ... 66 2.1. Splash 2.1. Splash ... 66 3. Support Modules 3. Support Modules ... 77 3.1. Hibernate 3.1. Hibernate ... 77 3.2. Jetty 3.2. Jetty ... 77 3.3. JPublish 3.3. JPublish ... 77 4. Core Modules 4. Core Modules ... 99 4.1. EE Core 4.1. EE Core ... 99 4.1.1. The DB Object 4.1.1. The DB Object ... 99 4.1.2. BLException 4.1.2. BLException ... 99 4.1.3. Constants 4.1.3. Constants ...9...9 4.1.4. Finders and Managers
4.1.4. Finders and Managers ... 1010 4.2. EE Entities
4.2. EE Entities ... 1010 4.2.1. SysConfig
4.2.1. SysConfig ... 1010 4.2.2. SysLog and SysLogEvent
4.2.2. SysLog and SysLogEvent ... 1111 4.2.3. ResultCode
4.2.3. ResultCode ... 1212 4.2.4. User, Props and Permissions
4.2.4. User, Props and Permissions ... 1313 4.2.5. Visitor 4.2.5. Visitor ... 1313 4.2.6. RevisionEntry 4.2.6. RevisionEntry ... 1414 4.2.7. Status 4.2.7. Status ... 1515 4.2.8. Merchants and Stores
4.2.8. Merchants and Stores ... 1616 4.2.9. Terminals and TerminalProfile
4.2.9. Terminals and TerminalProfile ... 1717 4.3. EE TXN 4.3. EE TXN ... 1818 4.3.1. The Context 4.3.1. The Context ... 1818 4.3.2. Debug participant 4.3.2. Debug participant ... 1919 4.3.3. Profiler and CheckPoint
4.3.3. Profiler and CheckPoint ... 2020 4.3.4. Notify 4.3.4. Notify ... 2020 5. Simulators 5. Simulators ... 2121 5.1. Server Simulator 5.1. Server Simulator ... 2121 5.2. Client Simulator 5.2. Client Simulator ... 2121 6. Experimental 6. Experimental... 2525 6.1. IRCLogger 6.1. IRCLogger ... 2525 6.2. QCluster 6.2. QCluster ... 2525 6.2.1. Dependencies 6.2.1. Dependencies ... 2727 6.3. Java Service Wrapper
6.3. Java Service Wrapper ... 2727 6.3.1. Credits 6.3.1. Credits ... 2727 6.4. HA Service 6.4. HA Service ... 2828 6.4.1. Credits 6.4.1. Credits ... 2828 6.5. ReplicatedSpace 6.5. ReplicatedSpace ... 2828 6.5.1. Usage 6.5.1. Usage ... 2929
6.5.2. Implementation notes 6.5.2. Implementation notes ... 2929 A. Copyright A. Copyright ... 3131 B. License B. License ... 3232 Index Index ... 3737 jPOS-EE-SDK jPOS-EE-SDK
Foreword
Foreword
jPOS is an ISO-8583 library/framework that can be used to implement financial interchanges, protocol jPOS is an ISO-8583 library/framework that can be used to implement financial interchanges, protocol
convert-ers, payment gateways, credit card verification clients and servers (merchant/issuer/acquirer roles), etc. ers, payment gateways, credit card verification clients and servers (merchant/issuer/acquirer roles), etc. jPOS Extended Editio
jPOS Extended Edition Software Developmn Software Development Kit ent Kit goes one step goes one step beyonbeyond jPOS d jPOS by providinby providing a g a develodevelopment en-pment en-vironment with a continuosly growing set of proven, ready-to-deploy components based on jPOS' best vironment with a continuosly growing set of proven, ready-to-deploy components based on jPOS' best prac-tices.
Chapter 1. Quick Start
1.1. Prerequisites
jPOS-EE-SDK assumes that the following software is installed in your development environment: • Java[tm] JDK 1.4 or superior [http://java.sun.com]
• Apache's ANT 1.6.2 or superior [http://ant.apache.org]
1.2. Bootstrap
• Create a new directory, i.e.jposee and change to that directory. You can use any name you want.
Note
We'll refer to that directory as JPOS_EE_HOME
• Download the bootstrap [http://jpos.org/ee/bootstrap.xml] build file into your JPOS_EE_HOMEdirectory .
• Then run the following command:
ant -buildfile bootstrap.xml
This will download the latest snapshot of the jPOS-EE SDK distribution.
Tip
The bootstrap process requires to fetch files from the Internet. If you use a proxy for Internet access, you will need to set the necessary ant options.
On Linux, for bash:
export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
For csh/tcsh:
setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
replacing the values with the correct values for your installation.
In order to test your new installation, please download the sp lash [http://jpos.org/ee/modules/splash.zip] mod-ule and unzip it into yourJPOS_EE_HOME/modules directory.
Run the following command in your JPOS_EE_HOMEdirectory:
ant
cd build
java -jar jpos-ee.jar
You will see the jPOS-EE start and the new installed splash module will be invoked.
For additional information about available modules, stay tuned to our Bl og [http://jpos.org/blog] and browse the modules [http://jpos.org/ee/modules] central repository.
Most modules will use specific jar files that will be installed in their lib directory. These jars will either be
provided as part of the module distribution zip file or will be downloaded by the ant setup in the module
specificbuild.xmlfile.
Whenever you download a new module, you should attempt to run its 'setup' target using the command:
ant setup
either at the module's directory or at JPOS_EE_HOME.
Note
Calling ant setup from your toplevel JPOS_EE_HOME directory will invoke everysetup target of each
installed module. We often update the supporting jars versions, so you should pay attention to the ver-sions in use and eventually remove old verver-sions from the lib directory. If in doubt, clear out the lib
folder in your module directory and then invoke ant setupagain.
Note
At any time, you can call
ant update
in order to fetch a new version of bootstrap.xml from the jPOS-EE SDK repository. After an ant up-date we recommend to perform a full ant clean compile.
Tip
Ant compares the timestamps of the local and repository files in order to decide if a download is re-quired or not. After a failed download, a corrupted file may have the appropriate timestamp. If in doubt, you may want to remove remove the suspicious jar and try ant setupagain.
1.3. Directory Structure
COPYRIGHT (1) LICENSE (2) build.xml (3) lib (4) *.jar modules (5) ignore.list (6) include.list (7) splash jetty hibernate ... ... <other-modules> Quick Start(1) COPYRIGHT information (2) LICENSE information (3) Ant's configuration file (4) Supporting jars.
(5) Modules directory.
(6) A list of modules that should be ignored at compile time. (7) The list of modules to be included at compile time.
jPOS-EE SDK comes with several ready-to-deploy modules (see modules chapter). Each module has the fol-lowing directory structure (most directories are optional):
src (1) cfg (2) lib (3) deploy (4) *.xml lib (5) *.jar test (6) (1) source code (2) configuration files
(3) Supporting jars that are copied to the runtime lib directory
(4) Module-specific QBean configurations (to be copied to the runtime deploy directory) (5) Supporting jars that are copied to the runtime deploy/lib directory
(6) Optional directory where *TestCase.java files can be placed. These tasks would be included in the top
level testant's target.
After calling antfor the first time, a new directorybuildwill be created, modules will be flatten and copied
in-to the src lib cfg deploy deploy/lib in order to be ready for compilation and distribution (except those listed
in modules/ignore.list file).
Tip
In addition to modules/ignore.list there's a modules/include.list that you can use to selectively
compile a set of modules, e.g:
clientsimulator/** serversimulator/**
When you call ant zip, a distdirectory is created, and a distribution file named dist/jpos-ee-x.x.x.zip is
placed there. (ant tgzcreates a tar gzipped distro.)
1.4. Quick start
ant -projecthelp
produces the following output (may differ slightly on your distribution):
Main targets:
clean clean up build and dist directories compile compile all
jar creates jpos-ee.jar javadoc generate javadocs
run invoke jPOS-EE under Ant's JVM
singlejar creates a single jpos-ee.jar including all supporting jars test perform unit tests
tgz create tgz distribution update update jPOS-EE SDK zip create zip distribution Default target: compile
Executing ant zip (or ant tgz) will create a distribution file, ready to be unzipped/untarred and then run by
using the command: java -jar jpos-ee.jar
Tip
As a fast alternative to start jPOS-EE, you can call 'ant run'.
We recommend a careful look at the toplevelbuild.xmlas well as any module specificbuild.xmlfile that you
may download. You'll notice that the toplevel jpos-ee build.xml file also calls each module specific instance
for each of the different targets (prepare, first, then the defaulttarget, etc.).
Tip
You can build jPOS-EE to your JPOS_EE_HOME/build directory for testing purposes by just calling ant
(that will invoke its default "compile"target) that takes care of the creation of build/jpos-ee.jar.
Note
jPOS-EE SDK has many modules, many of them are just examples, proof-of-concept, experimental modules, etc. You can also add modules of your own. In order to customize your distribution, you can either move away unwanted modules from the modules directory, or use the modules/include.list
and/or modules/ignore.list file.
Tip
jPOS-EE can produce a single [big] jar file containing all supporting jars. You can take advantage of this feature by ant singlejartarget.Please note that this may not work with some supporting modules
that requires special configuration in their META-INF directory.
1.5. Using jPOS-EE in IDE xyz
jPOS-EE SDK uses layered directory structure where every module gets 'flattened' into the build directory as described in the previous section.
If you want to import its source code and supporting jars into your favorite IDE, we recommend that you use jPOS-EE-SDK's own ant configuration at least once in order to copy the necessary files from their source
loca-tions to the builddirectory.
Once you have everything in place in
build/src/*
build/lib/*
you are free to copy them to your IDE's working environment.
1.6. Coding conventions
We adhere to standard coding conventions [http://java.sun.com/docs/codeconv/CodeConventions.pdf] for the Java Language, that among other things it specifies: Four spaces should be used as the unit of indentation. The exact construction of the indentation (spaces vs. tabs) is unspecified. Tabs must be set exactly every 8 spaces (not 4).
Due to our revision control system, we also need that hard tabs (ASCII 0x09) are not used in source code and configuration files (in order for diff to work properly among platforms.
For vim users, we are using the following .vimrc:
set ts=8 set sts=4 set sw=4 set expandtab
Chapter 2. Demo Modules
2.1. Splash
This is a proof of concept module, created to test jPOS' SDK build environment. It just displays a splash screen using jPOS' Q2 Module examples. (seeq2modules/src/examples in jPOS distribution).
Figure 2.1. Splash
Note
This module doesn't have source code, as its source is distributed by jPOS. See / q2modules/src/example/src/org/jpos/q2/example/Splash.java for details.
Chapter 3. Support Modules
3.1. Hibernate
Many modules in jPOS-EE use Hibernate, so this little module is just used to download the supporting Hibern-ate jars.
After installing this module, make sure you call 'ant setup' in order to get the those jars from their
repositor-ies.
Note
cfg/hibernate.cfg.xml is assembled by the prepare task, called by the toplevel ant by picking cfg/ _hibernate.cfg.head plus cfg/_hibernate.cfg.properties as well as cfg/ _hibernate.cfg.mappings taken from the installed modules and then cfg/_hibernate.cfg.tail.
Please double-check the resulting build/cfg/hibernate.cfg.xml. Please note that configuration files
started with an underscore doesn't get copied to build/cfg(that's defined in the toplevel build.xml).
Tip
In addition to the hibernate module, you should install a specific module for your particular database.
3.2. Jetty
This module adds Jetty support to jPOS-EE, by using jPOS' q2modules/jetty. It provides a configuration file deploy/90_jetty.xml with the following content:
<jetty class="org.jpos.q2.jetty.Jetty"> <attr name="config">cfg/jetty.xml</attr> </jetty>
cfg/jetty.xml is Jetty's configuration file, that uses webapps/root as its root directory. See Jetty's Home
[http://www.mortbay.com/mortbay/mbindex.html] for details.
The default configuration listens to port 8080, so you can point your browser to localhost [http://localhost:8080/] in order to verify that this modules is running.
Note
Please reviewcfg/jetty.xmlfor further configuration.
3.3. JPublish
This module installs JPublish [http://www.jpublish.org] in our jPOS-EE environment.
A typical JPublish installation would involve adding these jars to the WEB-INF/lib directory, but, in order to reuse the same jars in multiple jPOS-EE web applications, we just place them in the root classpath (lib
direct-ory).
Note
ant setup
the first time you install this module, in order to fetch several supporting jars from their repositories. Support Modules
Chapter 4. Core Modules
4.1. EE Core
The Extended Edition Core module adds several general purpose classes (exceptions, entities, etc.) used by oth-er ee modules.
It depends on the hibernatemodule as well as one of its dialects (hibernate_*).
4.1.1. The DB Object
jPOS-EE uses Hibernate for its O/R mapping. For legacy reasons, we have a DB (org.jpos.ee.DB) class that
was previously used as our entry point to O/R mapping. Now that we rely on Hibernate, we still keep it around as an easy way to initialize Hibernate, and to keep in scope a few variables required by the system (such as an optional reference to a Log object).
Whenever you need to access the EE system, you just have to instantiate a DB object, and create an [hibernate] session. import org.jpos.ee.DB; ... ... DB db = new DB(); db.open(); ... ... db.close();
DB uses a flyweightpattern, so creating DB objects is acheapoperation.
4.1.2. BLException
org.jpos.ee.BLException is the base class for jPOS-EE business-logic related exceptions. It is thrown by
jPOS-EE applications to indicate a problem that is expected to happen during normal system operation 1, but not to indicate runtime or lower level system problems.
BLException can carry a nested exception. It also implements jPOS' org.jpos.util.Loggeable interface (so
you can easily add it to a LogEvent).
4.1.3. Constants
Many modules, specially those using the TransactionManager's Contexthave to define a lot of Constants. We
found useful to have a centralized point for that, the org.jpos.ee.Constantsinterface.
jPOS-EE eecore's build.xmlprepare target scans all the installed modules looking for files with the .k prefix,
and concat its content into a single Constants.java file, build/src/org/jpos/ee/Constants.java.
build.xmlproduces a header with the package name and interface name, then adds *.kfiles and as a last step it
Your application is free to implement org.jpos.ee.Constants in order to have instant access to all these handy variables.
package org.jpos.ee; <--- created by build.xml public interface Constants { <--- created by build.xml
... <--- content in *.k
... <--- content in *.k
... <--- content in *.k
} <--- created by build.xml
In addition, filters are applied (see filter.properties property, so
public static final String VERSION = "@version@";
becomes
public static final String VERSION = "1.5.1";
in the output file.
Tip
We use a similar approach to create a build/src/org/jpos/ee/Constants.properties
Resource-Bundle out of *.pfiles.
4.1.4. Finders and Managers
jPOS-EE-SDK leverages Hibernate'shbm2java to automatically generate entity beans as well as Finders. (see
modules/eecore/cfg/_codegen.xml).
In cases where we need additional hand-crafted logic to access either an entity or a set of related entities, we use the suffixManagerto represent that class.
So we use a naming convention like this:
• Terminal (the bean)
• TerminalFinder (automatically generated)
• TerminalManager (higher level methods that could deal with a set of terminals as well as related entities such as Merchants, Batches, etc.
Tip
In many cases, the Managerclass extends the automatically generated Finder.
4.2. EE Entities
4.2.1. SysConfig
SysConfig is a handy table that can be used to persist configuration properties; it can hold id / value pairs. It
uses the following mapping:
<hibernate-mapping>
<class name="org.jpos.ee.SysConfig" table="sysconfig"> <id name="id" column="id" type="string" length="32"> <generator class="assigned" />
</id>
<property name="value" type="string" length="65535"> <meta attribute="finder-method">findByValue</meta> </property>
<property name="readPerm" type="string" length="32" /> <property name="writePerm" type="string" length="32" /> </class>
</hibernate-mapping>
that produce the following table:
create table sysconfig ( id varchar(32) not null, value text,
readperm varchar(32) default NULL, writeperm varchar(32) default NULL, primary key (id)
)
In addition to the id and value, SysConfig has two permission properties, readperm and writeperm that are
honored by the web user interface (module eeweb).
Tip
Please note that there's a meta attribute that instructshbm2java to produce a findByValue method in the
automatically generated SysConfigFinder class with the following signature:
public static List findByValue(Session session, java.lang.String value) throws SQLException, HibernateException;
4.2.2. SysLog and SysLogEvent
While jPOS loggers can be of great help to debug and trace a jPOS-EE based installation, they are not designed to be monitored by normal operators.
The application programmer can use the SysLog class in order to create SysLogEventsthat would address these
kind of high level users.
The SysLogEvent has the following fields:
Table 4.1. SysLogEvent table
Name Description
date the event timestamp, automatically set to the current localtime by theSyslog helper class.
deleted boolean field used to logically delete this SysLog entry. The system's DBA has to be put in charge of Core Modules
Name Description
culling deleted records from this table on a regular basis.
source Application specific source associated with this log event. We envision using the application, module or component name here, i.e. "Q2_NODE_1", "WEB-SERVER/XXX", etc.
type Application specific event type, i.e:INFO,WARN, TRACE, AUDIT, etc.
summary A summary description of this event intended to be rendered in a single line.
detail Optional detail information, can spawn several lines. trace Additional trace information intended to be used for
diagnostic purposes (i.e. a full message dump).
Note
We have been talking about Entities, Finders and Managers, as a matter of fact, the SysLog class
should have been named SysLogManager, but given the fact that this class is intended to be used very
often, we decided to use a short name, so we can write code like this:
new SysLog().log ("Q2", "INFO", "Q2 System start");
4.2.3. ResultCode
Many times a single internal result code (say 'card expired') has to be expressed in different ways when trans-mitted to different networks using different protocol flavors. We use the name locale to represent those flavors (i.e. ISO87, ISO93, CARDX, CARDY, whatever).
The ResultCode entity, with its set of tables (rc and rc_locale)can be used to help in that mapping.
We use the following mapping:
<hibernate-mapping>
<class name="org.jpos.ee.ResultCode" table="rc"> <id name="id" column="id" type="long">
<generator class="assigned" /> </id>
<property name="mnemonic" type="string" length="32"> <meta attribute="finder-method">findByMnemonic</meta> <column name="mnemonic" index="mnemonic" unique="true" /> </property>
<property name="description" type="string" /> <map name="locales" lazy="true" table="rc_locale">
<key />
<index column="locale" type="string" length="32"/> <composite-element class="org.jpos.ee.ResultCodeInfo">
<property name="resultCode" type="string" length="4" /> <property name="resultInfo" type="string" />
<property name="extendedResultCode" type="string" length="32" /> </composite-element>
</map> </class>
</hibernate-mapping>
ResultCodeManager helper class can be used to access result codes for different locales, i.e:
ResultCodeManager mgr = new ResultCodeManager (db); // get error '14' mapped to locale 'ISO87'
ResultCodeInfo info = mgr.getInfo ("14", "ISO87"); if (info != null) { m.set (39, info.getResultCode()); m.set (63, info.getResultInfo()); m.set (123, info.getExtendedResultCode()); } else { // ... }
4.2.4. User, Props and Permissions
jPOS-EE user interface (moduleeeweb) uses this User entity, with its associated set of permissions and
proper-ties in order to allow or deny access to the system. The password field is stored as
MD5SUM (nick + password)
The default installation usually defines a user 'admin' with password 'test' that produces the following MD5SUM:66d4aaa5ea177ac32c69946de3731ec0.
Tip
You can try
echo -n admintest | md5sum
Note
The name 'user' is a reserved word in some RDBMSs, so we use the name 'eeuser' for the table name and columns.
4.2.5. Visitor
Every web user (eeweb module) is associated with a persistent Visitor object. We use the VisitorManager to
create a random unique cookie to be stored in the client's browser.
When the user logs into the system, it has the option to be rememberedin his current computer. Core Modules
Figure 4.1. Login Screen
Note
The previous login screen is part of the eewebmodule.
If [s]he choose to check that option, then the Visitor's User field will point to a valid User. When the user logs off, the Visitor object remains associated with his computer, but Visitor.userwill be null.
The name and expiration of this long-lived cookie is defined in org.jpos.ee.VisitorManager as:
public static final String COOKIE_NAME = "JPOSEE"; public static final int COOKIE_EXPIRATION = 365*24*3600;
4.2.6. RevisionEntry
In order to track changes in multiple entities (mostly performed through the web user interface (modules
eeweb)) we use this revisiontable where we store RevisionEntries.
The Hibernate configuration looks like this:
<hibernate-mapping>
<class name="org.jpos.ee.RevisionEntry" table="revision" discriminator-value=" ">
<id name="id" column="id" type="long"> <generator class="native" />
</id>
<discriminator column="subclass" type="string" length="8" /> <property name="date" type="timestamp" />
<property name="info" type="text" />
<many-to-one name="author" class="org.jpos.ee.User" column="author" /> <subclass name="org.jpos.ee.UserRevisionEntry"
discriminator-value="user">
<many-to-one name="user" class="org.jpos.ee.User" column="eeuser" /> </subclass>
<subclass name="org.jpos.ee.StatusRevisionEntry" discriminator-value="status">
<many-to-one name="status" class="org.jpos.ee.status.Status" column="status" /> </subclass> <!--... ... other subclasses ... ... --> </class> </hibernate-mapping>
This is pretty much straight forward, but an interesting thing worth noting here is the fact that we use a single
revisiontable where we track changes to Users, Status, etc. (you can add your own here).
We use a single table in order to get easy access to queries such as • changes performed by a given user
• changes in a given period of time
• changes performed by a given user in a given period of time that could be used for audit purposes.
4.2.7. Status
jPOS-EE components useStatus entities in order to report their current state. If you have a channel with a
re-mote hostwhere you expect to receive 0800 messages every minute, then you can add a Status entity with a name representing that host. Every time you receive a 0800 message you use the StatusManager's touch
opera-tion in order to notify that everything is going okay.
In the previous example, you can setup a 75 seconds timeout on that status entry. If for some reason you don't receive a 0800s message in 75 seconds, then the Status entry will change its state from OKto ERROR.
Figure 4.2. Status Monitoring
The HeartbeatQBean (see 02_status_heartbeat.xml) can be used to check all non-expired status entries for
expiration. Heartbeat will regularly call the StatusManager that would in turn log timeouts and status changes to theSysLog.
4.2.8. Merchants and Stores
In acquirer systems you need to keep track of your Merchants and Terminals, so we have a merchant table as
well as a terminal table, but if you want to have fine-grained control over a merchant's set of locations
(branches or stores), you can assign stores to a merchant, and assign the terminals to the stores. The Merchant/Store definition looks like this:
<hibernate-mapping>
<class name="org.jpos.ee.Merchant" table="merchant" discriminator-value="M"> <meta attribute="class-description">Merchant information</meta>
<id name="id" column="id" type="string" length="15"> <generator class="assigned" />
</id>
<discriminator column="subclass" type="string" length="1" /> <property name="name" type="string" length="40">
<meta attribute="field-description">Merchant name</meta> <meta attribute="finder-method">findByName</meta>
</property>
<property name="active" type="boolean">
<meta attribute="field-description">True if merchant is active</meta> <meta attribute="finder-method">findByActive</meta>
</property>
<property name="contact" type="string" length="40" /> <property name="address1" type="string" length="40" /> <property name="address2" type="string" length="40" /> <property name="city" type="string" length="40" /> <property name="state" type="string" length="2" /> <property name="province" type="string" length="20" /> <property name="zip" type="string" length="10" />
<property name="phone" type="string" length="40" /> <property name="country" type="string" length="40" /> <set name="stores" lazy="true" cascade="all-delete-orphan"
order-by="id asc"> <key column="parent" />
<one-to-many class="org.jpos.ee.Store" /> </set>
<set name="terminals" lazy="true" cascade="all-delete-orphan" order-by="id asc">
<key column="merchant" />
<one-to-many class="org.jpos.ee.Terminal" /> </set>
<set name="revisions" lazy="true" cascade="all-delete-orphan" order-by="id asc">
<key column="merchant" />
<one-to-many class="org.jpos.ee.MerchantRevisionEntry" /> </set>
<subclass name="org.jpos.ee.Store" discriminator-value="S"> <many-to-one name="parent" not-null="false"
class="org.jpos.ee.Merchant" /> </subclass>
</class>
</hibernate-mapping>
Note
Although we try to keep this documentation up-to-date, it may slightly differ from the real code. Please double check modules/eecore/src/org/jpos/ee/Merchant.hbm.xml
4.2.9. Terminals and TerminalProfile
As described in the previous section, Terminals can be assigned to either Merchants or Stores (a Store is a sub-class of Merchant). We keep in this table basic information about a Terminal, an information field called 'softVersion' (so we can keep track of the version installed using the Revision History) and a pointer to a Ter-minalProfile.
In a typical acquirer system you have to deal with different groups of terminals, usually having different capab-ilities (i.e. different software versions, different capabcapab-ilities or merchant types, i.e: selfservice, gas pump, oper-atorless, etc.). That information is stored in the TerminalProfile table so one can easily make global changes to these groups.
The Terminal definition looks like this:
<hibernate-mapping>
<class name="org.jpos.ee.Terminal" table="terminal"> <id name="id" column="id" type="long">
<generator class="native" /> </id>
<property name="terminalId" type="string">
<meta attribute="field-description">real terminal identifier (field 41)</meta> <meta attribute="finder-method">findByTerminalId</meta>
<column name="terminalId" sql-type="char(8)" not-null="true" index="terminal_id" /> </property>
<property name="info" type="string" length="40">
<meta attribute="field-description">Free text information</meta> </property>
<property name="softVersion" type="string" length="32"> <meta attribute="field-description">software version</meta> </property>
<many-to-one name="merchant"
class="org.jpos.ee.Merchant"
2see javadocs for details column="merchant" /> <many-to-one name="profile" class="org.jpos.ee.TerminalProfile" column="profile"> <meta attribute="finder-method">findByProfile</meta> </many-to-one> </class> </hibernate-mapping>
We use an autogenerated id this time, because the terminalId may be duplicated among different merchants. Al-though we recommend to use a numbering scheme with unique terminal ids when possible, we found situations where every merchant starts has a terminal 00000001, 00000002, 00000003 and so on.
The TerminalManager class has a handy
Terminal getTerminal (String mid, String tid);
method that can be used to locate a terminal based on its merchantId/terminalId.
4.3. EE TXN
Transaction Support
4.3.1. The Context
jPOS TransactionManager uses a Context to pass around information among its participants. The Context as
defined by jPOS is just any Serializableobject, so it's up to the developer to define it.
In jPOS-EE we define a general purpose Context object that mimics a Map. Actually two of them, a transient Map and a persistent one.
When the TransactionManager runs a transaction by calling the prepare operation on the defined participants,
it saves a snapshot of the context to persistent storage (usually a JDBMSpace). But sometimes one has to put
live objects in the Context, such as a reference to a Socket connection, a JDBC session or non serializable ob- ject.
So jPOS-EE Context implementation uses two maps, a persistent one (the default) and a transient one (you have to use the 't'prefix toputand getoperations, as in tputandtget
In addition to standard map operations, jPOS-EE Context has some helper methods useful to access longs (getLong(String), getTLong(String)), etc.2.
We also define some general purpose Constants: (all of them are optional, you can use your own names)
Table 4.2. Context Constants
Name Description
REQUEST Can be used to save a request, such as an ISOMsg. RAW_REQUEST Usually the raw image of a request.
RESPONSE Response ISOMsg (or other format) Core Modules
Name Description
RAW_RESPONSE The raw image of a response message DB Transient reference to a DB object.
TX Transient reference to an Hibernate Transaction.
PROFILER A profiler object
LOGEVT A LogEvent associated with this transaction
RC Response Code
EXTRC Extended Response Code
Tip
This is a growing list that may not be synchronized with this documentation, please double-check your options in the javadocs or sourcecode.
In addition to the standardputand getoperations (along with their tputand tgetcounterparts), jPOS-EE
gen-eral purpose Context has two additional handy operations: • log (String)
This operations adds a standard jPOS LogEvent to the transient context under the key Constant.LOGEVT
and then uses the event's addMessage operation in order to keep log information about this transaction. • checkPoint (String)
checkPoint operates in a similar way, adding a Profiler object (see org.jpos.util.Profiler).
4.3.2. Debug participant
org.jpos.ee.transaction.Debug can be used to dump the Context to a given Logger. It's a great tool for
de-bugging purposes, and even good in production for audit and system monitoring.
The Debugparticipant implementsAbortParticipant, so it will be called even if the transaction aborts.
Its source code is very simple:
public class Debug extends TxnSupport implements AbortParticipant { public int prepare (long id, Serializable o) {
return PREPARED | READONLY; }
public int prepareForAbort (long id, Serializable o) { return PREPARED | READONLY;
}
public void commit (long id, Serializable o) {
Logger.log (createEvent ("commit", id, (Context) o)); }
public void abort (long id, Serializable o) {
Logger.log (createEvent ("abort", id, (Context) o)); }
private LogEvent createEvent (String action, long id, Context ctx) { LogEvent evt = createLogEvent (action);
evt.addMessage ("<id>" + id + "</id>"); evt.addMessage (ctx);
} }
and so is its configuration:
<participant class="org.jpos.transaction.Debug" logger="Q2" realm="Debug" />
that we usually add as the last participant in the chain.
4.3.3. Profiler and CheckPoint
jPOS-EE Context implementation has the ability to store a Profiler 3 that can be used to monitor the
perform-ance of the participants.
org.jpos.transaction.CreateProfiler participant can be used to initialize that profiler, and is usually
con-figured at the beginning of a transaction using a simple configuration like this:
<participant class="org.jpos.transaction.CreateProfiler" logger="Q2" realm="profiler" />
The profiler is used in combination with the CheckPoint participant that can be added at different locations
within the execution chain, i.e.:
<participant class="org.jpos.transaction.CheckPoint" logger="Q2" realm="profiler"> <property name="message" value="checkpoint A" />
</participant> ...
...
<participant class="org.jpos.transaction.CheckPoint" logger="Q2" realm="profiler"> <property name="message" value="checkpoint B" />
</participant>
4.3.4. Notify
org.jpos.transaction.Notify can be used to notify a Context producer that a given transaction has been
pro-cessed.
This can be used for monitoring purposes or just as a way to get a response. It's usage is very simple, one just have to add:
<participant class="org.jpos.transaction.Notify" />
and context.notifyAll() will get called at commit() or abort() time. Core Modules
Chapter 5. Simulators
5.1. Server Simulator
Server Simulator is an extremely simple, BSH based simulator that can be used to test ISO-8583 based client software.
It listens to port 10000, and forwards all incoming requests to a BSH based script that can be tweaked to meet your needs.
<server class="org.jpos.q2.iso.QServer" logger="Q2" name="simulator_10000"> <attr name="port" type="java.lang.Integer">10000</attr>
<channel class="org.jpos.iso.channel.XMLChannel"
logger="Q2" packager="org.jpos.iso.packager.XMLPackager"> </channel>
<request-listener class="org.jpos.bsh.BSHRequestListener" logger="Q2"> <property name="source" value="cfg/serversimulator.bsh" />
</request-listener> </server>
The BSH script looks like this:
message.setResponseMTI (); (1)
Random random = new Random (System.currentTimeMillis());
message.set (37, Integer.toString(Math.abs(random.nextInt()) % 1000000)); message.set (38, Integer.toString(Math.abs(random.nextInt()) % 1000000)); if ("000000009999".equals (message.getString (4))) (2) message.set (39, "01"); else message.set (39, "00"); source.send (message);
(1) Sets the response MTI (i.e: 0800/0810, 1201/1220...)
(2) We use the special amount value $99.99 to decline the transaction
Tip
Never ever use this simulator even close to a production environment, or you may end up blindy au-thorizing transactions.
5.2. Client Simulator
The Client Simulator can be used to fire a suite of unit tests against an ISO-8583 server. The suite is defined by a set of XML files representing messages to be sent and their expected responses.
In order to simulate complex ISO-8583 interchanges, the client simulator uses BSH scripting support to cus-tomize the content of ISO-8583 fields at runtime. This can be used to specify constant values, such as terminal IDs, merchant IDs, card numbers, as well as dynamic values such as trace numbers, retrieval reference num-bers, pinblocks, key exchange related stuff, etc.
Let's have a look at the simulator's QBean configuration:
<qbean name="clientSimulator" logger="Q2" realm="client-simulator" class="org.jpos.simulator.TestRunner">
<property name="mux" value="clientsimulator-mux" /> <property name="timeout" value="30000" />
<property name="sessions" value="1" />
We specify a mux (that's the name of a QMUX running on the same JVM) and a timeout to wait for a given re-sponse. Then we define an initialization block, i.e:
<init>
import org.jpos.space.*; int cnt = 1;
String terminal = "29110001"; String merchant = "000000001001"; String pinblk = "0123456789ABCDEF";
Space sp = SpaceFactory.getSpace("transient:default"); </init>
The initialization block is basically a BSH script. You can do whatever you want there, such as defining con-stants for later use, references to jPOS objects (such as Space instances, Security module, etc.).
And then the test suite:
<test-suite>
<path>cfg/</path>
<test file="echo" count="10" continue="yes" name="Simple Echo Test" /> <test file="echo" count="20" continue="yes" name="Simple Echo Test 2">
<init>
// optional init script
// the variable 'testcase'references _this_ testcase instance // the variable 'request' references the ISOMsg that is to be sent </init>
<post>
// optional post script
// the variable 'testcase' references _this_ testcase instance // the variable 'response' references the received message
</post> </test> <path>cfg/anotherpath</path> <test file="mytest">MyTest</test> ... ... </test-suite> </qbean>
The suite can be separated in different paths, in the previous example, we assume that there are files named:
cfg/echo_sand cfg/echo_r.
The letter sin cfg/echo_sstands forsend and the rin cfg/echo_rstands forreceive.
cfg/echo_s:
<isomsg>
<field id="0" value="1800" />
<field id="7" value="1025080500" /> <field id="11" value="000001" />
<field id="41" value="29110001" /> </isomsg>
cfg/echo_r:
<isomsg>
<field id="0" value="1810" /> <field id="39" value="00" /> </isomsg>
In the previous example, we send a 1800 message with some fixed data, and we expect to receive a 1810
mes-sage, with a 00content in field 39.
While using fixed content may be okay for most fields and test cases, there are situations where you want to use dynamic content.
Our simulator supports BSH scripts at the field level. Everything that starts with a bang character (!) is
con-sidered a script and evaluated as such, so you can write:
<isomsg>
<field id="0" value="1800" />
<field id="7" value="ISODate.getANSIDate (new Date())" />
<field id="11" value="! System.currentTimeMillis() % 1000000" /> <field id="41" value="! terminal" />
<field id="52" value="@ pinblk" /> </isomsg>
Please note that in our example terminal is a runtime script variable that we've defined in our <init> block.
The '@' characters operates in a similar way as the '!' character, but the resulting value which is supposed to be an hexadecimal string, is converted to byte[] using ISOUtil.hex2byte(String) in order to produce an ISOBin-aryField.
The same thing happens at receive time, when we are trying to simulate voids, reversals, we usually need in-formation received in previous transactions, such as retrieval reference numbers, audit numbers, etc. so we can save that information for later use using a receive-time script:
<isomsg>
<field id="0" value="1810" />
<field id="11" value="! previousTrace=value" /> <field id="37" value="! rrn=value" />
<field id="39" value="00" /> </isomsg>
There's a special variable name called valuewhere we put the received content, so in the previous example, the
received retrieval reference number (field 37), is stored in the variable named rrnfor later use.
The receive script may optionally return true or false, so we can write code like this:
<isomsg>
<field id='39' value='! return value.equals(EXPECTED_RETVALUE)' /> </isomsg>
whereEXPECTED_RETVALUE is initialized in a previous init block.
In fact, the previous example is equivalent to the following: Simulators
<isomsg>
<field id='39' value='! EXPECTED_RETVALUE' /> </isomsg>
where the string value of EXPECTED_RETVALUE is used (unless it is a boolean).
There is a special string*E to test for echo. To ensure that the received content of a field is the same as the con-tent we sent, we can write code like this:
<isomsg>
<field id='4' value='*E' /> </isomsg>
Note
The special string *M can be used to check for mandatory field presence, regardless its content. Like-wise, *Ecan be used to check for mandatory echo and *Ocan be used to check for optional echo.
Test cases supports a countattribute that can be used to fire the same testntimes.
It also supports a continue attribute. If continue="yes" then the test runner would just log an exception if
something goes wrong, and it would continue with the next test.
The default timeout is 60 seconds, but one can specify a different timeout using the timeout attribute of the testcaseelement.
At the end, you get a ticket with the test results.
<log realm="org.jpos.simulator.TestRunner" at="Mon Oct 25 13:46:13 UYT 2004.581"> <results>
Simple Echo Test [OK] 58ms.
Simple Echo Test [OK] 38ms.
Simple Echo Test [OK] 70ms.
Simple Echo Test [OK] 23ms.
Simple Echo Test [OK] 56ms.
Simple Echo Test [OK] 24ms.
Simple Echo Test [OK] 73ms.
Simple Echo Test [OK] 107ms.
Simple Echo Test [OK] 20ms.
Simple Echo Test [OK] 50ms.
Simple Echo Test [OK] 23ms.
Simple Echo Test [OK] 24ms.
Simple Echo Test [OK] 86ms.
Simple Echo Test [OK] 24ms.
Simple Echo Test [OK] 24ms.
Simple Echo Test [OK] 23ms.
Simple Echo Test [OK] 26ms.
Simple Echo Test [OK] 21ms.
Simple Echo Test [OK] 22ms.
Simple Echo Test [OK] 79ms.
Simple Echo Test 2 [OK] 22ms.
elapsed server=893ms(62%), simulator=526ms(37%), total=1419ms </results>
</log>
Chapter 6. Experimental
6.1. IRCLogger
This log listener can be used to send log events to an irc channel where multiple operators could be logged.
<log-listener class="org.jpos.util.IRCLogListener"> <property name="server" value="irc.freenode.net" /> <property name="port" value="6667" />
<property name="maxport" value="6667" />
<property name="channel" value="#jpos-logger" />
<property name="space" value="transient:default" /> </log-listener>
Most IRC servers have anti-flood controls, so you don't want to dump there a very verbose log, however, you can use the irc logger just for important notices.
Even if you install a local irc server, you'll notice that the output is delayed (one line at a time), that's probably the default anti-flood protection of your irc server software. If you plan to send too many information over the irc channel then you should disable that protection.
6.2. QCluster
Figure 6.1. QCluster
Each Q2 node has to deploy a org.jpos.qcluster.QCluster QBean with a configuration like this:
<qcluster class="org.jpos.qcluster.QCluster" logger="Q2"> <property name="interval" value="10000" />
<property name="node" value="Q2.001" /> </qcluster>
QCluster relies on a central SQL repository that has a qbeantable with a structure like this:
CREATE TABLE qbean (
id bigint(20) NOT NULL auto_increment, node varchar(64) default NULL,
name varchar(64) default NULL, config text,
timestamp bigint(20) default NULL, active tinyint(1) default NULL, PRIMARY KEY (id)
)
which is produced by Hibernate based on org.jpos.qcluster.QBeanInfo entity.
QCluster scans the qbean table looking for updated (timestamp greater than a given value) and active qbean descriptors and deploys them to its local deploy directory.
In the same way, it scans the qbean table looking for inactive qbeans, and undeploy them from the local deploy directory.
The QBA 4 can deploy arbitrary QBeans in individual nodes, but the expected configuration will have just two initial qbeans:
• 00_logger
• 02_qcluster
Tip
If for some reason Q2 has to be restarted, the restart scripts should remove all XML descriptors in the deploy directory and just install pristine versions of 00_logger.xmland02_qcluster.xml
6.2.1. Dependencies
QCluster requires the following modules:
• hibernate • hibernate_xxx • eecore
6.3. Java Service Wrapper
wrapper.sf.net
This module integrates TanukiSoftware's Java Service Wrapper [http://wrapper.sf.net] with Q2 in order to start Q2 as an NT-Service (when running in a Windows environment) as well as to control and monitor a running Q2 in a Linux environment (see wrapper's website in order to easily add support for additional platforms). We provide two different jPOS-EE modules, wrapper_linuxandwrapper_windows.
Both of them provides a wrapper configuration file cfg/wrapper.conf as well as abin/q2wrapper that can be
used to start, stop, install and remove the wrapper.
Note
Current configuration assumes that we are running jPOS-EE out of a singlejar, so you have to call ant singlejar while producing your distribution. If running in 'singlejar mode' is not desirable, you
can edit cfg/wrapper.conf in order to add additional jars to the classpath (i.e: wrap-per.java.classpath.n=lib/xxx.jar)
6.3.1. Credits
Bharavi Gade has been of great help in the development and testing of this module in the Windows environ-ment. His feedback has been backported to the Linux version as well.
6.4. HA Service
jPOS High Availability Service uses JGroups in order to create a cluster of nodes where one of the node is voted as a MASTERand the rest are SLAVES.
HA Service uses three external scripts that will get called whenever a node becomes a master, becomes a slave, or the cluster changes somehow.
<ha-service class="org.jpos.ha.HAService" logger="Q2">
<property name="group-config" value="cfg/ha.xml" /> (1) <property name="group-name" value="jPOS-HASERVICE" /> (2) <property name="up" value="cfg/up.sh" /> (3) <property name="changed" value="cfg/up.sh" /> (4) <property name="down" value="cfg/down.sh" /> (5) </ha-service>
(1) JGroups configuration. cfg/ha.xmluses JGroups' 2.2.8 default.xml configuration.
(2) The cluster's name. Any valid JGroups name would do.
(3) A script to be called whenever a node is elected as the MASTER. (4) A script to be called whenever the group changes.
(5) A script to be called whenever a node becomes a SLAVE.
It is up to the system designer to create suitableup, downand eventually changedscripts.
These scripts can copy QBean XML descriptors off temporary directories into the deploy directory in order to run the MASTERor theSLAVE.
In addition, we found very useful to use an alias IP address for the cluster, and have the MASTER stand-in using
that alias.
Sample up.sh script
/sbin/ifconfig eth0:10 192.168.1.10
send_arp eth0 192.168.1.10 001122334455 192.168.1.10 ffffffffffff
Sample down.sh script
/sbin/ifconfig eth0:10 down
6.4.1. Credits
Dave Bergert has been instrumental in the development, testing and fine tuning of jPOS HA Service. He's also in charge of several mission-critical jPOS based clusters using it.
6.5. ReplicatedSpace
ReplicatedSpace is a distributed/replicated Space implementation that uses JGroups for its underlying com-munication.
Note
This is an experimental jPOS-EE module. Use it at your own risk.
6.5.1. Usage
In order to use the ReplicatedSpace you need to deploy a simple QBean like this:
<rspace class="org.jpos.space.ReplicatedSpaceAdaptor" logger="Q2">
<property name="space" value="tspace:rs1" /> (1) <property name="rspace" value="rspace:rspace" /> (2) <property name="group" value="rspace" /> (3) <property name="config" value="cfg/jgroups.xml" /> (4) <property name="trace" value="true" /> (5) </rspace>
(1) The ReplicatedSpace uses a local space as its underlying storage. You can use for example a tspace or a jdbmkind of space, i.e: "tspace:rs1" "jdbm:rs1". If you choose to use a jdbmspace running on different
JVMs running in the same physical node, you need to use different storage files.
(2) The replicated space registers itself with the given uri, (i.e: rspace:rspace so you can use the Space-Factoryto locate it within your application.
(3) This is the JGroups group name. Different ReplicatedSpaces should use different group names. In
addi-tion, if you use the jPOS-HA service, you want to use a different group name too.
(4) JGroups configuration. The file cfg/jgroups.xmluses JGroups' 2.2.8 default.xml configuration.
(5) If true, the ReplicatedSpace will output useful debugging information to the Logger.
6.5.2. Implementation notes
The ReplicatedSpace uses group communications among multiple nodes. It sends requests defined in an inner
class ReplicatedSpace.Request.
As of this writting, it uses the following 4 message types:
Table 6.1. Message types
Operation Description
OUT When you callrs.out(key, data), a Request.OUTis sent to all members. The
request carries the key for that entry, its data, a timeout, and also a unique identi-fier for the entry called the reference key (refkeyfor short).
The receiving nodes will store the value and timeout using the reference key, and a pointer to it using the actual key. (see ReplicatedSpace.Ref inner class).
MOVE_REQUEST When a node wants toinpand entry, it creates a unique [local] reference key and
sends aMOVE_REQUESTmessage to the coordinator.
The coordinator verifies its local space in order to double-check that the given ref was not taken by another node recently. The procedure involves keeping a local revocation cache [which defaults to 5 minutes]).
This is a unicast message sent from the node requesting the entry to the coordinat-or.
Operation Description
MOVE_DENIED If the coordinator doesn't have the requested entry or a revocation is found in its cache, a unicastMOVE_DENIEDis sent to the requesting node.
MOVE If the coordinator finds that the entry is suitable to be taken by a node (available in the local space and not present in the revocation cache) it will inmediately broadcast aMOVErequest to all nodes.
The entry will be available in all nodes under the requested reference key, but un-linked from its former key during one minute. After that short period of time, it will expire.
The requesting node will be waiting for that particular reference key and will take it in order to use it as the return object for its inpoperation.
This prototype implementation is work in progress and it has a number of known limitations:
• If the cluster is broken and we get to have more than one coordinator, it is possible for two nodes to take the same entry using the inpoperation.
• For performance reasons the OUT operation doesn't go throw the coordinator, so it is possible for two nodes to have entries for a given key in different order.
Going throw the coordinator is an easy task (see MOVE_REQUEST implementation) and we can easily make
this optional through a configuration parameter.
• If a new node joins the the cluster, old entries won't be available. We plan to solve this by adding a Re-quest.SENDMEkind of message.
• When multiple nodes are waiting for the same key and a new entry under that key arrives, all of them will compete to get it and although only one will succeed, the procedure is far from optimal. We need to devise an algorithm where the sender could attempt a unicast based distribution, probably combined with the pro-posedRequest.SENDMEmessage.
Given these limitations, we still find that the current implementation can be very useful to create ad-hoc distrib-uted applications. For example, it is very easy to have a ChannelAdaptor operate over a ReplicatedSpace, or have multiple TransactionManagers pull work off a ReplicatedSpace.
Tip
We strongly recommend using the ReplicatedSpace in an environment where all entries are volatile and have a short duration (in the couple of minutes range). If the application doesn't expect to have long lasting entries, a broken/merged cluster will self-heal in a short period of time.
As a side effect of the way we've choosen to implement the ReplicatedSpace using an underlying local space, one can have access to that local space and pull entries directly from it (by calling its inp operation). That
means that a node can outentries on the replicated space and more than one node can inp them if it uses a
ref-erence to the local space instead of a refref-erence to the replicated one.
Note
We are using JGroups' default configuration, but we there's a lot to experiment in that area by using
different protocol stacks according to the user's requirements, cluster topology, etc. Experimental
Appendix A. Copyright
---BEGIN PGP SIGNED MESSAGE---Hash: SHA1
jPOS Extended Edition
Copyright (C) 2004 Alejandro P. Revilla jPOS.org (http://jpos.org)
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---BEGIN PGP
SIGNATURE---Version: GnuPG v1.2.5 (GNU/Linux)
iD8DBQFBpxdka0iHlm4vot8RAld3AKCVuAamFtarD17EKOE2LWhPlcKZhQCfQH83 Ofdt+g6zW6En7gBLr1kIoCE=
=Ec4i
SIGNATURE---Appendix B. License
GNU GENERAL PUBLIC LICENSE Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: