Online documentation - Websydian v6.5 |
Introduction Implementing Other Uses Parts Tutorial Glossary
Please note that support for RPC web services are introduced in Websydian version 6.1 and in the TransacXML import tool version 2.0.
If you are using an earlier version of Websydian, you can still implement most RPC based services, but some of the abstract Plex objects supporting this and some of the functionality described for the SOAP generator are not available.
In the SOAP standard, two distinct ways of looking at web services are described:
Unfortunately, this distinction has been allowed to have quite significant implications for the implementation of web services (the SOAP standard) and for the description of web services (the WSDL standard). In many cases, the implementation and descriptions of the two different kinds of web services are completely separate.
There is no real reason for this, as you can describe a RPC based service as a service that can receive a document - handle a document (by calling the function that is being wrapped) - and return a response document, which is exactly what a document based service does.
This document will describe how RPC based services are modeled in TransacXML and how you can call these services. There will also be an introduction to RPC encoded web services and how to handle these services.
This document does not provide a full explanation of RPC based web services - see the further reading section at the end of the document for more information.
Understanding this document will be helped by some experience/understanding of the implementation of document based web services in TransacXML, but it should not be a necessity.
This document will focus on how to call RPC based web services.
If you are going provide a web service, we strongly recommend that you implement a document based web service.
A simple example of an RPC based web service could be if you have a function GetCustomer that receives the customer number as an input field - and returns the name and address as output fields.
This means that the function signature would be like this:
Name:
GetCustomer
Input:
CustomerNumber
Output:
CustomerName
CustomerAddress
The request document created for the service would look like this:
And the response document would look like this:
The top element of the request document has the same name as the function, the one input parameter is added as a simple element that is scoped by the top element.
The top element of the response document has the name of the function, with "Response" added, the two output parameters are added as simple elements scoped by the top element.
When this service is implemented as a SOAP based service, the request and response documents will be wrapped in a SOAP envelope - but to keep this example simple, the SOAP wrapping is not shown here.
As can be seen, these are normal XML documents that could just as well have been described and handled as when using the document based web services.
When extending the support of TransacXML to RPC based web services, we have attempted to make the implementation of these services as close to the implementation of the document based services that has been supported by TransacXML for a long time.
So just as for document based web services, what you need to do is to model the request and response documents in Plex using the TransacXML abstract entities and fields.
You can do this modeling in two ways:
RPC-encoding is a subset of the RPC-based services. RPC-encoded services are implemented much as described above - but each parameter also contains a definition of the type of the parameter.
As an example - the function described above, could be implemented as follows when accessing an RPC-encoded service:
The request document:
The response document:
The interesting difference is the xsi:type attributes - for each parameter this specifies the type of the data contained in the parameter.
It is important to note that the name of the parameter field isn't significant - but the sequence and the type definition are.
As for the basic RPC-based web services, you must model the request and the response documents in Plex to be able to call an RPC-encoded web service.
You can do this in two different ways:
The first example will show how to model the response document shown above.
Define the following triples:
Source Object | Verb | Target Object |
---|---|---|
GetCustomerResponse | is a ENT | WSYXML/XMLElement |
GetCustomerResponse.Fields | field FLD | CustomerName |
GetCustomerResponse.Fields | field FLD | CustomerAddress |
GetCustomerResponse.Fields.CustomerName | is a FLD | WSYXML/ElementField |
GetCustomerResponse.Fields.CustomerName | is a FLD | WSYXML/EncodedField |
GetCustomerResponse.Fields.CustomerAddress | is a FLD | WSYXML/ElementField |
GetCustomerResponse.Fields.CustomerAddress | is a FLD | WSYXML/EncodedField |
GetCustomerResponse | has FLD | GetCustomerResponse.Fields.CustomerName |
GetCustomerResponse | has FLD | GetCustomerResponse.Fields.CustomerAddress |
The new feature compared to the modeling that would have been done for the basic RPC service is the inheritance from the EncodedField field.
By specifying this inheritance, you get three source codes scoped by the field:
The following values must be specified for the source codes:
GetCustomerResponse.Fields.CustomerName.Type: string
GetCustomerResponse.Fields.CustomerName.TypeNamespace: http://www.w3.org/2001/XMLSchema
GetCustomerResponse.Fields.CustomerName.TypePrefix: xsd
GetCustomerResponse.Fields.CustomerAddress.Type: string
GetCustomerResponse.Fields.CustomerAddress.TypeNamespace: http://www.w3.org/2001/XMLSchema
GetCustomerResponse.Fields.CustomerAddress.TypePrefix: xsd
The InsertRow function will create the type attributes and insert the values specified in the source code, as well as defining the necessary namespace declarations for the namespaces specified for the values. This means that the input to the InsertRow will only contain two fields (the name and the address).
The example shown above is relatively simple as each parameter is a simple element (a field) - but it is also possible to implement more complex structures for each parameter.
For instance if the function reading the customer returns a structure as the return parameter, the content of this structure must be defined in the "types" section of the WSDL describing the service. The example response document could look like this:
In this case, the parameter is the CustomerData complex element - so this is where the type definition is placed. MyCustomerDataType must be defined in a schema describing the namespace http://www.MyServer/MyTypes, which must be available in the WSDL describing the service.
So in this case, it is not the fields that is encoded, it is a complex element.
This can be modeled as follows:
Source Object | Verb | Target Object |
---|---|---|
GetCustomerResponse | is a ENT | WSYXML/XMLElement |
GetCustomerResponse | includes ENT | CustomerData |
GetCustomerResponse.CustomerData | is a ENT | WSYXML/XMLElement |
GetCustomerResponse.CustomerData | is a ENT | WSYXML/EncodedElement |
GetCustomerResponse.CustomerData.Fields | field FLD | CustomerName |
GetCustomerResponse.CustomerData.Fields | field FLD | CustomerAddress |
GetCustomerResponse.CustomerData.Fields.CustomerName | is a FLD | WSYXML/ElementField |
GetCustomerResponse.CustomerData.Fields.CustomerAddress | is a FLD | WSYXML/ElementField |
GetCustomerResponse.CustomerData | has FLD | GetCustomerResponse.CustomerData.Fields.CustomerName |
GetCustomerResponse.CustomerData | has FLD | GetCustomerResponse.CustomerData.Fields.CustomerAddress |
The inheritance from EncodedElement means that the entity CustomerData will scope three new source code objects:
The following values should be specified in this example:
GetCustomerResponse.CustomerData.Type: MyCustomerDataType
GetCustomerResponse.CustomerData.TypeNamespace: http://www.MyServer/MyTypes
GetCustomerResponse.CustomerData.TypePrefix: mn
When the GetCustomerResponse.CustomerData.InsertRow function is called, the values from these source codes will be used to automatically insert the type attribute and the namespace declaration needed for declaring that the mn prefix is to indicate the http://www.MyServer/MyTypes namespace.
As mentioned above, if you are going to provide a web service, we strongly recommend that you use a document based web service.
When you are going to call (consume) a web service, you often do not have this option. In these cases you have to be able to call the service - and to create the request document according to the specifications for the service.
In most cases, the provider will provide a WSDL file describing the service. If the providers doesn't do so, you should ask for one - it is the most commonly accepted way of describing web services. When you have the WSDL, use the TransacXML import tool to create the Plex definitions for the request and response documents.
If you absolutely cannot obtain a WSDL, you must create the definitions yourself as outlined above.
The rest of the implementation is made exactly as it is described for document base web services in the tutorial, with one small exception. In most cases RPC based web services do not specify a SOAP Action for identifying the specific operation to call. Instead the name of the top element in the request document is used to identify the operation (as this will be the name of the function that is wrapped). If this is the case, just specify *Blank for the SOAP Action parameter on the call to the CallSoapGenerator function - when this is done, no SOAPAction header is sent.
The implementation of the RPC based web services targets calling (consuming) services, not providing them. The side effect of this is that the CreateWSDL function only generates WSDLs for document based services.
The CreateWSDL function disregards the inheritance from EncodedField/EncodedElement and will define all operations and messages as document/literal.
RPC-encoded arrays are not supported by the WSDL import (See WSDL import limitiations).
Other informative documents:
http://msdn.microsoft.com/en-us/library/ms996466.aspx
http://www-128.ibm.com/developerworks/webservices/library/ws-whichwsdl/