Skip to main content

skip to main content

developerWorks  >  XML | SOA and Web services  >

Tip: Use XForms to send and receive Web services messages

Leverage the power of XML

developerWorks
Document options

Document options requiring JavaScript are not displayed


Rate this page

Help us improve this content


Level: Intermediate

Nicholas Chase (nicholas@nicholaschase.com), President, Chase and Chase, Inc.

24 Jun 2004

One of the great strengths of XForms is the fact that an XForms client can send its data as XML, and that it receives XML in return. This capability can be exceptionally useful in the field of Web services, where that's exactly what gets sent and received: XML messages. In this tip, the author looks at how to use an XForms browser as a Web services client, sending a SOAP request and displaying the results directly in the browser.

This tip assumes a basic familiarity with XForms and with Web services. It uses the FormsPlayer plug-in for Internet Explorer (see Resources to download it).

The Web service

In this tip, I'm going to show you how to create an XForms form that sends a request to a Web service and then displays the results. To keep things simple, I'm going to use the ubiquitous weather example, sending a ZIP code and receiving the current temperature. The actual Web service is provided by XMethods.net (see Resources).

The initial request is just a SOAP message, such as:


Listing 1. Initial SOAP request
<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">02134</zipcode>
      </ns1:getTemp>
   </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>

You'll use the XForms form to provide a value for the zipcode element. When you submit it to the service, you'll get a response such as:


Listing 2. Response
<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:getTempResponse xmlns:ns1="urn:xmethods-Temperature" 
           SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <return xsi:type="xsd:int">86</return>
      </ns1:getTempResponse>
   </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>

You'll also use the form to retrieve the return value and display it.



Back to top


The basic XForms form

Start by creating the basic form. An XForms form consists of a model and controls. The model includes information such as the instance, which represents the data to be displayed and submitted, and the submission, which includes information on where and how to send the data:


Listing 3. A basic XForms 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:ns1="urn:xmethods-Temperature"
   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="messages">

           <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">02134</zipcode> 
                 </ns1:getTemp> 
              </SOAP-ENV:Body> 
           </SOAP-ENV:Envelope> 

         </xforms:instance>

         <xforms:submission id="getweather"
             method="text-xml-post"
             replace="instance"
             action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
             />

      </xforms:model>

</body>
</html>

First, tell Internet Explorer to load the FormsPlayer object. If it's not loaded, the browser displays the contents of the tag, telling the user to download and install it.

Next you have the model, which includes the instance and the submission. The instance is not just the data to be displayed; it's also the data that will eventually be submitted, so it's identical to the SOAP request presented earlier in Listing 1. You'll get a closer look at the submission itself when you actually submit the data.

In the meantime, you need to actually create the form:


Listing 4. Create the form
...
   <xforms:model id="WeatherService">

     <xforms:instance id="messages">

       <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">02134</zipcode> 
             </ns1:getTemp> 
          </SOAP-ENV:Body> 
       </SOAP-ENV:Envelope> 

     </xforms:instance>

     <xforms:submission id="getweather"
           method="text-xml-post"
           replace="instance"
           action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
           />

   </xforms:model>

   <xforms:input ref="instance('messages').//zipcode">
   <xforms:label>Zip code: </xforms:label>
   <xforms:hint>Enter a zip code and submit the form for the current
         temperature in that area.</xforms:hint>
  </xforms:input>

</body>
</html>


Figure 1: The simple text control
The simple text control

When the user changes the value in this control, it changes the corresponding node of the XML contained in the instance. So if you were to change the value in that field to, say, 10314, the instance document would look like this in memory:


Listing 5. Instance document
<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">10314</zipcode>
       </ns1:getTemp> 
   </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

It is this document that gets submitted to the service. Before you get that far, however, you need to look at the state of the form.



Back to top


Changing states

