RemoteXerver

RemoteXerver User's Guide

Table of Contents

Introduction

Welcome to RemoteXerver. This is the 1.0 version.

What is RPC?

RPC allows one program to make a procedure call to the other program. Since the two systems may be on different computers or even opposite end of the world this is referred to as a Remote Procedure Call (RPC). RPC communication occurs between two programs. The Client side is the one that initiates the RPC and the Server side is the one that executes the desired procedure and returning the results. Client and Server can also be on the same machine. The relationship of the two applications is what determines which is the Client and which is the Server.

What is XML-RPC?

XML-RPC is a simple, portable way to make remote procedure calls over HTTP (Hypertext Transfer Protocol – the way browsers communicate with servers over the Web). It uses a standardized XML document to hold the request and response for the RPC. What happens is the Client application calls a separate application, known as an XML-RPC Client, telling it where to find a desired Server application, what procedure to call, and what variable to pass to it. The XML-RPC Client is responsible for wrapping all this up in an XML document and sending it to an application on the Server. This application is an XML-RPC Service. The XML-RPC Service reads the XML doc and figures out how to handle it. It calls the Server application, gets the results, wraps them into another XML doc and passes it back to the XML-RPC Client. The XML-RPC Client then passes the results back to the Client application.

The benefit of XML-RPC is that it uses a standard XML document for communication. This means that the Client and Server sides can be written in completely different languages by different people. As long as they both know the procedures and variables that will be passed the whole process should work.

Please visit the XML-RPC Home Page for more information.

What is RemoteXerver?

RemoteXerver is an XML-RPC framework written in the ProvideX programming environment. This allows programs written in PVX running on one system to communicate with programs on another system over the Internet. Since XML-RPC is an industry standard, RemoteXerver allows PVX programs to communicate with programs written in any other programming languages. Because of this, PVX programs can communicate with web-enabled devices such as PDAs and Cell Phones.

Installing RemoteXerver

Preparation

You must have a working/licensed copy of ProvideX into which RemoteXerver will be installed. If you are going to be creating server side applications you must already have installed and setup you ProvideX WebServer.

Included in the Installation

The RemoteXerver installation contains the following files:

 remx/array.pvc
remx/base64.pvc
remx/boolean.pvc
remx/datetime.pvc
remx/double.pvc
remx/httpconnection.pvc
remx/integer.pvc
remx/remotexerver.default.conf
remx/remxbase.pvc
remx/saxparser.pvc
remx/string.pvc
remx/struct.pvc
remx/urlconnection.pvc
remx/xmlrpcclient
remx/xmlrpcclient.pvc
remx/xmlrpcerrorhandler
remx/xmlrpcservice.pvc
remx/docs/license.txt
remx/docs/usersguide.html
remx/docs/api/classes.html
remx/docs/api/pvxdoc.css
remx/docs/images/diagram1.png
remx/docs/images/remxconf1.png
remx/docs/images/remxconf2.png
remx/docs/images/remxlogo.png
remx/docs/images/webconfig.png
remx/samples/HelloWorld
remx/samples/HelloWorld2
remx/samples/HelloWorldClient
remx/samples/HelloWorldClient2
remx/wwwroot/index.html
remx/wwwroot/remxconf
remx/wwwroot/xmlrpc








IMPORTANT:
Application programs need to be able to access RemoteXerver programs/objects using the remx path as part of their names. For example – in order to create a string object, the application program must be able to access it as "remx/string". Therefore, the directory in which remx resides must be part of you PREFIX. But, the remx directory itself must not be part of your PREFIX. The simplest way to achieve this is to install RemoteXerver to the ProvideX start directory.

Windows Installation

Linux and Unix Installations

 umask 0
cd /pvx
tar xvf /tmp/remotexerver.tar

Setting up RemoteXerver

Setting up remotexerver.conf

RemoteXerver uses the file 'remotexerver.conf' for settings and license information. The remotexerver.conf file is purposely not included in the distribution so that future installations will not overwrite your configuration. But, a sample/default settings file 'remotexerver.default.conf' is included. If a 'remotexerver.conf' file has not been setup when RemoteXerver first launches it will copy the default file. 

#
# This is the RemoteXerver configuration file.
#

###
#
# LICENSE needs to be set to the license key assigned to
# your ProvideX. If you have multiple license keys add
# them to one line with a space separating them.
#
#LICENSE xxxxx yyyyy

###
#
# PREFIX must be set for the XMLRPC service to find and load
# your application programs.
#
#PREFIX "c:\Program Files\Best Software\ProvideX\"

