| Allegro CL version 7.0 Significantly revised from 6.2. | |||||||
This document contains the following sections:
1.0 PrefaceThis document describes an implementation of the Allegro CL SOAP API. There are still pieces of the Allegro CL/SOAP implementation to be completed. These will be released when they are ready.
The Implementation Plan for the Allegro/SOAP API is as follows. Note that dates in the future are tentative.
See Release notes for SOAP in release-notes.htm.
The Allegro CL SOAP Server needs AllegroServe version 1.2.30 (or
later) to work. Be sure you have that version of AllegroServe. Both
the Client and the Server need PXML version 7.0.1. The PXML version is
returned by the function net.xml.parser:pxml-version and is the
value of the variable
net.xml.parser::*pxml-version*.
You load the SOAP API into a running lisp with the following call to require:
(require :soap)
All the symbols in the SOAP API are exported from the
net.xmp.soap package.
There is a SOAP client example in examples/soap/soapex.cl. There is a SOAP server example in examples/soap/soapval1.cl.
The letters xmp stand for XML Message Protocol. The XMP component implements a separately documented API that is used as a basis for the SOAP implementation and for other XML-based message protocols such as XMLRPC.
Users may find it more convenient to try the SOAP examples in a Modern (case-sensitive) Allegro CL image. Since case in SOAP symbols is significant, SOAP symbols typically have mixed case print names. Modern mode handles mixed case names without special effort. If you use an ANSI (case-insensitive) Allegro CL image, SOAP symbols need to be wrapped in vertical bar escapes (as is done in the Simple Example just below) in order to preserve their mixed-case print names.
This simple example shows how to access a public SOAP server that returns currency conversion rates. (See also the file examples/soap/soapex.cl.)
The symbols in the "urn:xmethods-CurrencyExchange" namespace are exported from a Lisp package created for this purpose.
(require :soap) (use-package :net.xmp.soap) ;; This form ensures that XSD is a nickname of the NET.XMP.SCHEMA ;; package: (defpackage :net.xmp.schema (:use) (:nicknames :xs :xsd)) (defpackage :conv (:use) (:export "getRate"))
We define a function to send the message and decode the reply:
(defun convert (&optional (country1 "Canada") (country2 "USA"))
(let ((conn (soap-message-client
:lisp-package :keyword
:url "http://services.xmethods.net:80/soap")))
(call-soap-method
conn
'(:element
conv:|getRate|
(:complex (:seq (:element "country1" xsd:|string|)
(:element "country2" xsd:|string|)
)
:action ""
:namespaces
(nil (:conv "tns" "urn:xmethods-CurrencyExchange"))
))
:|country1| country1 :|country2| country2
)))
The main element of the message is defined (in line) as a complex type composed of a sequence of two elements "country1" and "country2". The content of each of these elements is declared to be a string. The information needed to create the element definitions must be obtained from the server documentation, often in the form of a WSDL file.
We try the function:
cl-user(4): (convert) ;SOAP Warning: Undefined element conv::getRateResponse ;SOAP Warning: Undefined element :Result (conv::getRateResponse (:Result 0.7212)) nil
The warning indicates that we failed to specify the data type of the main element in the reply. A strict interpretation of the SOAP specification would require us to reject the message.
The result message is returned as a nested list of association lists where element name is the key and element content is the value.
We can muffle the warning by declaring the type of the element:
cl-user(5): (defpackage :conv (:use) (:export "getRateResponse"))
#<The conv package>
cl-user(6): (define-soap-element nil
'conv:|getRateResponse|
'(:complex (:seq (:element "Result" xsd:|float|))))
(:complex (:seq (:element ("Result") net.xmp.schema:float)))
We try again:
cl-user(7): (convert) (conv:getRateResponse (:Result 0.7212)) nil cl-user(8):
The client API encodes Lisp data into a SOAP message and transmits the encoded HTTP message to the server. The reply from the server is another HTTP message that is decoded into Lisp data returned to the caller.
The server API defines Lisp functions that are called when specified messages are sent to the server. The messages arrive as encoded HTTP text and the value returned by the function is sent as an encoded HTTP reply message.
The XML elements in both outgoing and incoming messages must be defined in order to specify the required encoding and decoding behaviors.
An element definition specifies how an element should be encoded in a message to a server and how it can be decoded in a reply message.
An element definition can appear as a component in a Lisp list structure that describes a compound XML element:
element-def -> (:element elt-name-spec type-spec)
An element definition can also be created with a call to define-soap-element:
Arguments: conn elt-name-spec type-spec &rest def-options &key (redef :warn)
After a call to define-soap-element, any of the names listed in the elt-name-spec may be used to denote the defined element.
The conn argument may be nil but can also be used to define behavior specific
to a particular class of connections.
The elt-name-spec argument specifies one or more names by which the element can be identified. It is described below.
The type-spec argument may be the name of a separately defined SOAP type, the name of a built-in SOAP type or an anonymous type definition as defined in the next section.
The redef option controls the behavior when a definition already exists. The possible values are:
nil - silently replace the existing definition
:warn - print a warning if a definition exists and
is not equal to the new definition
t - signal an error (instead of a warning)
An elt-name-spec is defined as follows:
elt-name-spec -> symbol | string
-> ( { symbol | string | (:any-case string) }... )
When a SOAP message is created, the first (or only) name in
elt-name-spec determines the name included in the
message. The components of an elt-name-spec are:
string --> unqualified QName
symbol --> 1. If the symbol-package of the symbol has been
associated with a namespace
AND
the namespace is included in the current context,
THEN
the qualified QName is included in the message.
2. OTHERWISE the symbol name is included as an unqualified QName.
(:any-case string) --> treated like string above
When a SOAP message is decoded, any one of the names in the
elt-name-spec is accepted as a name for this
element.
string --> accept any string= QName in any namespace symbol --> accept the EQ symbol (:any-case string) --> accept any string-equal QName in any namespace
A type definition specifies the structure, content and attributes of an XML element. A type definition also specifies the encoding from Lisp to XML and the decoding from XML to Lisp.
A type definition can appear as a component in a Lisp list structure that describes a compound XML element:
type-def -> (:simple simple-type-spec simple-option... )
-> (:array type-spec array-option... )
-> (:complex complex-def complex-option... )
A type definition can also be created with a call to define-soap-type:
Arguments: conn name type-def &key (redef :warn)
Once defined, a type name may be used in other element or type definitions.
simple-type-spec -> nil | type-name
type-spec -> type-name | type-def
complex-def -> (collector complex-part ...)
collector -> :seq ;; zero or one of each part in specified sequence
-> :seq* ;; zero or more of each part in specified sequence
-> :seq+ ;; one or more of each part in specified sequence
-> :seq1 ;; exactly one of each part in specified sequence
-> :set ;; zero or one of each part in any sequence
-> :set*
-> :set+
-> :set1
-> :or ;; exactly one of the parts
The components of :seq :seq* :seq1 and :seq+ must be ordered as specified.
The components of :set :set* :set1 and :set+ may appear in any order.
When a complex element is encoded, the sub-elements are always encoded in the order listed in the definition.
complex-part -> element-spec | complex-def element-spec -> element-name | (:any} | element-def
When a complex-part denotes a sequence of elements the sequence is spliced into the sequence containing the complex-part.
Sub-element definitions enter only through an element-def with a :complex or :array type-def.
:action string - this option is needed on the
top-level element of a message to specify the content of the HTTP
SOAPAction header in the request to the server.
:length dims - this option specifies the dimensions
of an array. A single integer denotes a 1-dimensional array of that
length. A list of n integers denotes an n-dimensional array.
:send-atype type-name - Send a
enc:|arrayType| attribute with
type-name as the value.
:send-asize asize - If non-nil, include an array size in arrayType:
:array-item ([array-item-prop-name array-item-prop-val]
...) - This option provides additional detail about how an
array should be encoded. The possibilities for
array-item-prop-name and
array-item-prop-val are:
array-item-prop-name: array-item-prop-val:
:element element-spec
:send-type boolean
:attributes property-list
:argument arg-spec
This option specifies how array
elements are passed to the encoding
functions. The argument is a list
of element data items as follows:
arg-spec: data item:
:element-and-arg (element-spec data)
:type-and-arg (type-spec data)
:attributes-and-arg (property-list data)
:arg-only data
nil data
:namespaces namespace-spec - this option may be present on any element.
namespace-spec -> (default-urn (package-name namespace-prefix urn)... )
The default-urn is encoded as the "xmlns=" attribute in the element and the other components are encoded as "xmlns:prefix=" attributes.
Symbols in the specified Lisp packages are encoded as qualified QName strings with the appropriate prefix.
:send-type type-name - this option may be present
on any element. When present, this option is encoded as the attribute
"xsi:type=type-name".
:attributes property-list - this option may be
present on any element. When present, this option is encoded as a
sequence of attributes "property-name=property-value".
:must-understand nil-or-non-nil - this option is
recognized only on the type-def of a top-level element sent as a
Header element in a message. If non-nil then
a "mustUnderstand" attribute with value "1" is included. If nil, then a "mustUnderstand" attribute with value "0"
is included.
:encoding URLlist - A string consisting of one or
more URLs separated by spaces. Sent as the
SOAP-ENV:encodingStyle attribute in the element.
The package qualifier xsd is a nickname for the
net.xml.schema package. You must have evaluated
(defpackage :net.xmp.schema (:use) (:nicknames :xs
:xsd)) in order for the nickname to be valid. Otherwise,
replace xsd with net.xmp.schema
in the lists below.
The package qualifier enc is a nickname for the
net.xml.soap.encoding package. You must have evaluated
(defpackage :net.xmp.soap.encoding (:use) (:nicknames
:enc)) in order for the nickname to be valid. Otherwise,
replace enc with
net.xmp.soap.encoding in the lists below.
package enc corresponds to namespace http://schemas.xmlsoap.org/soap/encoding/
package xsd corresponds to namespace http://www.w3.org/2001/XMLSchema
Lisp Name of
SOAP Type Lisp Type
enc:|QName| symbol in package corresponding to namespace
xsd:|string| string
enc:|int| integer
xsd:|int| integer
enc:|boolean| boolean
xsd:|boolean| boolean
enc:|float| single-float
xsd:|float| single-float
enc:|double| double-float
xsd:|double| double-float
enc:|base64| base64 data decoded to Lisp string
enc:|base64Binary| base64 data decoded to Lisp string
xsd:|base64Binary| base64 data decoded to Lisp string
other string
To make a client call, an application must create a connection instance with a call to soap-message-client.
A SOAP service available via HTTP is located with a URI that has several components:
Within the HTTP request that carries the SOAP message there are HTTP
headers that can be treated as attributes of the HTTP request. The
soapAction header may be used by a specific SOAP
server to recognize or to dispatch a message.
The entire pattern used to identify a SOAP method to be called consists of these components:
Arguments: &rest options
The options (keywords) and their values are (note that a value must be
supplied for :url):
:url url-of-soap-server: this argument is required
since there can be no reasonable default.
:lisp-package package-or-name. This option
specifies the package where unqualified SOAP names are interned as
Lisp symbols. The default is net.xmp.soap.none.
:must-understand flag, flag can
be :strict, :warn, or nil. The default is :warn.
:decode-flag flag, flag can be
:strict, :warn, or nil. The default is :warn.
:encoding string, sent out as encodingStyle
attribute. URIs separated by spaces, most specific first. The default
is "http://schemas.xmlsoap.org/soap/encoding/".
:actor string, the default is
"http://schemas.xmlsoap.org/soap/actor/next".
:start list, a list of additional arguments to
do-http-request. The following keywords are used by the SOAP module
internals and should not appear in the start
argument: :method, :protocol,
:content-type, :content,
:user-agent, :headers,
:external-format. The most likely user addition in
this argument is :proxy to specify a proxy server.
:null-element value: this argument specifies the
behavior when the value of a message element is
missing. value can be :empty,
in which case an empty element is included in the message; or
:default-value (which is the default if no value is
specified), in which case an element with a default null content is
included in the message. For numeric element types the default value
is zero.
:empty-element value: this argument specifies how
an empty message element is decoded into a Lisp value. If
value is :default-value (which
is the default if no value is specified), a suitable Lisp value is
returned. For numeric element types this value is zero and for string
types it is the empty string. If value is nil, the Lisp value is nil.
:decode-flag flag: the flag
argument may be :strict, :warn,
or nil. When :strict is
specified, all elements in a reply message must be defined, otherwise
an error is signaled. When :warn is specified,
undefined elements are accepted with a warning message. When nil is specified, all elements are accepted
silently. The default is :warn.
:message-dns namespace-map: the value of this
option is a namespace map that is combined with the
base-dns namespace map to form the full space map
for each message sent or received through this connection. The
default value is nil. In a typical
application, the standard SOAP and Schema namespaces are specified in
the :base-dns option and any additional namespaces specific to the
application are declared in the :message-dns option.
:base-dns namespace-map: this argument specifies
the namespace map for the standard and required namespaces. The
default value is :soap.
:trim-whitespace t-nil-or-string: this argument
determines the handling of the textual content of a SOAP message
element. The value may be nil (the default),
t, or a string. When nil is specified, then the content is not modified.
When a string is specified, then any leading or trailing characters
mentioned in the string are deleted from the element content. When
t specified, the characters #\return #\space
#\tab #\newline are deleted from the beginning and end of the element
content.
Arguments: conn method &rest args
The conn argument is an instance of
soap-client-connector.
The method argument is a symbol defined as a SOAP element or a list containing an element-def as described above.
The args argument may be the name of a SOAP type or the definition of a SOAP type. In this case, the remaining arguments are decoded according to the type definition. The following table shows the suitable values given a Method argument defintion:
Method argument def |
Suitable Lisp Value |
:complex | name value ... where each name occurs as a top-level element in the complex def. |
:array | A sequence of items, each suitable as an array element. |
:simple |
A single value or a sequence of values. |
Thus, if the SOAP message body consists of several elements, then the method argument would be of the form
(:complex (:seq (:element e1) (:element e2) ...))
The outgoing message includes any headers that have been added to the connector with soap-add-header (described below).
The function returns two values, the main body element in the reply and a list of header elements.
In this example, we call a method with one argument declared as a simple element containing a string value. We use strings for all the element names because the server does not expect qualified XML names.
(define-soap-element nil "simpleStructReturnTest" '(:complex (:seq (:element "myNumber" (:simple enc:|int|))))) (call-soap-method client "simpleStructReturnTest" "myNumber" 123)
In this example, the SOAP method expects one argument declared as a complex element with 3 sub-elements.
(define-soap-element nil "easyStructTest"
'(:complex
(:seq
(:element
"stooges"
(:complex
(:set
(:element "moe" enc:|int|)
(:element "larry" enc:|int|)
(:element "curly" enc:|int|)))))))
(call-soap-method client "easyStructTest" "stooges" (list "moe" 1 "larry" 2 "curly" 3))
In this example, the SOAP method expects one argument declared as an array of elements. The Lisp argument corresponding to the "myArray" element is a list of strings. Each string in the list is encoded as an array element with the default element name "item".
(define-soap-element nil "moderateSizeArrayCheck" '(:complex (:seq (:element "myArray" (:array xsd:|string|))))) (call-soap-method client "myArray" (list "a" "b" "c" "d"))
To specify more precisely the layout of an array we could say
(define-soap-element nil "moderateSizeArrayCheck"
'(:complex (:seq (:element "myArray" (:array xsd:|ur-type|
:array-item
(:element "myArrayElement"
:send-type t
:argument :type-and-arg))))))
In this case each array element in Lisp must be specified as a list
where the first element is the SOAP type of the encoding and the
second is the Lisp value to be encoded. Each array element will be
encoded as an element named "myArrayElement" and the type will be
encoded as a xsd:|type|
attribute. (xsd is a nickname for the
net.xml.schema package. You must have evaluated
(defpackage :net.xml.schema (:use) (:nicknames :xsd
:xs)) for the mickname to be valid. Otherwise replace
xsd with net.xml.schema in the
example below.)
(call-soap-method client "myArray" '((:xsd:|string| "a") (xsd:|int| 17)))
A SOAP server exports methods that may be called from remote clients through a network interface. The network interface in this implementation is an AllegroServe HTTP server. A method is exported by specifying a SOAP element pattern and a Lisp function. When the specified message is received by the network server, the Lisp function is called. The arguments to the Lisp function are the decoded sub-elements of the message. The result returned by the Lisp function is encoded and sent as the reply message.
A SOAP network interface is established with a call to soap-message-server.
Arguments: &key start enable publish class name service-name url port-name binding-name action lisp-package message-dns base-dns must-understand decode-flag encoding actor trim-whitespace &allow-other-keys
The function returns an instance of
soap-server-connector. This instance is an argument
to most of the other API functions.
The arguments are:
nil, take no
action. If :start, start the default http server
and enable the SOAP server. If :start-new, start a
separate http server and enable the SOAP server. If any other
non-nil value, enable the SOAP server (this
option assumes that the http server was started by some other
means). The default is :start.
:path
"/SOAP" is added. The function and
content-type arguments are not allowed in this
list.
soap-aserve-server-string-in-out-connector.
:empty,
in which case an empty element is included in the message; or
:default-value (which is the default if no value is
specified), in which case an element with a default null content is
included in the message. For numeric element types the default value
is zero.
:default-value (which is the default if no value is
specified), a suitable Lisp value is returned. For numeric element
types this value is zero and for string types it is the empty
string. If empty-element is nil, the Lisp value is nil.
nil (the default), t, or a string. When nil is
specified, then the content is not modified. When a string is
specified, then any leading or trailing characters mentioned in the
string are deleted from the element content. When t specified, the characters #\return #\space #\tab
#\newline are deleted from the beginning and end of the element
content.
All other arguments are passed as initargs in a call to make-instance. Arguments
recognized for the class
soap-aserve-server-string-in-out-connector include:
nil means that there is no default action and
action must be specified in each call to soap-export-method. A value of
:none means that the SOAPAction header is ignored.
Arguments: server &key &allow-other-keys
This method enables the server to respond to SOAP method calls. The HTTP server is not affected by this call.
Arguments: server &key &allow-other-keys
This method disables the server for SOAP method calls. The HTTP server is not affected by this call.
Arguments: server &key new start enable &allow-other-keys
Start the HTTP server for this SOAP server. If
new is non-nil, create a
new HTTP server If start argument is specified,
it overrides the start argument in call to
soap-message-server If
enable is non-nil,
enable the soap server.
Arguments: server &key disable &allow-other-keys
Stop the HTTP server for this SOAP server. If
disable is non-nil
disable the SOAP server as well.
A method must be exported to make it available to remote clients through the network server.
Arguments: conn name signature &key lisp-name (enable t) return help action ordered exact &allow-other-keys
This function defines how a Lisp function will be invoked when a SOAP message arrives at the server. The arguments to the Lisp function are the names and content of the sub-elements in the message.
The arguments to soap-export-method are:
soap-server-connector, typically the
result of a call to soap-message-server.
nil,
the method is enabled immediately. When nil,
the method must be enabled before it may be called.
nil).
nil, then ignore SOAPAction header in message.
:none, then ignore SOAPAction header in message.
:default, then use the action specified in
soap-message-server call.
nil,
elements in message must be in same order as in signature
nil, every
element in signature must be present in message
The Lisp function associated with a SOAP message is called with the
soap-invoke-method generic function. The SOAP API includes a method
specialized on soap-server-connector. This method
simply calls apply. Applications can add additional restrictions on
how and when the function is called by implementing a more specific
method on a sub-class of soap-server-connector.
Arguments: server name arg &key headers
This function is called to invoke the Lisp function associated with a
SOAP message. The default primary method simply calls apply. User methods can be
defined for sub-classes of soap-server-connector to
enforce more restrictive access rules.
The headers argument is a list of SOAP header elements that were included in the incoming message. The default method ignores these.
This function normally returns one value which is encoded as the content of the reply message. If zero values are returned, then a SOAP client fault with fault string "Call refused" is returned as the reply. Values other than the first are ignored.
An :around method specialized on
soap-server-connector binds the variable *soap-server*. If more specific
:around methods are defined, the body of these
methods will not see this binding.
The Lisp function defined as the SOAP method body is called with an &rest argument that consists of an alternating list of element names and element content values.
If the element names are Lisp keywords, the function may be defined with keyword arguments, otherwise the function must extract argument values by some other means such as getf.
Named element content in message: |
Lisp argument to method: |
| simple type | corresponding Lisp value |
| complex type | an association list in which the keys are sub-element names. The function soap-sub-element-content should be used to extract the content of a sub-element. |
| array type | a Lisp array of t,
each array element is the element content of
the array elements in the message |
During the execution of a SOAP method call, this variable is bound to a copy of the server instance that received the message with the method call.
Arguments: element-item sub-element-name
This function is used to extract the sub-element content from an argument to a SOAP method. The sub-element-name must be the name of an immediate sub-element of the argument.
If the sub-element is a simple element, the value is a Lisp atom that represents the value of the element. If the sub-element is a complex element, the value is a Lisp association list that can be decomposed with additional calls to soap-sub-element-content.
Arguments: element-alist &optional recursive
Translate an association list into a property list. This is useful when turning an argument into a reply.
Arguments: name type-spec data
This function returns an instance of soap-element that contains an encoded form of the data argument using the type-spec to control the encoding.
Once a value is encoded as a soap-element instance, it is not affected by other element or type specifications that may be applied to the value. This function may be used to specify the encoding of SOAP array elements when a uniform encoding rule cannot be specified.
Arguments: &optional v1 v2 v3 error-p
In its simplest form, with no arguments, this function returns a string containing the current version information.
If the first argument is t or a stream, the
version string is written to the stream (t
indicating *terminal-io*).
If the first argument is an integer, the function acts as a predicate that compares the integer arguments to the current version. If v2 or v3 are omitted, they default to zero.
nil the function returns nil; otherwise, the function signals an error.
A client connector instance should be used serially only. Only one thread should access the connector for the entire duration of a message round-trip.
When a server responds to an incoming message, a copy of the server
connector instance is cloned for the duration of the message. The
variable *soap-server* is bound in the thread that
calls the Lisp function exported to handle the message. Message
handling programs called by the server must take care to deal with
shared resources with appropriate interlocks.
The complete class hierarchy for sub-classes of
soap-connector includes all the following classes:
soap-connector soap-client-connector soap-server-connector soap-string-out-connector soap-string-in-connector soap-string-in-out-connector soap-client-string-out-connector soap-client-string-in-connector soap-client-string-in-out-connector soap-server-string-out-connector soap-server-string-in-connector soap-server-string-in-out-connector soap-aserve-connector soap-aserve-client-connector soap-aserve-server-connector soap-aserve-string-out-connector soap-aserve-string-in-connector soap-aserve-string-in-out-connector soap-aserve-client-string-out-connector soap-aserve-client-string-in-connector soap-aserve-client-string-in-out-connector soap-aserve-server-string-out-connector soap-aserve-server-string-in-connector soap-aserve-server-string-in-out-connector
Methods in the API and internals methods are specialized on the least-specific method in this hierarchy, but only the classes
soap-aserve-client-string-in-out-connector soap-aserve-server-string-in-out-connector
are actually instantiated in an application using this API. Thus, in order to provide behavior specific to a given application the programmer must create a sub-class of one or both of the above classes.
The following are accessors for soap-connector.
Values are used by encode-wsdl-file.
Arguments: soap-connector
Returns the port name.
Arguments: soap-connector
Returns the binding name.
Arguments: soap-connector
Returns the service name.
Many web services are defined in an XML dialect known as WSDL. The WSDL definition specifies the element content and data types in the SOAP messages received and sent by the service.
Given a web service WSDL definition, we can generate the Lisp functions and definitions needed to send messages to the service and to receive and decode the replies.
We can also generate the server interface and skeleton definitions for the server methods. The only additional programming needed is to supply the body of the server functions.
This early release of WSDL support implements most of the WSDL 1.1 specification. Any omissions are the result of oversight or for the benefit of an earlier release.
The known omissions include:
soap:header and
soap:fault entries in a file.
style="rpc"
use="encoded"
minOccurs and
maxOccurs attributes
xs:sequence we assume min=0
max=Unbounded
xs:all we assume min=0 max=1
xs:choice we assume min=0
max=1
The packages net.xmp.wsdl and
net.xmp.wsdl.soap hold the symbols in the WSDL
namespaces.
An instance of this class is created when a WSDL file is decoded.
Arguments: file &key namespaces base lisp-package
This function parses a file containing a WSDL specification and
returns wsdl-file-connector instance containing
the parsed data.
The lisp-package argument is a package specifier. Unqualified WSDL names will be interned in this package.
The value of the namespaces argument may be
nil, :decode, or a
namespace map. The default is :decode.
The base keyword argument may be nil or a namespace map. The default is
:wsdl1-prefix.
When the namespaces keyword argument is
:decode, decode-wsdl-namespaces is called with
the map keyword argument set to base
and if the namespaces can be decoded, the resulting namespace map is
used. Otherwise an error is signalled.
If a package-name occurs as an ex-ns-part, any unknown namespaces in the file are mapped to this package. Only one package-name should occur in the extended-namespace-spec.
If the form (:prefix symbol-or-string) occurs as an
ex-ns-part, each unknown namespace is mapped to a different package
named "prefixNN". Only one such form should occur in the
extended-namespace-spec.
The ex-ns-tail component specifies how the standard
namespaces should be identified in the file. If the
package-name or :prefix forms
occur as an ex-ns-part, or if the tail is :guess,
then decode-wsdl-namespaces is called.
Arguments: string &key namespaces base lisp-package
This function is like decode-wsdl-file but the input is from the string argument instead of a file.
Arguments: uri &key namespaces base lisp-package
This function is like decode-wsdl-file but the input is from the specified uri argument instead of a file.
Arguments: &key uri string file namespaces base lisp-package
This is the most general form of decode-wsdl-* functions. Only one of the keyword arguments uri, string, and file should be specified. The other keyword arguments are like decode-wsdl-file.
Arguments: &key namespaces base servers target name (if-exists :supersede)
Create a file with WSDL definitions of the specified servers. The definitions include exported methods and associated data types.
The arguments are:
(:net.xmp.wsdl) that specifies the the
WSDL namespace as the default namespace.
The effective namespace map during the encoding af each service is obtained by combining the the namespace map of the service with the above default namespace map for the WSDL definition.
(list nil
:wsdl1-namespaces :all).
:supersede
Arguments: conn &optional and-ports
Returns a list of the names of all the services defined in the wsdl file. The order of the names is the order of the defininitions in the file. If more than one service is defined, the index in the list may be used as the service argument to make-client-interface.
The optional and-ports argument determines the
level of detail included in the returned value. If it is omitted or
nil, the result will look like
(service-name ... ). If it is t, the result will
look like ((service-name port-name ...) ... ). If
it is :verbose, the result will look like ((service-name
(port-name binding url) ...) ... ).
Arguments: conn service destination &key eval (lisp-package :keyword) (file-package :user) empty-element null-element expand-singleton prefix suffix port if-missing-package
The service argument can be
nil or omitted, in which case 0 is passed
(see next entry).
The destination argument can be
nil, which supresses output
t, which causes output to be sent to the
console
The eval argument is ignored.
The lisp-package, empty-element, and null-element arguments apply to the client connection that is created in the client call functions.
The file-package argument denotes the package for the source file that is generated by this function.
When the expand-singleton argument is nil, each generated client function expects as many
keyword arguments as there are immediate components in the SOAP
message.
When the expand-singleton argument is non-nil, and the SOAP message consists of exactly one
sub-element, the generated client function expects as many keyword
arguments as there are immediate components in this singleton
sub-element. SOAP messages are often designed to contain this
structure, and this feature simplifies the client message function
arguments.
The prefix argument is the leading component of
the generated names of client functions. The argument must be a string
or a symbol. The default is :client-.
The suffix argument should be one of the keywords
:index or :message. The
keyword :index denotes names like
prefix-17. The keyword :message denotes
names like prefix-SoapMessageName.
The port argument specifies the port binding within a service. The value is a name string or an index. The default is 0.
The if-missing-package argument specifies the
behavior if a namespace cannot be mapped to a package. The value can
be :error or :warn or a string
or a symbol.
If the value of if-missing-package is
:error or :warn (the default),
an error or a warning is signaled. When the :warn
option is chosen, if no warnings are printed, the generated interface
is complete and correct. If warnings are printed, the generated
interface file must be hand modified to make it complete and
functional. It is usually easier to adjust the
namespaces argument and generate a new interface
file.
If the value of if-missing-package is a string or some other symbol, then a package with name "net.xmpns.SSSNN" where SSS is the string (or symbol-name) and NN is an index is created and used.
If no Lisp package has been defined for a namespace, the warning "There is no Lisp package defined for namespace ~S" is printed. If a Lisp package is not pre-defined in the application, the symbols will be interned in a new package for each new incoming message.
In order to define the generated interface, the generated interface file must be compiled and loaded.
Arguments: conn service destination &key eval (lisp-package :keyword) (file-package :user) empty-element null-element expand-singleton prefix suffix action message-dns port if-missing-package
This method analyzes the data in the WSDL file to generate type definitions and and server function skeletons.
Most of the arguments are as for make-client-interface. The eval argument, as in make-client-interface, is ignored.
The prefix argument is the leading component of
the generated names of server functions. The argument must be a string
or a symbol. The default is :server-.
The action argument is the default
soapAction expected for all incoming messages.
The message-dns argument is used to initialize the namespace definitions of the server instance.
In order to define the generated interface, the generated interface file must be compiled and loaded.
The meaning of XML, SOAP, and WSDL texts depends in part on the correct identification of various namespaces.
XML namespaces are identified by a URI and URIs are considered distinct if they differ in any character position. The SOAP module considers two URIs equivalent if they only differ in a final slash character.
"http://www.w3.org/2001/XMLSchema"
"http://www.w3.org/2000/10/XMLSchema"
"http://www.w3.org/1999/XMLSchema"
:net.xmp.soap.encoding.
:net.xmp.wsdl.
:net.xmp.wsdl.soap.
A namespace declaration is a list of the form (package
prefix uri).
One package may be linked to several URIs. One URI may be linked to several packages. The most recent definition is the first to be seen in a search. The primary-p argument to various operators allows some reordering.
One advantage of making a global namespace definition is that the package name may be used to denote the mapping. Also the entry will be found if :all is in namespace map.
Here is a recursize specification of the namespace maps:
namespace-map -> symbol-name-of-namespace-map |
(default-namespace [namespace-entry]... [namespace-tail])
namespace-entry -> (package-name) | (package-name prefix) |
namespace-declaration | namespace-declaration-instance
symbol-name-of-namespace-map |
:all
:stop
namespace-tail -> nil | (package nil :any) | (string nil :prefix)
The Lisp class of a namespace map object.
Arguments: name &rest namespace-map-parts
This function returns a xmp-namespace-map instance.
:wsdl-namespaces -> ( :wsdl1.2 :wsdl1.1 :soap )
This definition recognizes both the WSDL 1.1
and the WSDL 1.2 namespaces, and uses the WSDL 1.2
namespaces for output, sinc they appear first.
:wsdl1-namespaces -> ( :wsdl1.1 :wsdl1.2 :soap1 )
This definition uses the WSDL 1.
namespaces for output, sinc they appear first.
:soap -> ( :soap1.2 :soap1.1 :schema )
:soap1 -> ( :soap1.1 :soap1.2 :schema )
:soap1.1
:soap1.2
:wsdl1.1
:wsdl1.2
:schema -> ( :schema2001 :schema1999 )
:schema1 -> ( :schema1999 :schema2001 )
:schema1999 :schema2001
:wsdl-combine -> ( :wsdl-namespaces :all (:wsdl-data nil :any) )
This definition searches the :wsdl-namespaces first,
then any globally declared namespaces.
This definition maps any unmatched namespaces to the
:wsdl-data package.
:wsdl-keyword -> ( :wsdl-namespaces :all (:keyword nil :any) )
This definition maps any unmatched namespaces to the
keyword package.
:wsdl-prefix -> ( :wsdl-namespaces :all ("wsdl-" nil :prefix) )
This definition maps each unmatched namespace to a new
package with a name of the form "wsdl-nnn"
:wsdl1-combine -> ( :wsdl1-namespaces :all (:wsdl-data nil :any) )
:wsdl1-keyword -> ( :wsdl1-namespaces :all (:keyword nil :any) )
:wsdl1-prefix -> ( :wsdl1-namespaces :all ("wsdl-" nil :prefix) )
The current namespace environment is defined as the current nesting of namespace declarations. It consists of nested :namespaces options and/or xmlns attributes, the :message-dns slot specification, the :base-dns slot specification, and finally the namespace-tail entry.
During input decoding, when the server is decoding a request or a client is decoding a reply, or when decoding a wsdl file, "xmlns" attributes cause a search of the current namespace environment for an exact match on the URI. If a match cannot be found, an error is signalled. If a match is found, the XML name is interned in the corresponding Lisp package.
During output encoding, when the server is encoding a reply, or a client is encoding a request, or when encoding a wsdl file, create a top-level xmlns attributes from the first occurrence of each explicit namespace declaration in the namespace environment. A symbol in a package present in the current namespace environment is encoded as a qualified name.
The Lisp class of a namespace declaration object.
Arguments: package prefix uri &optional primary-p
If the package and uri
arguments are specified (that is, given a non-nil value), then a new namespace declaration object
is created if it does not already exist.
If only the package or the
uri argument is specified (that is, given a
non-nil value), then find a matching
namespace declaration object, if one exists.
If both package and uri are
nil, then do nothing and return nil.
This function returns a xmp-namespace-declaration instance or
nil.
Arguments: package prefix uri
This function deletes any namespace declarations matching the
arguments. Either package or
uri must be non-nil, or
no namespaces are deleted. If one is nil while the other is
non-nil, then all namespaces with the
non-nil component are deleted, that is, nil
works as a wildcard when the other component is specified. Nothing
will be deleted if only prefix is non-nil.
In an earlier version, the following variables had namespace specifications as values. All these variable are removed and namespaces are determined by the namespace operators described above.
*soap-namespaces*
*wsdl-default-namespaces*
*application-namespaces*
*soap-namespaces-a*
*soap-namespaces-b*
*wsdl-1.1-namespaces*
*wsdl-1.2-namespaces*
The function decode-wsdl-namespaces returns information about the namespaces mentioned in a WSDL definition and it can generate a namespace specification based on some heuristic rules.
Arguments: &key file string uri
This function returns 4 values:
file should be a string containing the path to a file. string should be a string containing a WSDL definition. uri should be the uri where a WSDL definition may be found. Only one of the above arguments should appear.
When decode-wsdl-file is called with a
namespaces argument of
:decode, the function decode-wsdl-namespaces is called and if
values 2 3 and 4 are nil the decode operation
proceeds with the resulting namespace specification. If any of the
values 2 3 or 4 are non-nil, the function
signals an error.
Sometimes, when a connection does not seem to be working, it is useful to see the actual XML message strings passed between client and server.
The variable *soap-client-debug* can be set to a
non-nil value to cause a printout of the HTTP
headers and the XML message text sent by the client. When the reply
arrives, the HTTP headers and XML message text are printed as well.
If the variable is set to :stop, then the message
is not sent to the server.
The variable *soap-server-debug* can be set to a
non-nil value to cause a printout of the HTTP
headers and the XML message text received by the server and sent as a
reply.
The debug flag can also be associated with a single client or server connection by using the soap-debug keyword initarg in the call to soap-message-client or soap-message-server.
If the variables *soap-client-debug* or *soap-server-debug* are stack bound, the
stack bound value takes precedence over the slot or the global value.
When non-nil, causes the printing out of the HTTP
headers and the XML message text received by the server and sent as a
reply.
When non-nil, causes the printing out of the
HTTP headers and the XML message text sent by the client. When the
reply arrives, the HTTP headers and XML message text are printed as
well.
Many web services are defined in an XML dialect known as WSDL. The WSDL definition specifies the element content and data types in the SOAP messages received and sent by the service.
Given a web service WSDL definition, we can generate the Lisp functions and definitions needed to send messages to the service and to receive and decode the replies.
We can also generate the server interface and skeleton definitions for the server methods. The only additional programming needed is to supply the body of the server functions.
This early release of WSDL support implements most of the WSDL 1.1 specification. Any omissions are the result of oversight or for the benefit of an earlier release. We plan to correct omissions and add support for the WSDL 1.2 specification in a future release.
The known omissions include:
soap:header and
soap:fault entries in a file.
style="rpc"
use="encoded"
minOccurs and
maxOccurs attributes
xs:sequence we assume min=0
max=Unbounded
xs:all we assume min=0 max=1
xs:choice we assume min=0
max=1
The packages net.xmp.wsdl and
net.xmp.wsdl.soap hold the symbols in the WSDL
namespaces.
An instance of this class is created when a WSDL file is decoded.
Arguments: file &key namespaces lisp-package base
This function parses a file containing a WSDL specification and
returns wsdl-file-connector instance
containing the parsed data.
The lisp-package argument is a package specifier. Unqualified WSDL names will be interned in this package.
The namespaces keyword argument may be nil, :decode, or a namespace
map. The default is :decode.
The base keyword argument may be nil or a namespace
map. The default is :wsdl1-prefix.
If a package-name occurs as an
ex-ns-part, any unknown namespaces in the file
are mapped to this package. Only one package-name
should occur in the extended-namespace-spec.
If the form (:prefix symbol-or-string) occurs as an
ex-ns-part, each unknown namespace is mapped to a different package
named "prefixNN". Only one such form should occur in the
extended-namespace-spec.
The ex-ns-tail component specifies how the standard
namespaces should be identified in the file. If the
package-name or :prefix forms
occur as an ex-ns-part, or if the tail is
:guess, then decode-wsdl-namespaces is called.
When the namespaces keyword argument is
:decode, decode-wsdl-namespaces is called with the
map argument set to base and
if the namespaces can be decoded, the resulting namespace map is
used. Otherwise an error is signaled.
Arguments: string &key namespaces lisp-package
This function is like decode-wsdl-file but the input is from the string argument instead of a file.
Arguments: uri &key namespaces lisp-package
This function is like decode-wsdl-file but the input is from the specified uri argument instead of a file.
Arguments: &key uri string file namespaces lisp-package
This is the most general form of decode-wsdl-* functions. Only one of the keyword arguments uri, string, and file should be specified. The other keyword arguments are like decode-wsdl-file.
Arguments: &key namespaces servers target name (if-exists :supersede)
Create a file with WSDL definitions of the specified servers. The definitions include exported methods and associated data types.
The arguments are:
(:net.xmp.wsdl) that specifies the the
WSDL namespace as the default namespace. The effective namespace map
during the encoding af each service is obtained by combining the the
namespace map of the service with the above default namespace map for
the WSDL definition.
(list nil
:wsdl1-namespaces :all).
:supersede.
Arguments: conn &optional and-ports
Returns a list of the names of all the services defined in the wsdl file. The order of the names is the order of the defininitions in the file. If more than one service is defined, the index in the list may be used as the service argument to make-client-interface.
The optional and-ports argument determines the
level of detail included in the returned value. If it is omitted or
nil, the result will look like
(service-name ... ). If it is t, the result will look like ((service-name
port-name ...) ... ). If it is :verbose,
the result will look like ((service-name (port-name binding
url) ...) ... ).
Arguments: conn service destination &key eval (lisp-package :keyword) (file-package :user) empty-element null-element expand-singleton prefix suffix port if-missing-package
This method analyzes the data in the WSDL definition to generate type definitions and client call functions.
The service argument can be
nil or omitted, in which case 0 is passed
(see next entry).
The destination argument can be
The lisp-package, empty-element, and null-element arguments apply to the client connection that is created in the client call functions.
The file-package argument denotes the package for the source file that is generated by this function.
When the expand-singleton argument is nil, each generated client function expects as many
keyword arguments as there are immediate components in the SOAP
message.
When the expand-singleton argument is non-nil, and the SOAP message consists of exactly one
sub-element, the generated client function expects as many keyword
arguments as there are immediate components in this singleton
sub-element. SOAP messages are often designed to contain this
structure, and this feature simplifies the client message function
arguments.
The prefix argument is the leading component of
the generated names of client functions. The argument must be a
string or a symbol. The default is :client-.
The suffix argument should be one of the keywords
:index or :message. The keyword
:index denotes names like prefix-17. The
keyword :message denotes names like
prefix-SoapMessageName.
The port argument specifies the port binding within a service. The value is a name string or an index. The default is 0.
The if-missing-package argument specifies the
behavior if a namespace cannot be mapped to a package. The value can
be :error or :warn or a string
or a symbol.
If the value of if-missing-package is
:error or :warn (the default),
and error or a warning is signaled. When the :warn
option is chosen, if no warnings are printed, the generated interface
is complete and correct. If warnings are printed, the generated
interface file must be hand modified to make it complete and
functional. It is usually easier to adjust the namespaces argument
and generate a new interface file.
If the value of if-missing-package is a string or some other symbol, then a package with name "net.xmpns.SSSNN" where SSS is the string (or symbol-name) and NN is an index is created and used.
If no Lisp package has been defined for a namespace, the warning "There is no Lisp package defined for namespace ~S" is printed. If a Lisp package is not pre-defined in the application, the symbols will be interned in a new package for each new incoming message.
Arguments: conn service destination &key eval (lisp-package :keyword) (file-package :user) empty-element null-element expand-singleton prefix suffix action message-dns port if-missing-package
This method analyzes the data in the WSDL file to generate type definitions and and server function skeletons.
Most of the arguments are as for make-client-interface.
The prefix argument is the leading component of
the generated names of server functions. The argument must be a
string or a symbol. The default is :server-.
The action argument is the default
soapAction expected for all incoming messages.
The message-dns argument is used to initialize the namespace definitions of the server instance.
Arguments: conn element-spec &rest args
The arguments are as for call-soap-method, but instead of sending
a message, this method returns an object of class
soap-header which contains an encoded
representation of the header element.
If the header element must have a "mustUnderstand" attribute, the attribute may be specified as a :must-understand option or included in the :attributes option of the element definition.
Arguments: conn header &key after before reset
The header argument must be an instance of the
class soap-header. The method adds the header to
the list of headers that will be sent with the next message.
The before and after
arguments may be nil or headers previously
added.
If reset is non-nil,
then any previously added headers are discarded.
Arguments: conn element-name
When a reply message is decoded, and a "mustUnderstand" attribute with value "1" is present, then this method is called.
The default method behavior depends on the setting of the
:must-understand flag in the connection
instance. The following settings produce the indicated behavior:
:warn - print a warning and accept the header
nil - accept the header silently
In this implementation, "Fault" results are returned like other reply messages.
Errors detected by the implementation in the Lisp code are signaled as
instances of soap-error.
*application-namespaces* (Removed variable, see this note)
*soap-client-debug* (Variable)
*soap-namespaces* (Removed variable, see this note)
*soap-namespaces-a* (Removed variable, see this note)
*soap-namespaces-b* (Removed variable, see this note)
*soap-server* (Variable)
*soap-server-debug* (Variable)
*wsdl-default-namespaces* (Removed variable, see this note)
wsdl-file-connector
*wsdl-1.1-namespaces* (Removed variable, see this note)
*wsdl-1.2-namespaces* (Removed variable, see this note)
xmp-namespace-declaration
xmp-namespace-map
Copyright (c) 1998-2004, Franz Inc. Oakland, CA., USA. All rights reserved.
Documentation for Allegro CL version 7.0. This page has had significant revisions compared to the 6.2 page.
Created 2004.8.21.
| Allegro CL version 7.0 Significantly revised from 6.2. | |||||||