When you submit the form, you will actually replace the instance document with a second instance document that has a different structure, so in order to display information from it, you will need controls based on that structure instead of the original one. You can't, however, include both of these controls on the page at the same time, because one of them will always refer to a nonexistent node, causing an error. To get around this problem, you need to create a situation in which only one set appears at a time. You can do that with a switch:


Listing 6. Add a switch
...
   </xforms:model>

   <xforms:switch id="switch1">

      <xforms:case id="requestGUI">

         <xforms:input ref=".//zipcode">
            <xforms:label>Zip code: </xforms:label>
            <xforms:hint>Enter a zip code and submit the form for the current
                  temperature in that area.</xforms:hint>
         </xforms:input>

         <xforms:trigger style="display:block">
            <xforms:label>Change to results case</xforms:label>
            <xforms:action ev:event="DOMActivate">
               <xforms:toggle case="responseGUI" />
            </xforms:action>
         </xforms:trigger>

      </xforms:case>

      <xforms:case id="responseGUI">

         Results go here.

         <xforms:trigger>
            <xforms:label>Change to request case</xforms:label>
            <xforms:action ev:event="DOMActivate">
               <xforms:toggle case="requestGUI" />
            </xforms:action>
        </xforms:trigger>

     </xforms:case>

 </xforms:switch>

</body>
</html>

Here there are two cases. The first is displayed by default. To this case you add a trigger, or button, that activates when you click it, as in Figure 2.


Figure 2. Add a trigger
Add a trigger

When it does, it executes everything in the action element, which in this case is to toggle the case to the responseGUI state. This tells the browser to display only that case, as in Figure 3:


Figure 3. The results case
The results case

Using this form, the user can toggle back and forth by clicking the buttons. Now you need to add the form submission.



Back to top


Submitting the form

Of course, the form isn't much good to you this way. What you ultimately want is to switch to the results case after you submit the form. You can do that by adding the submission to the action:


Listing 7. Add the submission to the action
...
         <xforms:trigger style="display:block">
            <xforms:label>Get current temperature</xforms:label>
            <xforms:action ev:event="DOMActivate">
               <xforms:send submission="getweather" />
               <xforms:toggle case="responseGUI" />
            </xforms:action>
         </xforms:trigger>
...

This simply tells the browser to execute the submission getweather when the user clicks the button. Now, when you created the submission, you added some information to it:


Listing 8. Specify the submission as an XML post
...
      <xforms:submission id="getweather"
           method="text-xml-post"
           replace="instance"
           action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
               />
...

This submission specifies that you're submitting it as an XML post, which is perfect for a SOAP message, and that you want to replace the instance. This way, when it comes back, the instance looks something like Listing 9:


Listing 9. Returned instance
<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:getTempResponse xmlns:ns1="urn:xmethods-Temperature" 
          SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <return xsi:type="xsd:int">86</return> 
      </ns1:getTempResponse> 
   </SOAP-ENV:Body> 
 </SOAP-ENV:Envelope> 

To see the results, you need to retrieve them from within the resultGUI case:


Listing 10. Retrieve the results
  <xforms:case id="responseGUI">

    <xforms:output ref="instance('messages')//return" 
            style="width:40ex;display:block;">
      <xforms:label>Current Temperature:</xforms:label>
    </xforms:output>

  </xforms:case>
...

This way, when you submit the form, you get the resulting temperature, as in Figure 4.


Figure 4. The resulting page
The resulting page


Back to top


Summary

Because an XForms form sends and receives XML documents, it makes an excellent Web services client. In this tip, I showed you the basic process of using an XForms form to request information from a Web service. The process looked like this:

  1. The browser displays information from the instance document, which is structured as a SOAP request.
  2. The browser sends the instance document (including the ZIP code) to the Web service.
  3. The Web service sends a response (including the temperature) to the browser, which uses it to replace the original instance document.
  4. The browser switches to a second set of controls, which display the information returned by the Web service.


Resources



About the author

Photo of Nicholas Chase

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


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top