Skip to main content

Tip: Send multiple Web services requests from XForms

Submit a request and then use the response as the basis for a second request.

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.

Summary:  A typical HTML form only lets you submit to one URL at a time, which makes it difficult to retrieve information from multiple Web services. This tip shows you how to use XForms to solve that problem by using multiple submissions from a single form.

View more content in this series

Date:  03 Sep 2004
Level:  Intermediate
Activity:  2197 views

Unlike traditional HTML forms, which are typically designed to either get information from or give information to the user, Web services are ultimately designed to provide information to an application; the user is almost an afterthought. This means that while it's generally sufficient to submit an HTML form to a single location and get a response, you often need to submit a request to a Web service and then use the response as the basis for a second request.

In this tip, you'll create an XForms form that provides information on a series of temperature sensors. The form takes a sensor identifier and submits it to a Web service that returns the zip code for that sensor. The form then automatically submits the zip code to a second service that provides the ambient temperature at the location that corresponds to that zip code. This tip assumes that you are generally familiar with XForms and that you have the FormsPlayer XForms client installed. (See the Resources for more information.)

The basic request form

Start by creating the basic form (shown in Listing 1), into which the user enters a sensor ID:


Listing 1. The 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: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="sensorInstance">

             <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:getZip xmlns:ns1="urn:example-sensorZip" 
                      SOAP-ENV:encodingStyle=
                             "http://schemas.xmlsoap.org/soap/encoding/"> 
                      <sensorId xsi:type="xsd:string"></sensorId> 
                   </ns1:getZip> 
                </SOAP-ENV:Body> 
             </SOAP-ENV:Envelope> 

         </xforms:instance>

      </xforms:model>

      <xforms:input ref="instance('sensorInstance')//sensorId">
          <xforms:label>Sensor ID: </xforms:label>
          <xforms:hint>Enter the ID for the sensor whose ambient 
                temperature you want to check.</xforms:hint>
      </xforms:input>

</body>
</html>

Here you have a simple form that enables the user to enter a value, as you can see in Figure 1. That value represents the contents of the sensorId element in the sensorInstance instance. The sensorInstance just happens to be in the form of a SOAP request, which you can then send to a Web service to get a response.


Figure 1: The basic form
The basic form

Submitting to the first service

The first part of the form takes the sensor ID and submits it to a Web service that returns a zip code. To make that happen, you have to add a submission element and a trigger that sends it, as shown in Listing 2.


Listing 2. Submitting the form
...
    <xforms:model id="WeatherService">

       <xforms:instance id="sensorInstance">

             <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:getZip xmlns:ns1="urn:example-sensorZip" 
                   SOAP-ENV:encodingStyle=
                         "http://schemas.xmlsoap.org/soap/encoding/"> 
                   <sensorId xsi:type="xsd:string"></sensorId> 
                </ns1:getZip> 
              </SOAP-ENV:Body> 
             </SOAP-ENV:Envelope> 

       </xforms:instance>

       <xforms:submission id="getzip"
        method="text-xml-post"
        replace="instance"
        ref="instance('sensorInstance')"
        action="http://www.nicholaschase.com/sensors/getZipService.php"
       />

      </xforms:model>

<xforms:switch id="switch1">
  <xforms:case id="requestGUI">

      <xforms:input ref="instance('sensorInstance')//sensorId">
          <xforms:label>Sensor ID: </xforms:label>
          <xforms:hint>Enter the ID for the sensor whose ambient 
                temperature you want to check.</xforms:hint>
      </xforms:input>

      <xforms:trigger style="display:block">
          <xforms:label>Get sensor ambient temperature</xforms:label>
          <xforms:action ev:event="DOMActivate">
              <xforms:send submission="getzip" /> 
              <xforms:toggle case="responseGUI" />
          </xforms:action>
      </xforms:trigger>

  </xforms:case>

  <xforms:case id="responseGUI">

       <xforms:output ref="instance('sensorInstance')//return">
          <xforms:label>Sensor zip code:</xforms:label>
       </xforms:output>

  </xforms:case>
</xforms:switch>

</body>
</html>

