|
|
ADVISOR VIEW
Create 100% Domino 6 Web Services
Explore how to combine LotusScript and Domino 6 XML objects to implement Web services now.
Subscribers: Sign-in to activate download link -- Demo database and a simple Web service client to test Web services.
Web services take us to the next generation of application architecture. For some it's still the future, but for you the future is here now. In fact, I've been showing how to create Web services with Domino 5 and LotusScript for more than a year (see "Host Web Services on Lotus Domino 5 on Domino 6 -- Now!" at http://Advisor.com/doc/09647). But when showing the tedious code for parsing the SOAP message, I always said, "In 6, you'd use the built-in XML classes."
Now it's time to show you how to create Web services in Domino 6 using the Domino Objects for handling XML. This article looks at the advantages of using these classes, and walks you through the code for a Domino/XML Web service that uses the new LotusScript SAX parser to process SOAP messages.
Web services
A Web service is a program that can be called using the Web services standards. A Web service client is a program that calls the Web service in the standard way. The "way cool" thing about Web services is that the call is independent of programming language, operating system, or platform because it uses XML. Any programming language can call any program on any platform; a Mac can call a Java program running on a remote Linux machine.
The mechanics of a typical Web service are:
- A Web service client calls a Web service by constructing a request in an XML format called SOAP.
- A URL call with an HTTP post.
- The server's Web service decodes the XML/SOAP message and runs the requested program with parameters.
- The server wraps the result in an XML/SOAP message called a response and sends it back to the Web service client.
This is a simple Web service. You can read more about WSDL, UDDI, and related topics on Advisor.com. A good place to start is "Domino's Standards Support Continues: WSDL and UDDI," by John Duggan, at http://Advisor.com/doc/08998.
In this article, I'll show you what happens on the server side.
How Domino works as a Web service host
The Domino server has long been able to do what Web services do -- even before Web services existed. The Web query "OpenAgent" can run an Agent (program) invoked by a URL call. With the advent of the Web services standards, it's simple enough to add this standard interface to existing Domino functionality. Here's how:
A Domino Web agent runs when called by a Web services client. For example, the URL http://GarysDell/Web+Service+Agent.nsf/WebServiceXML?OpenAgent calls the Domino server "GarysDell" and runs the agent "WebServiceXML" found in the "Web Service Agent.nsf" database.
This Web agent reads the XML/SOAP message, or request, that's contained in an HTTP post; it's just a way for URL calls to pass information -- you don't have to know how it works. Domino puts any URL post information in the agent's "Documentcontext" document, a Notes document that's automatically created when an agent runs. An item on this document called "Request_content" holds the XML/SOAP request.
SOAP= doc.GetItemValue("Request_content")(0) 'read soap
'request
This line of code puts the SOAP request into a variable call "SOAP." Here's an example of a SOAP request:
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
\"http://schemas.xmlsoap.org/soap/envelope/\">
<SOAP-ENV:Body> <m:GetQuote xmlns:m=\"uri:Domino\"> <DocIndex SOAP-ENV:encodingStyle=\"http://schemas.
xmlsoap.org/soap/encoding/\">0</DocIndex></m:GetQuote>
</SOAP-ENV:Body></SOAP-ENV:Envelope>
This request is asking to run the method "GetQuote" with the parameter of "0" using a name space called "Domino." There are many ways to parse the information. Originally I did it this way:
bodyPos= Instr(1,SOAPin,|<SOAP-ENV:Body>|)+15
methodPos= Instr(bodyPos,SOAPin,|:|)+1
methodEnd=Instr(methodPos,SOAPin,| |)
MethodName = Mid(SOAPin,methodPos,(methodEnd-methodPos))
nameSpacePos= Instr(methodEnd,SOAPin,|uri:|)+4
nameSpaceEnd=Instr(nameSpacePos,SOAPin,|"|)
NameSpace=Mid(SOAPin,nameSpacePos, _
(nameSpaceEnd-nameSpacePos))
argPos=Instr(nameSpaceEnd,SOAPin,|>|)+1
argPos2=Instr(argPos, SoapIn, |>|)+1
argEnd=Instr(argPos2,SOAPin,|</|)
argValue =Mid(SOAPin,argPos2,(argEnd-ArgPos2))
What you want to do here is map the information from the SOAP request to Domino. This code pulls out the MethodName ("GetQuote"), NameSpace ("Domino"), and argValue ("0") from the SOAP request. These values are used to call a LotusScript function, "GetQuote." The NameSpace value from that SOAP message, "Domino," is used to load a LotusScript library, called "Domino," that contains the LotusScript function "GetQuote" on the Domino side. The agent is generic. It adds a Web service interface to any LotusScript function that takes one parameter.
Because the SOAP request is XML, I can use the new XML classes in Domino 6 to achieve the same goal. Here's an example:
Sub Initialize
...
SOAP= doc.GetItemValue("Request_content")(0)
SAXResult=""
Found_Flag=False
Set saxParser=s.CreateSAXParser(SOAP)
On Event SAX_Characters From saxParser Call SAXCharacters
On Event SAX_EndDocument From saxParser Call SAXEndDocument
On Event SAX_EndElement From saxParser Call SAXEndElement
On Event SAX_Error From saxParser Call SAXError
On Event SAX_FatalError From saxParser Call SAXFatalError
On Event SAX_IgnorableWhitespace From saxParser Call
SAXIgnorableWhitespace
On Event SAX_NotationDecl From saxParser Call
SAXNotationDecl
On Event SAX_ProcessingInstruction From saxParser Call
SAXProcessingInstruction
On Event SAX_StartDocument From saxParser Call
SAXStartDocument
On Event SAX_StartElement From saxParser Call
SAXStartElement
On Event SAX_UnparsedEntityDecl From saxParser Call
SAXUnparsedEntityDecl
On Event SAX_Warning From saxParser Call SAXWarning
saxParser.Process ' initiate parsing
answers= "Name Space= " & NameSpace & " Method Name= "
& MethodName & " Parameter= " & Parameter
...
End Sub
But, if this code works, where are the variables NameSpace, MethodName, and Parameter being set? You can see the SOAP variable being passed in as the saxParser object is created. The rest looks very different to LotusScript developers.
Here's how it works
The saxParser object does nothing until the saxParser.Process method is called near the end of the code. Then the saxParser object starts reading the XML found in the SOAP variable from the beginning. As it encounters XML fundamentals, events are raised. For example, in the case of encountering the beginning of a document, a SAX_StartDocument event is triggered. This code calls the SAXStartDocument function when this event is raised. You then must write the function SAXStartDocument to tell the parser what to do when it finds the beginning of the XML document.
You have events to cover anything the parser might find in the XML. In this case, most of the action happens in the SAXStartElement function:
Byval elementname As String, Attributes As
NotesSaxAttributeList)
Dim i As Integer
If Found_Flag = True Then
Found_Flag= False
MethodName = Right$(elementname,
(Len(elementname)- Instr(elementname,":")))
If Attributes.Length > 0 Then
Dim attrname As String
For i = 1 To Attributes.Length
attrname = Attributes.GetName(i)
If ("xmlns"= Left$(attrname,5)) Then
NameSpace = Right$(Attributes.GetValue(attrname),
(Len(Attributes.GetValue(attrname))-
Instr(Attributes.GetValue(attrname),":")))
End If
Next
End If
End If
If elementname = "SOAP-ENV:Body" Then
Found_Flag=True
End If
The first element in your SOAP request is the SOAP-ENV:Body. After you read past that element, indicated by the flag, the next one is Method name. Keep in mind that Domino 6's XML parsers are fairly old and aren't "name space"-aware, so you must manually split the name space from the method name. Now, you have the Method name and the name space. The SAXCharacters function collects the parameter value.
After you have these values, you can load the LotusScript Library with the same name as the name space; call a function in that library with the same name as the method name, and pass in the parameter with the value in the SOAP request:
'The NameSpace will be the name of the Script Library
'to load.
'The MethodName will be the name of the function in
'the Script.
'Library loaded by this agent (NameSpace)
LSlib = NameSpace
MyFunction = MethodName
Library= |"| & LSlib & |"|
Arg= |("| & Parameter & |")|
' load the right LotusScript Library and call the
' function
CallString = |Use | & Library & |
response = | & MyFunction & Arg
Execute CallString
The result of the function call is placed in the global variable "response."
Before you can send the SOAP response document you must tell Domino not to convert it to HTML, which it does by default. You do this with the command:
Print "Content-Type: text/xml"
Finally, you wrap the result of the LotusScript function call into a "SOAP response" format and send it back to the Web service client:
strTmp = |<?xml version="1.0" encoding="UTF-8" _
standalone="no"?>| &_
|<SOAP-ENV:Envelope xmlns:SOAP-ENV= _
"http://schemas.xmlsoap.org/soap/envelope/" _
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _
xmlns:xsd="http://www.w3.org/2001/XMLSchema">| & _
|<SOAP-ENV:Body>| & _
|<m:| & MethodName & "Response" & | xmlns:m="| & _
NameSpace & |" SOAP-ENV:encodingStyle= _
"http://schemas.xmlsoap.org/soap/encoding/">| & _
|<Answer xsi:type="xsd:string">| & response & _
|</Answer>| & |</m:| & MethodName & |Response>| & _
|</SOAP-ENV:Body>| & _
|</SOAP-ENV:Envelope>|
Print strTmp
A better way to format the SOAP response would be to use an XSLTransform. In an upcoming article I'll show you how.
What have we learned?
You can draw several conclusions from this exercise. The SAX parser is very cool. It can rip through a large XML file and do anything you can code. In this case, it seems a bit of overkill. The number of lines of code nearly doubled. Plus, this solution won't work on Domino 5. So, what's gained? Some experience working with a SAX parser, which is an industry standard even if the Domino version is a bit old. Also, the code is just cool. Besides, the real benefit of using industry-standard technologies such as XML is that years from now, other developers can look at your code and be able to understand, edit, reuse, and support it.
For production applications, consider using the DOM Parser, XSLTransformer, or just staying with LotusScript string handling if you're dealing with a Domino 5 environment. While I was at Lotus, I set in motion plans to make creating Domino 7 Web services as easy as creating an Agent; let's hope it happens. Until then, you have many options. The best part is that a good Web service can be used by many client applications today and in the future without changes. Domino Web services can work with WebSphere Application Server, .NET, Microsoft Office, or any Web service clients.
You can download this demo and a demo Web service client from http://Advisor.com/doc/12607.
Gary Devendorf is Microsoft technical evangelist on collaboration, including SharePoint and "Domino.Net". For more than 7 years Gary was IBM Lotus product manager for LotusScript, Domino Designer, Domino Objects, XML, COM toolkit, Domino Collaboration Objects, Java, Web Services and more. Gary is a popular writer and speaker who gave more technical presentations than anyone at Lotus. http://garydev.advisorblogs.com
Keyword Tags: Application Development, IBM, IBM Lotus, IBM Lotus Domino, IBM Software, Web Services, XML
ADVISORAMA One man practicing sportsmanship is far better than 50 preaching it. -- Knute Rockne, football coach
|
ARTICLE INFO
Print Edition: August 2003, Page 6
FREE ACCESS
Article files are on this issue's Resource CD.
File: Demo database and a simple Web service client to test Web services. Subscribers, log-in for Download link.
|
SUBSCRIPTION STATUSYou are not signed-in. If you are a subscriber to this publication, sign-in above to access locked articles. To subscribe or renew go to www.AdvisorStore.com.
|

Get it all -- every current and past ADVISOR tech/business publication, now all-in-one subscription, with new articles and a huge reference library packed with expert advice, how-to and downloads. Subscribe now to get it all.![]() 
Read the advanced guide to creating custom business database solutions with FileMaker software. Subscribe now to gain access to all the archives and downloads.![]() 
Learn the fundamentals of using FileMaker Pro software. Every issue gives you step-by-step instructions on creating the databases you need. Subscribe now!![]()
![]()
![]()
 ![]()

Submit your tips, techniques and advice and let Advisor promote your business and build your career. Show the world what you know!![]()  ![]()
|
|