###
#
# NO_XML_DEF can be set to ommit the XML Definition
# ("<?xml version="1.0" encoding="ISO-8859-1"?>")
# from your response. Any value will set the flag
#
#NO_XML_DEF 1

###
#
# Other user defined string variables can be set here. %REMX will be
# prepended and made available at runtime.
# Example: 'TIMEOUT 10' will set %REMX.TIMEOUT$="10"
#

Comment lines start with a '#' and are not processed. All other lines are processed as parameter assignments. The first word of the line is the parameter to be assigned and must be a valid variable name in ProvideX (Note: all parameters are string variables. But, the parameter must not end in a '$'). The parameter is separated from it's value by a space - do not use an '=' sign. The parameter will be set to everything that follows on the line. The parameter will be prepended with '%REMX.' when it is created in ProvideX.

RemoteXerver looks for 3 specific values: LICENSE, PREFIX, and NO_XML_DEF.

LICENSE

The LICENSE parameter is assigned to your particular installation of ProvideX by HighTower. RemoteXerver requires a separate license for client and server. Therefore, If you are going to use both the client and the server potions of RemoteXerver you will require 2 licenses. They both can be entered on one line with a space separating them.

PREFIX

On the server, it may be necessary to assign additional PREFIX settings for your application. The prefixes that are assigned in the config file will be appended to the PREFIX list generated when ProvideX launches.

NO_XML_DEF

NO_XML_DEF can be set to omit the XML Definition '<?xml version="1.0" ?>' from your response. Any value will set the flag.

Setting up the WebServer

As mentioned earlier, If you are going to be creating server side applications you must already have installed and setup you ProvideX WebServer. Once the PVX WebServer is installed and functioning all that needs to be done is to create a new Server that points to the directory where RemoteXerver is installed.

As illustrated above, a server RemoteXever is created on TCP Socket port 8081 (This port number is chosen for testing purposes only. For production servers please choose a proper port number.) The Root Directory is set to point you the 'remx/wwwroot' directory in our PVX installation. The Default Document is set to 'index.html'.

Testing the WebServer

A sample page is included with the installation in order to test the setup. Simply use a web browser to to go to the index.html document. In the sample it would be http://localhost:8081/

The Validate link will bring you to a generated page that will display all the settings that are currently in RemoteXerver.

XML-RPC Explained

Process Flow Diagram



Step 1: On the client side, when a program needs to communicate to the server, it passes the request to the XmlRpcClient.
Step 2: The XmlRpcClient then wraps up the information and packages it in an XML document which is sent over the Internet to the server.
Step 3: The XmlRpcService running on the server then reads this XML document, figures out what the request is, and passes the information to the desired program.
Step 4: The program returns its results to the XmlRpcService.
Step 5: The XmlRpcService packages the results in another XML document and returns it to the client.
Step 6: The XmlRpcClient reads the XML response, figures out the results, and passes them to the original program.

Request example

Here's an example of an XML-RPC request. The request XML document is enclosed in an HTTP POST:

POST /xmlrpc HTTP/1.0
Host: 127.0.0.1
Content-Type: text/xml
Content-length: 252

<?xml version="1.0"?>
<methodCall>
<methodName>WhsService.CheckQty</methodName>
<params>
<param>
<value><string>Widget2000</string></value>
</param>
<param>
<value><string>001</string></value>
</param>
<param>
<value><double>0</double></value>
</param>
</params>
</methodCall>

Header requirements

The format of the URI in the first line of the header is not specified. For example, it could be empty, a single slash, if the server is only handling XML-RPC calls. However, if the server is handling a mix of incoming HTTP requests, we allow the URI to help route the request to the code that handles XML-RPC requests. (In the example, the URI is /xmlrpc, telling the server to route the request to the "xmlrpc" responder.)

A User-Agent and Host must bespecified. The Content-Type is text/xml.

The Content-Length must be specified and must be correct.

Payload format

The payload is in XML, a single <methodCall> structure.

The <methodCall> must contain a <methodName> sub-item, a string, containing the name of the method to be called. The string may only contain identifier characters, upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon and slash. It's entirely up to the server to decide how to interpret the characters in a methodName.

For example, the methodName could be the name of a file containing a script that executes on an incoming request. It could be the name of a cell in a database table. Or it could be a path to a file contained within a hierarchy of folders and files.

If the procedure call has parameters, the <methodCall> must contain a <params> sub-item. The <params> sub-item can contain any number of <param>s, each of which has a <value>.

