WebDevelopersJournal.comTips on Web Page Design, HTML and Graphics
SITE SEARCH
Newsletters
Java/Open Source Daily



Jobs at webdeveloper.com

Resources By Subject
Technical
Graphical
Authoring
Business
WDJ resources
Archive

internet.com

internet.commerce
  • Partner With Us
















Developer Channel


Find a web host with:
CGI Access DB Support Telnet Access
NT Servers UNIX Servers



Semi-automatic?

JavaScript
JavaScript Helper:
Meet Paige Turner, the least geeky geek we've ever come across.

Variables and Operators Explained:
First of a three part guide to JavaScript basics.

Controlling Forms:
Enhance your HTML forms with a touch of JS.

DHTML:
Forget how it works, let's see some in action!


Serving Dynamic WAP Content with Java Server Pages

by by Mark Webber

WAP With Bells And Whistles

In this article I will show you how easy it is to start creating dynamic content for WAP-enabled mobile phones using the Wireless Markup Language (WML) and Sun Microsystems' Java Server API. Rather than list and explain all of the WML tags we will examine a sample application that will demonstrate some of the main language features.
May 5, 2000

Our sample Java Server Pages application displays regularly updated appointment data for someone on the move, such as an appliance engineer making house calls. This application was created on Windows NT using the Java Server Web Development Kit (JSWDK) 1.01. I used the servletrunner utility that comes with the JSWDK to serve the JSP pages from my own desktop machine.

In order to test and view the application I used the Nokia WAP Toolkit 1.2. This is a nice Java SWING application that requires the Java Runtime Environment (JRE) 1.2.2 to be installed on your computer before it will run. It consists of a browser that displays the WAP content on a simulation of a mobile phone.

The normal way to serve WAP content is to have a WAP gateway server sitting between the mobile phone network and a standard web server. One reason for this is that WML is compiled or "tokenized" to conserve bandwidth. But the Nokia WAP Toolkit contains its own WML compiler and so it can talk directly to an HTTP server (in our case the servletrunner utility).

The WAP toolkit is available from the Nokia WAP Developer Forum at http://forum.nokia.com. Although it is free, you will have to register before you can download it.

A Brief Introdution to WML

The most important thing to remember about WML is that, since it is an XML-defined language, it is "well-formed". This means that, unlike HTML, all tags must be closed and cannot be incorrectly nested, and all attribute values must be enclosed in quotation marks.

WML is also DTD-validated, which means that any WML content is checked against the WML Document Type Definition before it is displayed. So tags must have exactly the attributes specified in the DTD and cannot be nested inside a another tag unless permitted by the DTD. Unlike normal web browsers, you'll find that the Nokia simulator is extremely fussy and will refuse to display any page that contains the slightest violation.

Although WML bears a superficial resemblance to HTML, don't be fooled, because there are significant differences. The key metaphor in WML is that of a deck of cards. The deck is the smallest unit that is downloaded to the device and consists of one or more cards which normally equate to one display "screen". The deck is contained within the <wml> and </wml> tags.

When a deck is first loaded, the first card in the code is shown (unless you are navigating to a specific card within the deck). Each <card> has an "id" attribute that is used for referencing it in hyperlinks and a "title" attribute that is typically displayed at the top of the screen. All visible content in a card must be enclosed in a <p> element.

The text formatting tags are the same as their HTML counterparts: <b>, <big>, <em>, <i>, <small>, <strong> and <u>. You can also build tables in WML with the familiar <table>, <tr>, and <td> tags, but the <table> tag requires a "columns" attribute. It is important to remember that current WAP devices may not support all of the formatting elements, and there may be considerable variations in the way that they are displayed.

With WML it is possible to declare variables that can be substituted into display text, and which can be used to preserve state between decks. Variables are set with the <setvar> element which has the name and value attributes. To substitute the current value of the variable into text, prefix the variable name with $, as in Perl. As a consequnce of this, the dollar sign must itself be escaped as $$ if you wish to display it in normal text.

