New Features for PocketSOAP 1.5
SOAP 1.2 Support
Here's a quick sample of sending a SOAP 1.2 message with PocketSOAP, the changes from a PocketSOAP 1.4.3 usage are highlighteddim env, t
set env = CreateObject("PocketSOAP.Envelope.12")
env.SetMethod "echoString", "http://example.org/ts-tests"
env.Parameters.Create "inputString", "Hello World"
set t = CreateObject("PocketSOAP.HTTPTransport")
t.Send "http://www.whitemesa.net/soap12/test-rpc", env
env.Parse t
wscript.echo env.Parameters.Item(1).Value
Note the 2 changes, first off, you use a different ProgID to create the envelope object, PocketSOAP.Envelope.12 will create a SOAP 1.2 envelope object, PocketSOAP.Envelope.11 will create a SOAP 1.1 envelope. the previously used PocketSOAP.Envelope.2 will continue to create a SOAP 1.1 envelope. Secondly, the envelope object is passed directly to the transport in the Send method, no longer do you pass a serialized instance of the envelope (i.e. you pass env, not env.serialize). This allows the transport to detect what version of SOAP envelope it is and send the correct Content-Type header in the request. If you do pass a serialized envelope to the Send method, then it will assume it is a SOAP 1.1 message (i.e. existing code should just continue to work without any changes).
The above sample generates this request
POST /soap12/test-rpc HTTP/1.1
Host: www.whitemesa.net
Accept-Charset: UTF-8, UTF-16;q=0.8, iso-8859-1;q=0.8
Accept-Encoding: deflate, gzip
Content-Type: application/soap+xml; charset="utf-8"
User-Agent: PocketSOAP/1.5.0/PocketHTTP/1.2.2
Content-Length: 380
<E:Envelope
xmlns:a="http://example.org/ts-tests"
xmlns:XS="http://www.w3.org/2001/XMLSchema"
xmlns:XI="http://www.w3.org/2001/XMLSchema-instance"
xmlns:E="http://www.w3.org/2003/05/soap-envelope">
<E:Body>
<a:echoString E:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<inputString XI:type="XS:string">Hello World</inputString>
</a:echoString>
</E:Body></E:Envelope>
gzip compression
In addition to the existing support for deflate compression, gzip compression is now also supported. By default the request will indicate that it supports both deflate and gzip'd responses. If you are sending compressed requests, then these will continue to be deflate compressed by default, if you want to send a gzip compressed request, then set the compression.method option to gzip, e.g.dim h set h = CreateObject("PocketSOAP.HTTPTransport") h.option("compression.method") = "gzip" ' continue to use transport as usual ...
New Features for PocketSOAP 1.4
HTTP Compression
All HTTP requests now include a header in the request that indicates that we can handle a compressed response. If the response is compressed, the transport will automatically uncompress it. By default the request SOAP message is not compressed. To send compressed requests, call the new option method on the HTTP transport object, setting the compression.enabled property to true, e.g.dim h set h = CreateObject("PocketSOAP.HTTPTransport") h.option("compression.enabled") = true ' continue to use transport as usual ...
PocketPC HTTP Timeouts
HTTP Timeouts are now handled on the PocketPC, set the timeout property on the transport, the same way as you do on the Win32 version.dim h set h = CreateObject("PocketSOAP.HTTPTransport") ' set timeout to 5 seconds (it defaults to 15 seconds) h.timeout = 5000
New Features for PocketSOAP 1.3
Attachments Support
You can now send and receive binary attachments to the SOAP message via either DIME or SwA. See the samples for details.Support for document/literal style services has been improved, the serialization interfaces now allow access to typed attributes, e.g.
Private Sub ISoapSerializer_Serialize( theVal As Variant, _ ByVal ctx As PocketSOAP.ISerializerContext, _ ByVal dest As PocketSOAP.ISerializerOutput) Dim val As Person Set val = theVal Dim d2 As ISerializerOutput2 Set d2 = dest ' val.name and val.male will get serialized with a serializer based on their type. d2.SerializeAttribute val.name, "Name", "" d2.SerializeAttribute val.Male, "Male", "" dest.SerializeValue val.Age, "Age", "http://soapinterop.org/xsd" dest.SerializeValue val.id, "ID", "http://soapinterop.org/xsd" End Sub Private Sub ISoapDeSerializer_Start( ByVal node As PocketSOAP.ISOAPNode, _ ByVal ElementName As String, _ ByVal Attributes As PocketSOAP.ISoapDeSerializerAttributes, _ ByVal ns As PocketSOAP.ISOAPNamespaces) Set m_obj = CreateObject(m_comtype) node.Value = m_obj Set m_refs = New Collection Dim a As ISoapDeSerializerAttributes2 Set a = Attributes m_obj.name = a.ValueAs("Name", "", "string", "http://www.w3.org/2001/XMLSchema") m_obj.Male = a.ValueAs("Male", "", "boolean", "http://www.w3.org/2001/XMLSchema") End Sub
New Features for PocketSOAP 1.2
Enhanced EncodingStyle support
In addition to the current EncodingStyle property on the envelope, each node object can now adjust the encodingStyle. This is particularly useful for headers, which are typically defined using schemas rather then section 5 encoding. The serializer engine will disable the multi-ref features of section 5 if the encodingStyle is set to something other than the section 5 encoding URI. Nodes created via Nodes.Create will automatically inherit their encodingStyle from their parent, stand-alone nodes created through new (or CoCreateInstance) default to section 5 encoding. e.g.dim e set e = CreateObject("pocketSOAP.Envelope.2") e.SetMethod "echoString", "http://soapinterop.org/" e.Parameters.Create "inputString", "hello World" set n = e.Headers.Create ("messageHeader",empty,"http://foo.org/") n.encodingStyle= "" n.mustUnderstand = true n.Nodes.Create "msgID", 12345 wscript.echo e.serializethis generates the following SOAP message
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://foo.org/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:d='http://soapinterop.org/' xmlns:c='http://www.w3.org/2001/XMLSchema' xmlns:b='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:messageHeader S:mustUnderstand='1' S:encodingStyle=''><msgID b:type='c:short'>12345</msgID> </a:messageHeader> </S:Header> <S:Body><d:echoString><inputString b:type='c:string'>hello World</inputString> </d:echoString> </S:Body></S:Envelope>
The RawTCP Transport
This is a simple TCP based transport that works with the TcpServer module in SOAP::Lite. This is useful when the service provider doesn't want to deploy a full blown HTTP based system. e.g.set e = CreateObject("pocketSOAP.Envelope.2") e.setMethod "test", "http://www.soaplite.com/ClearingHouse" set t = CreateObject("pocketSOAP.RawTCPTransport") t.send "rawtcp://some.server.org:8002", e.serialize e.parse t wscript.echo e.parameters.item(0).value
Local Type mappings support
One of the problems with the existing type mapping support, is that you can't cope with elements having the same name, but different types in different parts of the message. The local types support, allows you to register element name to type mappings as before, but also to specify that the mapping is only valid within the scope of a particular type. This allows you to have multiple elements <item> in a message, but for its type to be dependent upon the containing elements type. e.g.const XSD = "http://www.w3.org/2001/XMLSchema" set e = CreateObject("pocketSOAP.Envelope.2") e.SerializerFactory.ElementMapping "c","","three","http://soapinterop.org/" e.SerializerFactory.LocalTypeMapping "one","http://soapinterop.org/","item","","string",XSD e.SerializerFactory.LocalTypeMapping "two","http://soapinterop.org/","item","","int", XSD e.SerializerFactory.LocalTypeMapping "three","http://soapinterop.org/","item","","float",XSD e.parse GetTestMsg for i = 0 to e.parameters.count-1 set n = e.parameters.item(i).Nodes.item(0) wscript.echo n.Name & " -> " & n.Value & " -> " & TypeName(n.Value) next Function GetTestMsg() m = "<S:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " + _ "SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' " + _ "xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' " + _ "xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' " + _ "xmlns:d='http://soapinterop.org/' " + _ "xmlns:xs='http://www.w3.org/2001/XMLSchema' " + _ "xmlns:xi='http://www.w3.org/2001/XMLSchema-instance'>" + _ "<S:Body><d:testFooResponse>" + _ "<a xi:type='d:one'><item>String</item></a>" + _ "<b xi:type='d:two'><item>1414</item></b>" + _ "<c><item>33.33</item></c>" + _ "</d:testFooResponse></S:Body></S:Envelope>" GetTestMsg = m end FunctionThis generates the following output.
item -> String -> String item -> 1414 -> Long item -> 33.33 -> Single
New Features for PocketSOAP 1.1
The Nodes Object
The Parameters property returns a Nodes object, which allows you to read/write/create new nodes in the parameters tree. Each node object also contains a nodes property, which make it much easer to construct complex types, e.g.dim e, a set e = CreateObject("pocketSOAP.Envelope.2") e.methodName = "addAddress" e.URI = "http://tempuri.org/" e.Parameters.Create "name", "Simon Fell" set a = e.Parameters.Create "address","" a.Nodes.Create "street", "100 Spear Street" a.Nodes.Create "city", "San Francisco" a.Nodes.Create "state', "CA" a.nodes.Create "zip", "94107"this generates the following SOAP message
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://tempuri.org/' xmlns:b='http://www.w3.org/2001/XMLSchema-instance' xmlns:c='http://www.w3.org/2001/XMLSchema'> <S:Body><a:addAddress><name b:type='c:string'>Simon Fell</name> <address href='#a'/> </a:addAddress> <address E:root='0' id='a'><street b:type='c:string'>100 Spear Street</street> <city b:type='c:string'>San Francisco</city> <state b:type='c:string'>CA</state> <zip b:type='c:string'>94107</zip> </address> </S:Body></S:Envelope>
Headers
The Headers property allows access to the headers of the SOAP message. This uses the node/nodes objects the same as the parameters property does. e.g.dim e, h set e = CreateObject("pocketSOAP.Envelope.2") e.methodName = "placeOrder" e.URI = "http://tempuri.org/" set h = e.headers.Create ("Transaction", "42", "http://soap.tip.org/") h.MustUnderstand = true e.Parameters.Create "item", "widget 19" e.Parameters.Create "number", 5 wscript.echo e.serializeThis generates the following SOAP message
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://soap.tip.org/' xmlns:b='http://www.w3.org/2001/XMLSchema-instance' xmlns:c='http://www.w3.org/2001/XMLSchema' xmlns:d='http://tempuri.org/'> <S:Header> <a:Transaction S:mustUnderstand='1' b:type='c:string'>42</a:Transaction> </S:Header> <S:Body><d:placeOrder><item b:type='c:string'>widget 19</item> <number b:type='c:int'>5</number> </d:placeOrder> </S:Body></S:Envelope>
Multi-Dim arrays
The standard array serializer supports all the various array options, single dimension, multi-dimension, partial & sparse arrays. e.g.dim e, a(1,1) a(0,0) = "one" a(0,1) = "two" a(1,0) = "three" a(1,1) = "four" set e = CreateObject("pocketSOAP.Envelope.2") e.methodName = "strings" e.URI = "http://tempuri.org/" e.Parameters.Create "strArray", a wscript.echo e.serializeThis generates the folloiwng SOAP message
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://tempuri.org/' xmlns:b='http://www.w3.org/2001/XMLSchema' xmlns:c='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:strings><strArray E:arrayType='b:anyType[2,2]'><i c:type='b:string'>one</i> <i c:type='b:string'>two</i> <i c:type='b:string'>three</i> <i c:type='b:string'>four</i> </strArray> </a:strings> </S:Body></S:Envelope>
base64 support
There's a base64 serializer for serializing byte arrays.Dim e, a(5) As Byte a(0) = 10: a(1) = 20: a(3) = 30: a(4) = 40: a(5) = 50 Set e = CreateObject("pocketSOAP.Envelope.2") e.methodName = "echoBase64" e.URI = "http://soapinterop.org/" e.Parameters.Create "inputBase64", a MsgBox e.serialize
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://soapinterop.org/' xmlns:b='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoBase64><inputBase64 b:type='E:base64'>ChQAHigy</inputBase64> </a:echoBase64> </S:Body></S:Envelope>
SetMethod
The envelope object has an addition method SetMethod that can be used to set the methodName & URI in one go, e.g.dim e set e= CreateObject("pocketSOAP.Envelope.2") e.SetMethod "add", "http://simon.fell.com/calc"
Multi-Refs / Object Graph Serialization
There's full support for serializing & deserializing object graphs, including circular references etc. Here's an example of a serialized ring bufferdim soap set soap = CreateObject("PocketSOAP.Envelope") soap.SetMethod "Add", "http://simon.fell.com/calc" dim n, last set h = CreateNode ( "f", a, nothing ) set last = h for i = 1 to 5 set n = CreateNode ( "a", i, last ) set last = n next ' make it a ring buffer h.Nodes.ItemByName("next").value = last soap.Parameters.Create "head", n wscript.echo soap.serialize Function CreateNode ( name, v, nextNode ) dim n set n = CreateObject("pocketSOAP.Node") n.name = name n.type = "linkedlist" n.typeNS = "http://soapinterop.org" n.Nodes.Create "value", v n.Nodes.Create "next", nextNode Set CreateNode = n end Function
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://simon.fell.com/calc' xmlns:b='http://soapinterop.org' xmlns:c='http://www.w3.org/2001/XMLSchema-instance' xmlns:d='http://www.w3.org/2001/XMLSchema'> <S:Body><a:Add><head href='#a'/> </a:Add> <b:linkedlist E:root='0' id='f'><value></value> <next href='#a'/> </b:linkedlist> <b:linkedlist E:root='0' id='e'><value c:type='d:int'>1</value> <next href='#f'/> </b:linkedlist> <b:linkedlist E:root='0' id='d'><value c:type='d:int'>2</value> <next href='#e'/> </b:linkedlist> <b:linkedlist E:root='0' id='c'><value c:type='d:int'>3</value> <next href='#d'/> </b:linkedlist> <b:linkedlist E:root='0' id='b'><value c:type='d:int'>4</value> <next href='#c'/> </b:linkedlist> <b:linkedlist E:root='0' id='a'><value c:type='d:int'>5</value> <next href='#b'/> </b:linkedlist> </S:Body></S:Envelope>
The PropertyBag serializer
pocketSOAP comes with a PropertyBag serializer, this will deserialize any COM object that implements IPersistPropertyBag to/from a SOAP complex type. In VB if you've set the Persistable property of a class to 1 - Persistable then VB will implement IPersistPropertyBag for you, making it easy to add SOAP support to your existing COM objects.Serializer Factory
The Serializer Factory object controls the mapping between COM date types and SOAP date types. The SerializerFactory property on the Envelope object can be used to access the serializerFactory object. Once you got the SerializerFactory object, you can register new serializers or de-serializers and add additional mappings from element names to types. e.g.Dim e As CoEnvelope Set e = New CoEnvelope Dim sf As ISerializerFactoryConfig Set sf = e.SerializerFactory sf.ElementMapping "phone", "", "phone", "http://apache.org/" sf.ElementMapping "address", "", "address", "http://apache.org/" sf.Deserializer "phone", "http://apache.org/", False, "ps.telephone", "pocketSOAP.SerializerPB.1" sf.Deserializer "address", "http://apache.org/", False, "ps.address", "pocketSOAP.SerializerPB.1"This adds two new element name mappings (these tell the de-serializer what type elements are that don't contain type information on the wire). In the example is says, any element called phone is of type {http://apache.org/}phone and any element called address is of type {http://apache.org/}address. It then registers two de-serializer mappings, one that maps the SOAP data type {http://apache.org/}phone to the com object ps.telephone and registers the de-serializer object pocketSOAP.SerializerPB.1 as the de-serializer that will map the data from the SOAP message to the COM object. It then does the same for address to ps.address using the same de-serializer.
Serializer Factory (more!)
The Serializer Factory contains support for both the 1999 XML Schema namespace and the 2001 XML Schema namespace. By default pocketSOAP will use the 2001 Schema namespace, however if you are calling a service that requires the use of the 1999 namespace, then you can set the PrimarySchema property to the value of the 1999 Schema namespace, and pocketSOAP will serialize using that format instead (including taking care of such differnces as ur-type vs anyType, timeInstant vs dateTime etc), e.g.dim e, a set e = CreateObject("pocketSOAP.Envelope.2") e.methodName = "addAddress" e.URI = "http://tempuri.org/" e.Parameters.Create "name", "Simon Fell" set a = e.Parameters.Create ("address","") a.Nodes.Create "street", "100 Spear Street" a.Nodes.Create "city", "San Francisco" a.Nodes.Create "state", "CA" a.nodes.Create "zip", "94107" e.SerializerFactory.PrimarySchema = "http://www.w3.org/1999/XMLSchema" wscript.echo e.serializethis generates the following SOAP message
<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:E='http://schemas.xmlsoap.org/soap/encoding/' xmlns:a='http://tempuri.org/' xmlns:b='http://www.w3.org/1999/XMLSchema-instance' xmlns:c='http://www.w3.org/1999/XMLSchema'> <S:Body><a:addAddress><name b:type='c:string'>Simon Fell</name> <address href='#a'/> </a:addAddress> <address E:root='0' id='a'><street b:type='c:string'>100 Spear Street</street> <city b:type='c:string'>San Francisco</city> <state b:type='c:string'>CA</state> <zip b:type='c:string'>94107</zip> </address> </S:Body></S:Envelope>