Scalar <value>s

<value>s can be scalars, type is indicated by nesting the value inside one of the tags listed in this table:

Tag

Type

Example

<i4> or <int>

four-byte signed integer

-12

<boolean>

0 (false) or 1 (true)

1

<string>

string

hello world

<double>

double-precision signed floating point number

-12.214

<dateTime.iso8601>

date/time

19980717T14:08:55

<base64>

base64-encoded binary

eW91IGNhbid0IHJlYWQgdGhpcyE=


If no type is indicated, the type is string.

<struct>

A value can also be of type <struct>.
A <struct> contains <member>s and each <member> contains a <name> and a <value>.

Here's an example of a two-element <struct>:

<struct>
<member>
<name>lowerBound</name>
<value><i4>18</i4></value>
</member>
<member>
<name>upperBound</name>
<value><i4>139</i4></value>
</member>
</struct>

<struct>s can be recursive, any <value> may contain a <struct> or any other type, including an <array>, described below.

<array>

A value can also be of type <array>. An <array> contains a single <data> element, which can contain any number of <value>s.

Here's an example of a four-element array:

<array>
<data>
<value><i4>12</i4></value>
<value><string>Egypt</string></value>
<value><boolean>0</boolean></value>
<value><i4>-31</i4></value>
</data>
</array>

<array> elements do not have names.

You can mix types as the example above illustrates.

<arrays>s can be recursive, any value may contain an <array> or any other type, including a <struct>, described above.

Response example

Here's an example of a response to an XML-RPC request:
HTTP/1.1 200 OK
Connection: close
Content-Length: 142
Content-Type: text/xml
Date: Fri, 24 Jun 2005 17:20:38 GMT
Server: 127.0.0.1


<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>Widget2000</string></value>
</param>
<param>
<value><string>001</string></value>
</param>
<param>
<value><double>215</double></value>
</param>
</params>
</methodCall>

Response format

Unless there's a lower-level error, the XmlRpxService will always return 200 OK. The Content-Type is text/xml. Content-Length must be present and correct.

The body of the response is a single XML structure, a <methodResponse>, which can contain a single <params> which contains a single <param> which contains a single <value>.

The <methodResponse> could also contain a <fault> which contains a <value> which is a <struct> containing two elements, one named <faultCode>, an <int> and one named <faultString>, a <string>.

A <methodResponse> can not contain both a <fault> and a <params>.

Fault example

HTTP/1.1 200 OK
Connection: close
Content-Length: 426
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:02 GMT
Server: UserLand Frontier/5.1.2-WinNT


<?xml version="1.0"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>4</int></value>
</member>
<member>
<name>faultString</name>
<value><string>Too many parameters.</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>

Accessing XML-RPC Services with RemoteXerver

Here we'll take a look at how to use the RemoteXever Client to access XML-RPC services.

Basic – Using the XmlRpcClient Program

Let's start by making use of the XmlRpcClient program provided with RemoteXerver. This program is designed to make coding easier by allowing the developer to execute an XML-RPC request with a simple ProvideX CALL statement. The parameters that are passed in the CALL are automatically mapped to XML-RPC types and passed to Server. This can make development very easy, especially if the client and the server a being developed in ProvideX.

But, it is limited in one important way. The parameters being sent back by the service must match the types that were sent by the client. That is, if the client makes a CALL to a service and passes 2 strings and one numeric, the service must send back 2 strings and one numeric in the same order. 

Let's look at a very simple HelloWorld example:

10 ! HelloWorld
20 SayHello:
30 ENTER Name$
40 Name$ = "Hello "+Name$
50 EXIT

Here we have a simple program “HelloWorld” with an entry point “SayHello”. The program ENTERs a string into Name$, prepends it with “Hello “, and exits passing the new string back to the calling program.

Next we'll look at the HelloWorldClient:

10 ! HelloWorldClient
20 Param$ = "George"
30 CALL "remx/xmlrpcclient","http://localhost:8081/xmlrpc","HelloWorld.SayHello", Param$
40 PRINT "The Server Says: ",Param$

The call to XmlRpcClient uses the following syntax:

CALL "remx/xmlrpcclient",URI$,EndPoint$,Parameter-1[,Parameter-2,...,Parameter-n]

Where URI$ is the URI for the Server to be called, EndPoint$ is the Program and Method to execute, and Parameter-[1..n] are the parameters to be passed. The parameters may be any number of string and numeric variables.