WML uses the # sign to indicate a hyperlink to a card within a deck, in the same way that anchors within an HTML page are referenced. For example, the URL "/my_deck.jsp#card_two" will display the card with the id attribute value of "card_two" in the deck served up by "my_deck.jsp", whereas the URL "#card_two" references the card with that id in the current deck.

The Constraints of WAP Development

When building WAP applications you must bear a number of points in mind. WAP devices have a small display area - typically four lines of twelve characters, and having to scroll too much can be annoying. The data entry capabilities may be limited and awkward. The device will probably have limited RAM and CPU power. And the current wireless networks have low bandwidth and are slow and unreliable with high latency. Coupled with the lack of control the programmer has over the way that widgets are displayed, it becomes clear that WAP applications should be lightweight and simple.

The Application

Our sample application consists of two decks. The first is served up by pick_appointment.jsp and has one card which displays a <select> widget of appointment times. When an <option> is selected the user is forwarded to the second deck, show_appointment_data.jsp, which is passed the appointment ID as a parameter. This second deck has two cards. The first displays the appointment data and the second contains a data entry widget that allows the engineer to check off the appointment by entering a completion code.

The dynamic appointment data is fetched from a Java Bean instance, the source code of which is not shown, but which might use JDBC to connect to a database of appointments. The check-off code is processed by a servlet, the source code of which is also not shown. Since the appointments may change throughout the day as customers phone in to cancel we will refresh the pick_appointment.jsp page every minute in case the engineer leaves his phone pointing at that page.

pick_appointment.jsp

Please note that there are artificial line breaks in the code that follows - created by the layout of this Web page. You can check the correct line breaks by looking at the page source code.


<%@ page language="java" contentType="text/vnd.wap.wml" %>

<jsp:useBean id="appointmentBean" class="mwebber.samples.AppointmentBean"
scope="application" />

<%!
// This convenience method builds our <option> elements, one for each appointment.
private String getOptions(mwebber.samples.AppointmentBean appointmentBean) {
StringBuffer sb = new StringBuffer();
int[] appointmentIDs = appointmentBean.getAppointmentIDs();
for(int i=0; i<appointmentIDs.length; i++) {
sb.append("<option onpick=\"show_appointment_data.jsp?id=");
sb.append(i);
sb.append("\">");
sb.append(appointmentBean.getAppointmentTime(i));
sb.append("</option>");
}
return sb.toString();
}
%>

<%! String strXMLPrologue = "<?xml version=\"1.0\"?>"; %>

<%-- WML CONTENT BEGINS --%>
<%= strXMLPrologue %>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card id="pick" title="Appointments">
<!-- Refresh the deck every minute -->
<onevent type="ontimer">
<go href="pick_appointment.jsp"/>
</onevent>

<timer value="100%"/>

<!-- Display a widget to navigate back by one in the history stack -->
<do type="prev">
<prev/>
</do>

<!-- Display the "select" widget of appointments to pick -->
<p>
<select title="Appointments">
<%= getOptions(appointmentBean) %>
</select>
</p>
</card>
</wml>

<%-- WML CONTENT ENDS --%>


show_appointment_data.jsp


<%@ page language="java" contentType="text/vnd.wap.wml" %>

<jsp:useBean id="appointmentBean" class="mwebber.samples.AppointmentBean"
scope="application" />

<%
// Grab the "id" parameter, using the in-built reference to the request object.
int intAppointmentID = Integer.parseInt(request.getParameter("id"));
%>

<%! String strXMLPrologue = "<?xml version=\"1.0\"?>"; %>

<%-- WML CONTENT BEGINS --%>
<%= strXMLPrologue %>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card id="main_data" title="Main Data">
<p align="center">
<b>
<%= appointmentBean.getAppointmentTime(intAppointmentID) %>
</b>
</p>
<p>
<br/>
<%= appointmentBean.getAppointmentDetails(intAppointmentID) %>
<br/>
<a href="#check_off">Check off this appointment</a><br/>
<a href="http://localhost:8080/pick_appointment.jsp">Back to appointments list</a>
</p>
</card>

<card id="check_off" title="Check Off">
<!-- Set up a widget to send the input field data to the server -->
<do type="accept">
<go href="/servlet/ProcessCheckOff" method="post">
<postfield name="check_off_code" value="$check_off_code"/>
</go>
</do>

<p>
<input name="check_off_code" emptyok="false" maxlength="6"/>
</p>
<p>
<a href="#main_data">Back to appointment data</a>
<br/>
<a href="http://localhost:8080/pick_appointment.jsp">Back to appointments list</a>
</p>
</card>

</wml>
<%-- WML CONTENT ENDS --%>


At the very top of each file we set the correct MIME type. The deck will be rejected by the simulator if this is not right. In our case, text/vnd.wap.wml indicates WML source code. Other types include text/vnd.wap.wmlscript for WMLScript source code, and image/vnd.wap.wbmp for Wireless Bitmap images.

Since a WML deck is really an XML document it contains the standard XML prologue and a pointer to the DTD. However, the <? and ?> markers of the prologue appear to confuse the JSP parser and so we hide this prologue in a String variable (don't forget that a JSP page is parsed into a Java source file which is then compiled into a servlet). You should also be aware of this problem if you use other "server page" languages such as PHP and ASP. Note that the <br/> tag is closed - this is standard XML. And as you can see, comment markers are the same as in HTML.

WML has support for basic event generation and handling. To understand the mechanism, you'll need to think in terms of "tasks" which are bound to "events". A task, unsuprisingly, is something that is done. There are four types of task, <noop>, <refresh>, <prev> and <go>. Our sample application uses the latter two. The <prev> task navigates to the previous card in the device's history stack, which each WAP device is required to maintain. The <go> task navigates to a URL. It may be used as a simple hyperlink, as in our first deck which uses it in conjunction with a timer event, or to send form data to the server, as in our second deck which uses it in conjunction with an accept event.

For the second use there is the <postfield> element which defines the name-value pairs to be passed to the processing script. Note that the "value" attribute is set to the "check_off_code" variable, which the device automatically sets to the value that the user entered in the input field.

An event, when fired, processes the task that is bound to it. Tasks may be bound with one of three event tags: <anchor>, <onevent>, and <do>. Our application uses the latter two. The <onevent> tag handles what are known as Intrinsic Events. These are events that are triggered internally by the device. There are four types of Intrinsic Event, specified with the type attribute: oneventforward, oneventbackward, ontimer, and onpick. The first two are fired when the user navigates to a card, and the onpick event occurres when the user selects or deselects an <option> item of a <select> widget.

Our application uses a timer to reload the deck every minute. The value attribute of the <timer> tag is the interval in tenths of a second. You can see that we have associated a <go> task with the timer event in order to reload the deck.

Besides Intrinsic Events there are seven User-Triggered Events. These are specified with the <do> element which assigns a task to a hardware key or on-screen widget (this is device-dependent). These Intrinsic Events are accept, prev, help, reset, options, delete, and unknown.

On the Nokia simulator our "prev" event is fired by a selecting a special "Back" option that appears below the main screen, accessed by the right control button on the handset. Setting the label attribute of the <do> element has no effect with this device. The display widgets for the "accept" event in our second deck are rather convoluted, and involve taking us through an Options menu to a dedicated data entry screen.

The <input> element specifies a text entry object. Among the attributes of the <input> element are the following.

emptyok - this specifies whether or not the user must enter a value in the field.
format - this takes a string that is an input mask, which is a very useful and time-saving feature.
name - the name of the variable that is set to the value of the input text.
title - a label that may be used by the device when displaying the element.

There is considerably more to the WML language than we have had space to cover here, but I hope that this article has covered enough of the basics to allow you to begin developing WAP applications of your own.


The full WML specification can be downloaded from the WAP Forum: http://www.wapforum.org.

An excellent WML and WMLScript tutorial is Programming Applications with the Wireless Application Protocol by Steve Mann (John Wiley & Sons, 2000).



Mark Webber is a Web Developer with Demon Internet, a brand of Thus plc. He is a Sun Certified Java Programmer.
Suits PonytailsPropheadsContact WDJDiscussWeb AudioSearch


The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers