6.1 WAP and WML

Java Servlet Programming, 2nd Edition > 6. Sending Multimedia Content > 6.1 WAP and WML

 
< BACKCONTINUE >

6.1 WAP and WML

The Wireless Application Protocol (WAP, pronounced like whap) is a de facto standard for providing Internet communications to mobile phones, pagers, and personal digital assistants (PDAs) on wireless networks across the world. It was created in 1998 by Ericsson, Nokia, Motorola, and Phone.com (formerly Unwired Planet) who wisely desired to create a standard protocol rather than competing proprietary protocols. Together the four companies founded the WAP Forum (http://www.wapforum.org), a democratically organized group whose participation has since grown to more than 400 members.

WAP consists of a set of specifications for developing applications to run on wireless networks. The WAP Protocols covers both the application level (the WML markup language and the WMLScript scripting language, collectively known as the Web Application Environment or WAE) and the underlying network transport layers (the WDP, WTLS, WTP, and WSP protocols). The WAP stack parallels the web protocol stack, as shown in Figure 6-1.

Figure 6-1. Web and WAP stacks

The primary difference is that WAP is optimized for low-bandwidth wireless communication. For example, WAP uses a binary format for request and response structure instead of the text format used by the Web.

A WAP Gateway acts as an intermediary between the WAP network and the Web. A gateway converts a WAP request into a web request, and the following web response into a WAP response. You can think of a WAP Gateway as a "protocol stack converter."[1] WAP Gateways give WAP devices access to standard web servers. Figure 6-2 demonstrates.

[1] WAP Gateways are normally provided transparently by the bearer of a wireless network. For those interested in setting up their own gateway or in learning how a gateway operates, there's an open source WAP Gateway named Kannel available at http://www.kannel.3glab.org/.

Figure 6-2. The role of a WAP Gateway

The short story is, as a wireless developer, you can ignore the WAP transport layer. A WAP Gateway takes care of making a device's request look like an HTTP request. The layer where you must concentrate is the application layer, where instead of generating HTML you instead generate WML.

6.1.1 WML

Portable devices are far more limited than PCs. They have slow processors, tiny amounts of memory, small displays, and extremely limited bandwidth. Because of these limitations, WAP devices don't interact with normal HTML and image content. Instead, they use the Wireless Markup Language (WML) for text content, the WMLScript language for scripting, and the Wireless Bitmap (WBMP) monochromatic image format for graphics.

WML is an application of XML, similar to HTML but with far fewer tags. It follows the metaphor of a deck of cards. Each card represents a screen or page, and each deck is a collection of cards that can be transferred at once. Sending content a deck at a time instead of a card at a time reduces the latency (how long it takes to view the next card) when accessing content.

Example 6-1 shows a static WML document that acts as a minibartender. It provides a list of drinks to choose from, then displays the ingredients of the selected drink. Notice the document is XML with a well-known DTD.

Example 6-1. A WML Minibartender, drinks.wml
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC   "-//WAPFORUM//DTD WML 1.1//EN"   "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml>   <card  title="Select a Drink">     <p>     Select a Drink:     <anchor>       Kamikaze <go href="#Kamikaze" />     </anchor><br/>     <anchor>       Margarita <go href="#Margarita" />     </anchor><br/>     <anchor>       Boilermaker <go href="#Boilermaker" />     </anchor><br/>     </p>   </card>   <card  title="Kamikaze">     <p>     To make a Kamikaze:<br/>     1 part Vodka<br/>     1 part Triple Sec<br/>     1 part Lime Juice<br/>     </p>   </card>   <card  title="Margarita">     <p>     To make a Margarita:<br/>     1 1/2 oz Tequila<br/>     1/2 oz Triple Sec<br/>     1 oz Lime Juice<br/>     Salt<br/>     </p>   </card>   <card  title="Boilermaker">     <p>     To make a Boilermaker:<br/>     2 oz Whiskey<br/>     10 oz Beer<br/>     </p>   </card> </wml>

The document contains four cards. The first card, displayed by default, provides a short list of drinks. Each drink name is a hyperlink to another card in the document, with the card name given with the #Cardname syntax. The later cards each display the ingredients for a given drink. The entire document can be transferred to a device in a single step, even though only parts are available at any point in time.

6.1.2 WAP Device Simulators

To make it possible to execute WAP applications without taking to the airwaves, various companies have created WAP-enabled phone simulators, software to run on a PC that acts like (and even looks like!) a phone. Figure 6-3 shows how the document appears on the Phone.com UP.Simulator (http://www.phone.com). Other simulators and WAP development kits can be found at http://www.nokia.com, http://www.ericsson.com, http://www.motorola.com, and many more sites. Some standard web browsers, including Opera, also support WML.

Figure 6-3. Don't drink and dial

6.1.3 Serving WAP Content

For WAP content to be served correctly, the server must send the WML file with the explicit content type text/vnd.wap.wml. Some servers set this content type automatically for .wml files. Others have to be told about the new type. A server can be told about WAP-related content types with the following <mime-mapping> elements in the server's web.xml deployment descriptor. The web.xml snippet in Example 6-2 adds the proper content types for WML, WMLScript, and Wireless Bitmap files.

Example 6-2. Adding WAP Mime Types to web.xml
<!-- ... --> <mime-mapping>     <extension>         wml     </extension>     <mime-type>         text/vnd.wap.wml     </mime-type> </mime-mapping> <mime-mapping>     <extension>         wmls     </extension>     <mime-type>         text/vnd.wap.wmlscript     </mime-type> </mime-mapping> <mime-mapping>     <extension>         wbmp     </extension>     <mime-type>         image/vnd.wap.wbmp     </mime-type> </mime-mapping> <!-- ... -->

In addition, some web application programmers find it useful to add index.wml to the default list of files to search in a directory, known as the welcome file list. The web.xml deployment descriptor block in Example 6-3 sets the welcome file list to index.html, index.htm, and index.wml, in that order. This indicates to the server a request for http://localhost/wap should resolve to http://localhost/wap/index.wml if index.html and index.htm do not exist.

Example 6-3. Adding WAP Welcome Files to web.xml
<!-- ... --> <welcome-file-list>   <welcome-file>     index.html   </welcome-file>   <welcome-file>     index.htm   </welcome-file>   <welcome-file>     index.wml   </welcome-file> </welcome-file-list> <!-- ... -->

The <welcome-file-list> feature comes in handy for non-WAP uses as well. For example, a web application that for historical reasons uses home.html as the default welcome file can add home.html to the welcome file list and safely deploy across any servlet-enabled server.

6.1.4 Dynamic WAP Content

There's almost no technical difference in how a servlet serves dynamic WAP content and how a servlet serves dynamic web content. To serve WAP a servlet must simply change the response content type to text/vnd.wap.wml and the response content from HTML to WML. To a servlet the request is normal HTTP; the external WAP Gateway handles the WAP and web protocol stack conversion. But while the technical difference is slight, the occasion when it's appropriate to use a servlet for dynamic content generation can be more limited.

On the Web, there's usually little performance penalty in contacting the server for minor tasks and page updates. With WAP the performance penalty can be more noticeable. As a result, simple tasks such as card navigation and form data validation, which on the Web might involve a servlet, are best performed in WAP using the WML deck metaphor and the WMLScript client-side scripting ability. For example, the previous bartender uses a set of WML cards to serve its drinks without contacting the server.

Servlets still have their place of course. A servlet (or other server script) is needed to generate a deck of cards containing dynamic information pulled from a database. A servlet is also necessary to handle queries against data too large to fit on a set of cards. Devices are often limited to storing just 1400 bytes of compiled page data.

Example 6-4 and Example 6-5 demonstrate with a WML form and WML-generating servlet that together provide an area code lookup application. A client may enter a telephone area code into the form, submit it to the servlet, and learn which state or region contains that code. People with WAP-enabled phones can use this application to physically locate any Caller ID number.

Example 6-4. Using WML to Ask for an Area Code
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC   "-//WAPFORUM//DTD WML 1.1//EN"   "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml>   <card  title="Enter an Area Code">     <do type="accept" label="Enter">       <go href="servlet/AreaCode?code=$(code)"/>     </do>     <p>     Enter an Area Code: <input type="text" name="code"/>     </p>   </card> </wml>

This WML document holds a simple form with a text input area. Whatever area code is entered gets sent to the AreaCode servlet as the code parameter. We use the $(code) variable substitution syntax to construct the query string manually.

Example 6-5. Using WAP to Locate an Area Code
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class AreaCode extends HttpServlet {   Properties lookup = new Properties();   public void init() {     // Transfer raw data from below into a fast-lookup Properties list     for (int i = 0; i < data.length; i++) {       Object[] record = data[i];       String state = (String) record[0];       int[] codes = (int[]) record[1];       for (int j = 0; j < codes.length; j++) {         lookup.put(String.valueOf(codes[j]), state);       }     }   }   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setContentType("text/vnd.wap.wml");     PrintWriter out = res.getWriter();     String msg = null;     String code = req.getParameter("code");     String region = null;     if (code != null) {       region = lookup.getProperty(code);     }     out.println("<?xml version=\"1.0\"?>");     out.println("<!DOCTYPE wml PUBLIC " +                 "\"-//WAPFORUM//DTD WML 1.1//EN\" " +                 "\"http://www.wapforum.org/DTD/wml_1.1.xml\">");     out.println("<wml>");     out.println("<card id=\"Code\" title=\"Code\">");     out.println("  <p>");     out.println("  Area code '" + code + "'<br/>");     if (region != null) {       out.println("  is " + region + ".<br/>");     }     else {       out.println("  is not valid.<br/>");     }     out.println("  </p>");     out.println("</card>");     out.println("</wml>");   }   // Raw area code data for each region   private Object[][] data = new Object[][] {     { "Toll Free", new int[] { 800, 855, 866, 877, 888 } },     { "Alabama", new int[] { 205, 256, 334 } },     { "Alaska", new int[] { 907 } },     { "Alberta", new int[] { 403, 780 } },     { "Arizona", new int[] { 480, 520, 602, 623 } },     { "Arkansas", new int[] { 501, 870 } },     { "British Columbia", new int[] { 250, 604 } },     { "California", new int[] { 209, 213, 310, 323, 369, 408, 415, 424, 510,       530, 559, 562, 619, 626, 627, 650, 661, 707, 714, 760, 805, 818, 831,       858, 909, 916, 925, 949 } },     { "Colorado", new int[] { 303, 719, 720, 970 } },     { "Connecticut", new int[] { 203, 475, 860, 959 } },     { "Deleware", new int[] { 302 } },     { "District of Columbia", new int[] { 202 } },     { "Florida", new int[] { 305, 321, 352, 407, 561, 727, 786, 813, 850, 863,       904, 941, 954 } },     { "Georgia", new int[] { 229, 404, 478, 678, 706, 770, 912 } },     { "Hawaii", new int[] { 808 } },     { "Idaho", new int[] { 208 } },     { "Illinois", new int[] { 217, 224, 309, 312, 618, 630, 708, 773, 815,       847 } },     { "Indiana", new int[] { 219, 317, 765, 812 } },     { "Iowa", new int[] { 319, 515, 712 } },     { "Kansas", new int[] { 316, 785, 913 } },     { "Kentucky", new int[] { 270, 502, 606, 859 } },     { "Louisiana", new int[] { 225, 318, 337, 504 } },     { "Maine", new int[] { 207 } },     { "Manitoba", new int[] { 204 } },     { "Maryland", new int[] { 240, 301, 410, 443 } },     { "Massachusetts", new int[] { 413, 508, 617, 781, 978 } },     { "Michigan", new int[] { 231, 248, 313, 517, 586, 616, 734, 810, 906 } },     { "Minnesota", new int[] { 218, 320, 507, 612, 651, 763, 952 } },     { "Mississippi", new int[] { 228, 601, 662 } },     { "Missouri", new int[] { 314, 417, 573, 636, 660, 816 } },     { "Montana", new int[] { 406 } },     { "Nebraska", new int[] { 308, 402 } },     { "Nevada", new int[] { 702, 775 } },     { "New Brunswick", new int[] { 506 } },     { "New Hampshire", new int[] { 603 } },     { "New Jersey", new int[] { 201, 609, 732, 856, 908, 973 } },     { "New Mexico", new int[] { 505 } },     { "New York", new int[] { 212, 315, 347, 516, 518, 607, 631, 646, 716,       718, 845, 914, 917 } },     { "Newfoundland", new int[] { 709 } },     { "North Carolina", new int[] { 252, 336, 704, 828, 910, 919, 980 } },     { "North Dakota", new int[] { 701 } },     { "Northwest Territories", new int[] { 867 } },     { "Nova Scotia", new int[] { 902 } },     { "Ohio", new int[] { 216, 234, 330, 419, 440, 513, 614, 740, 937 } },     { "Oklahoma", new int[] { 405, 580, 918 } },     { "Ontario", new int[] { 416, 519, 613, 647, 705, 807, 905 } },     { "Oregon", new int[] { 503, 541, 971 } },     { "Pennsylvania", new int[] { 215, 267, 412, 484, 570, 610, 717, 724, 814,       878, 902 } },     { "Puerto Rico", new int[] { 787 } },     { "Quebec", new int[] { 418, 450, 514, 819 } },     { "Rhode Island", new int[] { 401 } },     { "Saskatchewan", new int[] { 306 } },     { "South Carolina", new int[] { 803, 843, 864 } },     { "South Dakota", new int[] { 605 } },     { "Tennessee", new int[] { 423, 615, 865, 901, 931 } },     { "Texas", new int[] { 210, 214, 254, 281, 361, 409, 469, 512, 682, 713,       806, 817, 830, 832, 903, 915, 940, 956, 972 } },     { "US Virgin Islands", new int[] { 340 } },     { "Utah", new int[] { 435, 801 } },     { "Vermont", new int[] { 802 } },     { "Virginia", new int[] { 540, 571, 703, 757, 804 } },     { "Washington", new int[] { 206, 253, 360, 425, 509, 564 } },     { "West Virginia", new int[] { 304 } },     { "Wyoming", new int[] { 307 } },     { "Yukon Territory", new int[] { 867 } },   }; }

This servlet receives the WAP request as a normal HTTP GET request. In its doGet() method the servlet sets the content type to text/vnd.wap.wml, fetches the code parameter, locates the corresponding region via the lookup table, and finally generates a WML document containing the region. The area code information comes from a manually entered data array that's converted to a Properties table on servlet initialization. A screen shot of the output is shown in Figure 6-4.

Figure 6-4. Using WAP to locate callers

6.1.5 And That's a WAP

If you're interested in learning more about how to create sites catering to WAP devices, see Learning WML & WMLScript by Martin Frost (O'Reilly). There are also many good resource sites including http://www.wap-resources.net, http://www.AnywhereYouGo.com, and http://www.wirelessdevnet.com. There's even a Sun-hosted webjava-wireless mailing list with archives at http://archives.java.sun.com/archives/webjava-wireless.html.


Last updated on 3/20/2003
Java Servlet Programming, 2nd Edition, © 2001 O'Reilly

< BACKCONTINUE >


Java servlet programming
Java Servlet Programming (Java Series)
ISBN: 0596000405
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net