XML 'Ping Pong'
This is a particularly simple example, intended to illustrate the construction of xml-space command documents, and their use.
This example involves the repeated exchange of 'ping' and 'pong' xml messages between two xml-space clients.
The first client inserts 'ping' messages into the space, and then waits for a reply. The second client receives the 'ping'
message from the space, and returns a 'pong' message, which is then received by the first client; which then continues this
process, in a loop.
In this example, the xml-space command documents are constructed explicitly by string manipulation, in more complex
situations this xml is usually constructed using a dedicated utilities library.
The three relevant xml command documents are listed below. It will be seen that the pinger uses two command documents,
the first inserts a 'ping' message, and the second extracts a 'pong' message; whereas the 'ponger' only uses one document
- which contains the complementary operations. This difference is to avoid a possible xml-space transaction deadlock,
as explained in the final section.
Implementation Details
The xml-space clients insert and receive their messages using the simple xml-space operations:
- <operation-put />
- <operation-take />
The source-code for the Pinger.java and Ponger.java classes can be viewed by following these links:
The xml command documents that are used in this example are shown below. Note, the simple nature of this example means that,
providing there are no errors, we do not need to process the xml response documents that are returned by the xml-space server.
XML-Space Command Listings
The listings below show the structure of the xml command files that are sent to the xml-space server. The outer document
element is an <xmlspace-commands> element, which can contain one or more
<xmlspace-operation-set> elements. For a brief explanation of the role of these elements,
see the page describing the RCRT
XML-Space API.
(i) 'Pinger' - XML Listing To Send a 'Ping' Message
In this listing, there is a single <operation-put> space-operation, enclosed within a single
operation-set. This operation inserts one 'ping' xml entry into the xml-space. The ping entry's header
contains a single 'count' attribute. The space-entry's description element is also populated;
the description is used if the contents of the space are listed.
<?xml version='1.0' ?>
<xmlspace-commands>
<xmlspace-operation-set>
<operation-put>
<space-entry xtype="ping">
<description>a ping message.</description>
<header>
<attribute name="count" value="#count" />
</header>
<body />
</space-entry>
</operation-put>
</xmlspace-operation-set>
</xmlspace-commands>
Note: In the above '#count' represents an integer variable.
(ii) 'Pinger' - XML Listing To Receive a 'Pong' Message
In this listing, a single <operation-take> xml-space operation is enclosed within an
<xmlspace-operation-set>. The operation has a timeout of 60000 mS (one minute),
and includes a template against which the required entries are matched. In this case, only the xtype of the entry
is used for matching (an entry of type 'pong') is required, there is no additional 'attribute matching' or xml 'xpath matching'
criteria.
<?xml version='1.0' ?>
<xmlspace-commands>
<xmlspace-operation-set>
<operation-take result-id="reply" timeout="60000">
<space-entry-template xtype="pong">
<header />
</space-entry-template>
</operation-take>
</xmlspace-operation-set>
</xmlspace-commands>
(iii) 'Ponger' - XML Listing To Receive a 'Ping' and then Send a 'Pong' Message
In this listing, there are two <xmlspace-operation-set> elements enclosed within a single
<xmlspace-commands> element. The first operation-set contains the operation to take a 'ping'
entry from the space, whilst the second contains the operation to put a 'pong' entry into the space.
Since these two operations are in consecutive operation-set elements, the 'put' operation will only be executed
after the 'take' operation has completed.
<?xml version='1.0' ?>
<xmlspace-commands>
<xmlspace-operation-set>
<operation-take result-id="reply" timeout="3600000">
<space-entry-template xtype="ping">
<header />
</space-entry-template>
</operation-take>
</xmlspace-operation-set>
<xmlspace-operation-set>
<operation-put>
<space-entry xtype="pong">
<description>a pong message.</description>
<header>
<attribute name="Ponger" value="#name" />
</header>
<body />
</space-entry>
</operation-put>
</xmlspace-operation-set>
</xmlspace-commands>
Note: In the above '#count' represents an integer variable.
Avoiding Deadlock - XML-Space Transactions
It might be noticed in the above, that the 'pinger' uses two separate xml-space calls, whereas the 'ponger' only uses one call;
but that this call includes two separate space operations. This arrangement is to prevent a 'space deadlock' from occurring,
as explained below:
In this example, each xml-space 'commands' call has been made within the scope of its own xml-space transaction. When
the ponger's space operations execute, they are both within the scope of a single transaction. When this transaction is committed,
the removal of the 'ping' message and the insertion of the 'pong' messages are both committed at the same time. At this point
the 'pong' message becomes visible to other clients outside of their local transaction-space, and can be collected by the 'pinger'.
However, if both of the 'pinger's operations were also within the scope of a single transaction, then a deadlock would result
- each client's message would only become visible to the other when the other's message had already been received, which would
never happen. The simplest way to avoid this situation is to ensure that the 'pinger's two operations are in isolated transaction
spaces.