When you click the trigger button, two things happen. First, the browser sends the getzip submission. This submission is defined in the model using the submission element, which determines which data gets submitted and where it goes. In this case, you're sending the sensorInstance data to a service, which returns a SOAP message with the response. The actual zip code is in the return element.

After sending the submission, the form changes cases from the requestGUI, which shows the original form, to the responseGUI, which shows the returned data (see Figure 2).


Figure 2: The initial response
The initial response

The second submission

Now that you have the zip code, you have to find a way to send it to the weather service. Start by creating an instance to submit to that service, as shown in Listing 3:


Listing 3. Add the second instance
...
  <xforms:model id="WeatherService">

    <xforms:instance id="sensorInstance">

        <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:getZip xmlns:ns1="urn:example-sensorZip" 
                 SOAP-ENV:encodingStyle=
                        "http://schemas.xmlsoap.org/soap/encoding/"> 
                 <sensorId xsi:type="xsd:string"></sensorId> 
              </ns1:getZip> 
           </SOAP-ENV:Body> 
        </SOAP-ENV:Envelope> 

     </xforms:instance>

     <xforms:instance id="weatherInstance">

        <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> 

     </xforms:instance>

     <xforms:submission id="getzip"
         method="text-xml-post"
         replace="instance"
         ref="instance('sensorInstance')"
         action="http://www.nicholaschase.com/sensors/getZipService.php"
        />

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

    </xforms:model>
...

The overall idea here is the same as what you've done so far: Create an instance that looks like a Web service request and then send it to a Web service as defined in the submission element. All you need to do now is to find a way to get the zip code returned by the first submission into the second instance before submitting the second instance. Fortunately, you can do that using the setvalue element:


Listing 4. Linking the two submissions
...
         <xforms:submission id="getweather"
             method="text-xml-post"
             replace="instance"
             ref="instance('weatherInstance')"
             action="http://services.xmethods.net:80/soap/servlet/rpcrouter"
            />

      </xforms:model>

<xforms:switch id="switch1">
  <xforms:case id="requestGUI">

      <xforms:input ref="instance('sensorInstance')//sensorId">
          <xforms:label>Sensor ID: </xforms:label>
          <xforms:hint>Enter the ID for the sensor whose ambient 
                temperature you want to check.</xforms:hint>
      </xforms:input>

      <xforms:trigger style="display:block">
        <xforms:label>Get sensor ambient temperature</xforms:label>
        <xforms:action ev:event="DOMActivate">
          <xforms:send submission="getzip" /> 
          <xforms:setvalue value="instance('sensorInstance')//return" 
                         ref="instance('weatherInstance')//zipcode"/> 
          <xforms:send submission="getweather" /> 
          <xforms:toggle case="responseGUI" />
        </xforms:action>
      </xforms:trigger>

   </xforms:case>

   <xforms:case id="responseGUI">

       <xforms:output ref="instance('sensorInstance')//return">
          <xforms:label>Sensor zip code:</xforms:label>
       </xforms:output>
       <br />
       <xforms:output ref="instance('weatherInstance')//return">
          <xforms:label>Ambient sensor temperature:</xforms:label>
       </xforms:output>

   </xforms:case>
</xforms:switch>

</body>
</html>

If you look at the trigger, you'll realize that you've simply added more actions for the browser to perform. After submitting the first request, the sensorInstance instance will have a return element that holds the desired zip code. Using the setvalue element, you copy that value to the weatherInstance instance, which you subsequently submit. The results can then be shown in the page, as seen in Figure 3.


Figure 3. The final results
The final results

Summary

XForms is designed to separate the process of displaying data from the process of manipulating it, so it is very well suited to performing multiple submissions with a single request. This process involves creating an instance for each service, with each consisting of a SOAP request for that particular service. When the user causes an event such as activating a button, you can execute any number of actions, and because each instance can have its own submission, you can simply submit each instance in turn, moving data between instances using the setvalue element.


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.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, SOA and Web services
ArticleID=15082
ArticleTitle=Tip: Send multiple Web services requests from XForms
publish-date=09032004
author1-email=nicholas@nicholaschase.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers