 | Level: Intermediate Nicholas Chase (nicholas@nicholaschase.com)Studio B
13 Aug 2004 An XForms form is handy as a Web service client because it enables you to easily send and receive an XML document, but what if you don't necessarily want to send the entire data instance? This tip explains how you can build an instance that includes a SOAP message along with other data, and then send only the SOAP message on submission.
In previous tips, you've discovered how an XForms form can easily send a Web service request and receive the response, but in all of those cases you were sending the entire instance to the Web service. However, this may not always fit with your plans. For example, the SOAP message may be part of a larger instance document that includes related data. In this tip, you'll learn how to create an XForms form around an instance that includes more than just a SOAP message and then send only the SOAP message on submission. This tip assumes that you are generally familiar with XForms and that you have the FormsPlayer XForms client installed. (See Resources for more information.)
The instance
Start by creating the basic form, including the instance, as shown in Listing 1:
Listing 1. The basic form
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>
<head>
<title>XForms and Web Services</title>
</head>
<body>
<object id="FormsPlayer"
classid="CLSID:4D0ABA11-C5F0-4478-991A-375C4B648F58">
<b>FormsPlayer has not loaded. Please check your installation.</b>
</object>
<?import namespace="xforms" implementation="#FormsPlayer" ?>
<xforms:model id="WeatherService">
<xforms:instance id="weatherInstance" >
<data>
<employees>
<emp id="1">
<name>Nick</name>
<zip>10314</zip>
</emp>
<emp id="2">
<name>Troy</name>
<zip>90210</zip>
</emp>
<emp id="3">
<name>Bob</name>
<zip>34652</zip>
</emp>
</employees>
<soapmessage>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature"
SOAP-ENV:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/">
<zipcode xsi:type="xsd:string"></zipcode>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</soapmessage>
</data>
</xforms:instance>
</xforms:model>
</body>
</html>
|
The instance has two basic parts: the employees data and the SOAP message, contained in the soapmessage element. You'll use the employees data to populate the SOAP message before submitting it. To do that, add a select1 control that presents each of the employees as an option, as shown in Listing 2:
Listing 2. Adding a select1 menu
...
</xforms:model>
<xforms:select1 appearance="minimal"
ref="instance('weatherInstance')//zipcode">
<xforms:label>Choose Employee</xforms:label>
<xforms:itemset nodeset="instance('weatherInstance')//emp">
<xforms:label ref="name"/>
<xforms:value ref="zip"/>
</xforms:itemset>
</xforms:select1>
</body>
</html>
|
This control loops through each of the available emp elements and creates a drop-down menu, as shown in Figure 1.
Figure 1: The basic data control
Because you've set the select1 element's ref attribute to point to the SOAP message's zipcode element, simply changing the drop-down menu adds the appropriate value to the Web service request.
Before you get to the submission, fill in the rest of the form.
Structuring the form
The goal of this project is to create a form that submits a SOAP message and then retrieves the SOAP response and displays the result. To do that, you need to add a submission trigger button and the ability to read the returned data, as shown in Listing 3:
Listing 3. Adding the rest of the form itself
...
</data>
</xforms:instance>
</xforms:model>
<xforms:switch id="switch1">
<xforms:case id="requestGUI">
<xforms:select1 appearance="minimal"
ref="instance('weatherInstance')//zipcode">
<xforms:label>Choose Employee</xforms:label>
<xforms:itemset nodeset="instance('weatherInstance')//emp">
<xforms:label ref="name"/>
<xforms:value ref="zip"/>
</xforms:itemset>
</xforms:select1>
<xforms:trigger style="display:block">
<xforms:label>Get sensor ambient temperature</xforms:label>
<xforms:action ev:event="DOMActivate">
<xforms:send submission="getweather" />
<xforms:toggle case="responseGUI" />
</xforms:action>
</xforms:trigger>
</xforms:case>
<xforms:case id="responseGUI">
<xforms:output ref="instance('weatherInstance')//return">
<xforms:label>Employee local temperature:</xforms:label>
</xforms:output>
</xforms:case>
</xforms:switch>
</body>
</html>
|
Here you separate the form into two cases because the instance that provides data for the controls will be different before and after submission. You start with the first case, which includes the employee data control and a trigger button. When the user clicks the trigger, the browser sends the getweather submission (which you'll create next) and changes to the responseGUI case, which will look for data in the new structure. Once in the responseGUI case, the browser displays the temperature, which is in the return element.
Now you just have to create the actual submission.
Creating the submission
To submit the form, you have to create a submission element. That submission element specifies not just where the data should go (through the action attribute), but also what data should go and what should happen to the data that comes back. For example, take a look at the simple submission element shown in Listing 4:
Listing 4. A simple submission element
<xforms:submission method="text-xml-post"
action="http://services.xmethods.net:80/soap/servlet/rpcrouter" />
|
This element does get the job done, but not as elegantly as you'd like. The XForms client -- or in this case, the browser -- sends the entire instance to the URL specified in the action, and then replaces the entire page with the response, just as it does for a traditional HTML form. However, that's not quite what you want. Instead, you want to send only the contents of the soapmessage element, and when the response comes back replace only the instance, leaving the rest of the form intact. You can specify all of this on the submission element, as shown in Listing 5:
Listing 5. The submission element
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</soapmessage>
</data>
</xforms:instance>
<xforms:submission id="getweather" method="text-xml-post"
ref="instance('weatherInstance')//soapmessage/*"
replace="instance"
action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
/>
</xforms:model>
|
The submission element specifies that you only want to send the contents of the soapmessage element, and that when the response comes back, it should only replace the instance and not the entire document.
Note that although you're only submitting a portion of the instance, when the Web service sends back a response, it replaces the entire instance, so this is generally a one-shot deal. To prevent that, you can specify that the returned message doesn't replace anything by using replace="none" -- but that only applies to situations in which it is the submission itself that's important, and not the response.
Summary
An XForms form enables you to create an instance that includes a SOAP message, but an instance can also include other data. For example, in this case you've created a form that uses data from elsewhere in the instance to help populate the actual SOAP message. To make this work, you can create a submission element that specifies the portion of the instance you actually want to submit. You can also use the submission element to specify what should happen to the returned data.
Resources
About the author  | |  | Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of an interactive communications firm in Clearwater, Florida, USA, and is the author of several books on Web development, including
XML Primer Plus
(Sams). He's currently trying to buy a farm so he and his wife can raise alpacas and chickens. He loves to hear from readers and can be reached at: nicholas@nicholaschase.com. |
Rate this page
|  |