At line 20 param$ is set to a value. Then, at 30 a call is made to the RemoteXerver xmlrpcclient. The first argument passed to the program is the URI for the server. The second argument passed is the program and method/entry point to be executed on the server. Standard XML-RPC uses a '.' to separate the program from the entry point. This is different from PVX which uses a ';'. With RemoteXerver you can use either '.' or ';' and it will generate the request properly. The last argument is the parameter to be passed to the server-side program. The xmlrpcclient program can accept any number of parameters to be passed to the server.

Here's the result of running the client:

>RUN "HelloWorld"
The Server Says: Hello George
>

Advanced – Using the XmlRpcClient Class

The xmlrpcclient program is actually a simple wrapper for the remx/xmlrpcclient class. The remx/xmlrpcclient class is where all the work is done. To use it directly requires an understanding of the array and struct classes.

10 ! HelloWorldClient2
20 Params = new("remx/array")
30 Params'Add(new("remx/string","George"))
40 Client = new("remx/xmlrpcclient","http://localhost:8081/xmlrpc")
50 Response = Client'Execute("HelloWorld.SayHello",Params)
60 PRINT "The Server Says: ",Response'Get(1)'Value$

At line 20 an array object is created to hold parameters that will be passed to the server. At line 30 a string initialized to "George" is added to the Params array. At line 40 the xmlrpcclient class is instantiated and set it to point to "http://localhost:8081/xmlrpc". Then, at line 50 the Process() method is called with the entry point "HelloWorld.SayHello" and Params object passed as parameters. The response is put into the variable Response which will be an array object. Finally, the first object held in the Response array is accessed with the Get() method and the value is displayed.

Here's another example using structs:

10 a = new("remx/array")
15 s = new("remx/struct")
20 s'addMember("sku",new("remx/string","widget"))
25 s'addMember("qty",new("remx/integer",50))
30 s'addMember("price",new("remx/double",3.45))
35 s'addMember("taxable",new("remx/boolean",1))
40 a'add(s)
45 o = new("remx/xmlrpcclient","")
50 o'setAddress("http://localhost:8080/xmlrpc")
55 r = o'execute("Order.GetExtension",a)

This example will generate the following XML-RPC Request Document:

<?xml version="1.0"?>
<methodCall>
<methodName>Order.GetExtension</methodName>
<params>
<param>
<struct>
<member>
<name>sku</name>
<value><string>widget</string></value>
</member>
<member>
<name>qty</name>
<value><i4>50</i4></value>
</member>
<member>
<name>price</name>
<value><double>3.45</double></value>
</member>
<member>
<name>taxable</name>
<value><boolean>1</boolean></value>
</member>
</struct>
</param>
</params>
</methodCall>

Publishing XML-RPC Services with RemoteXerver

We've already illustrated an XML-RPC Service with the HelloWorld program above. As shown above the URI looks for the document "xmlrpc". This is a wrapper program. All it does is initialize the RemoteXerver environment, instantiate the xmlrpcservice object and pass the request to it.

The simplest way to publish an XML-RPC Service is to create your application and make it visible to the webserver (that is - the program has to be able to be loaded by the webserver by way of the PREFIX). Please note that the application program that is the EndPoint (<program>.<entry point>) must be a PVX program and not an object and it must have an entry point.

Advanced – Working directly with the XmlRpcService Class

As noted above the remx/xmlrpcservice object manages much of the processing that takes place. It parses the incoming request, makes the call to the application, and then marshals up the results into a result array. During the call to the application program a number of global variables are available.

%REMX.NO_XML_DEF$
Flag assigned in the remotexerver.conf. If it is set to any value the <?xml version="1.0"?> header will not be a be added to the response document.
%REMX.PREFIX$
The PVX PREFIX assigned in the remotexerver.conf.
%REMX.LICENSE$
The License assigned in the remotexerver.conf.
%REMX.RequestXML$
The Request Document passed to the server from the Client. It is possible for the server application to access this document directly. Modifying this variable will have no affect on the server request or response.
%REMX.RequestArray
The request document parsed into a remx/array object. It will contain all the parameters as defined in the request document.
%REMX.RequestIolist$
The remx/xmlrpcservice tries to interpret the request as a list of string and numeric variables and create an iolist from this. If the request is too complex this string may be empty.
%REMX.RequestRecord$
If remx/xmlrpcservice is able to build a %REMX.RequestIolist$ this will contain the corresponding data in a PVX record format.
%REMX.MethodName$
The method name contained in the <methodName> tag.
%REMX.ResultArray
%REMX.ResultArray is not instantiated when the application code is executed. But, if the application instantiates it and adds results to it, the remx/xmlrpcservice will use this array to build the response.
%REMX.FaultCode
%REMX.FaultCode is a numeric variable and is set to zero when the application is executed. If the application sets this to a non-zero value a fault response will be generated with this and %REMX.FaultString$.
%REMX.FaultString$
%REMX.FaultString$ is set to "" when the application is executed. If the application sets this to any string value a fault response will be generated with this and  %REMX.FaultCode.

