Ill write this blog post as I go, so it may be a little … choppy in spots.
I have said a couple of times – “you can (and should) use WSDL to document your callbacks/weblinks etc”. OK. Well, let’s put my money where my mouth is (actually, my employer’s money).
We have a couple of simple services described [? can’t find the confluence page anymore]. I would like to produce a WSDL describing these services. My test shall be: I should be able to feed that WSDL into the “metro” package (which generates java interfaces based on a WSDL) and connect to our service with some java code. I know that this works fine when connecting to the LSID service using the OMG WSDLs.
( … actually, it *used* to work fine back when our SOAP service was alive. Will metro handle HTTP bindings?)
To recap WSDL:
- We start with a Type. The standard types are the xsd types: int, string, and so on, as well as arrays. In fact … the types section
simply uses XSD! I wonder if I can simply import the RDF and BOA schemas?
- Types are aggregated together into Messages. A message is a number of key/value pairs.
These wind up being sets of function parameters, parts of a mime-multipart message, the values in a www-form-encoded post … whatever.
- Message are used by Operations. An operation has a message as input, and a message as output.
Operations correspond to “functions” or “methods”.
- Operations are grouped together into Port Types.
A port type corresponds to an interface.
- Port types are bound to a particular technology with a Binding.
This is the scary part. This part of wsdl allows you to say “to use the foo.bar operation on this service, make an HTTP GET request to this URL. Pass the baz part of the input message as URL parameter named “theBaz”, and base64 encode it”.”
There are a number of different well-known binding types – HTTP, SOAP, email (!) and so on.
Bindings are grouped together into Ports. A port is a physical location – a pointer to a single thing. The notion is that no matter what binding – no matter what technology – you use to talk to the port, you are talking to the same thing. A print server. A taxonomic repository. More strictly, the effect of invoking any operation on the port is the same, no matter what binding you use. If you call “increment count” via SOAP, then “get count” via CORBA or whatever, you will see that the count has incremented.
Thus, back before we turned off SOAP, our Port – conceptually, the repository – had HTTP, HTTPDirect, and SOAP bindings for the LSID Authority and Metadata port types (each of which has just one operation).
Some binding types allow the port declaration to add extra info to the binding. For instance, the LSID spec – common to all users of LSIDS – has HTTP a binding for “getMetadata”, describing the parameters (“lsid” and “metadataFormat”). At the port declaration, you specify the front part of the URL – our service declaration imports the OMG spec and states that the service is at “http://biodiversity.org.au/authority/metadata”.
How and what you can do here is particular to each well-known binding type.
- A group of Ports constitutes a Service.
Basically, an umbrella for all the different “things” you expose. I suppose you could expose your dev print node, image repo, and transaction server as one service, and the production versions of same as a different service
So. That’s WSDL.
Now, lets take our simplest and most basic service: “fetch http://biodiversity.org.au/apni.taxon/54321”.
Well, it’s not so simple and basic.
First, what you get back is some XML. The XML you get back varies according to content negotiation, or you can specify a suffix. And the XML is either RDF or an “app:Documents” document containing a TaxonConcept, TaxonName, or Publication element followed by a “links-to” element.
- To deal with the different types of result, I can start by creating named types, but just making them all xs:string. I can describe in the documentation section that the string contains XML.
- We have three parameters: namespace, objectid, and content type. But our users are dealing with atomic URIs a lot of the time, so we should support that.
- If I describe a port “getAfdTaxon” that just takes an objectid, then I can explicitly state that the returned XML will have an TaxonConcept record. But this requires describing six ports – it can be done later.
In all, the input message has the structure [(URI or (namespace and objectid)) and content-type?]. The content-type has two bindings – by way of an extension on the URI, or by way of a mime-type in the Accept header. Ideally it would be nice to type these values – one is an enumeration, one is a mime-type string. But again: too much work.
Ah ha! I found this in the spec: “The XSD type system can be used to define the types in a message regardless of whether or not the resulting wire format is actually XML”.
Well, that is interesting. I should be able to import my XML schema directly, and say – in the message type – “this output value is an ibis:TaxonConcept, and then say – in the binding – “the output value is put in the HTTP response as an XML stream”. It *may* even be possible to say that the object is represented as JSON … but that requires a whole world of complexity.
Well, I’ll see if I can get a basic WSDL going – the whole round-trip with metro – then see if I can add more detailed types to the results.