In addition to these variables, any variables you setup in the remotexerver.conf file will also be available to your application.

The following is the HelloWorld re-written using the RemoteXerver classes.

10 ! HelloWorld2
20 SayHello:
30 Name$ = %REMX.RequestArray'Get(1)'Value$
40 Name$ = "Hello "+Name$
50 %REMX.ResultArray = new("remx/array")
60 %REMX.ResultArray'Add(new("remx/String",Name$))
70 EXIT

Here is a possible implementation of the prior Order.GetExtension example:

10 ! Order
15 GetExtension:
20 s = %REMX.RequestArray'Get(1)
25 sku$ = s'GetMember$("sku")
30 qty = s'GetMember("qty")
35 price = s'GetMember("price")
40 ext = qty * price
45 r = new("remx/struct")
50 r'AddMember("sku",sku$)
55 r'AddMember("extension",new("remx/double",ext))
60 %REMX.ResultArray = new("remx/array")
65 %REMX.ResultArray'Add(r)
70 EXIT

Note that at line 50 the 'Sku' member is assigned directly to a string rather than new("remx/string",sku$). This is a convenience method in 'remx/struct'. See the Class Index for information on the classes available in RemoteXerver.

This example will generate the following XML-RPC Response Document:

<?xml version="1.0"?>
<methodCall>
<methodResponse>
<params>
<param>
<struct>
<member>
<name>sku</name>
<value><string>widget</string></value>
</member>
<member>
<name>extension</name>
<value><double>172.5</double></value>
</member>
</struct>
</param>
</params>
</methodResponse>

XML <-> ProvideX Data Mapping in RemoteXerver

Mapping XML-RPC tags to RemoteXerver objects

As mentioned earlier, RemoteXerver makes use of ProvideX objects. RemotXerver provides a number of objects to encapsulate data types used in XML-RPC. The chart below describes how XML-RPC value tags are mapped to RemoteXerver data objects. In addition to these data objects RemoteXerver also has collection objects to help map to certain XML structures used by XML-RPC.

Standard mappings from XML-RPC to ProvideX

Tag

Type

i4,int

remx/integer

boolean

remx/boolean

double

remx/double

string

remx/string

dateTime.iso8601

remx/datetime

Base64

remx/base64



Glossary

XML
The Extensible Markup Language (XML) is a W3C-recommended general-purpose markup language for creating special-purpose markup languages. It is a simplified subset of SGML, capable of describing many different kinds of data. Its primary purpose is to facilitate the sharing of data across different systems, particularly systems connected via the Internet. Languages based on XML (for example, RDF, RSS, MathML, XHTML, SVG, and cXML) are defined in a formal way, allowing programs to modify and validate documents in these languages without prior knowledge of their form.
URI
A Uniform Resource Locator or Web address, is a standardized address name layout for resources (such as documents or images) on the Internet (or elsewhere). Every URL is a type of Uniform Resource Identifier (URI)
URI
A Uniform Resource Identifier (URI), is an Internet protocol element consisting of a short string of characters that conform to a certain syntax. The string comprises a name or address that can be used to refer to a resource. It is a fundamental component of the World Wide Web.
TCP
The Transmission Control Protocol (TCP) is one of the core protocols of the Internet protocol suite. Using TCP, applications on networked hosts can create connections to one another, over which they can exchange data. The protocol guarantees reliable and in-order delivery of sender to receiver data. TCP also distinguishes data for multiple, concurrent applications (e.g. web server and email server) running on the same host.
Socket
A socket on a certain host is defined as the combination of an IP address, a protocol, and a port number. The PVX WebServer refers to the PORT number as the socket.
Port
A software network port is an identified doorway (address) for communicating between a program and another communications system or program often passing through a hardware port. The network port is usually numbered and a standard network implementation like TCP will attach a port number to data it sends. In the examples given, 8081 is used as the port number for the RemoteXerver server. This is for internal testing only. Be careful choosing a port for your production server as many port numbers are pre-assigned to certain protocols. Please refer to your  PVX WebServer manual.