Java Development News:
Breaking OpenLaszlo loose from XML data
By Geert Bevin
01 Mar 2007 | TheServerSide.com
OpenLaszlo is a development platform that allows you to create rich internet applications which execute on several runtimes, including Flash and DHTML. You use an XML-based language, called LZX, to declaratively create the user interface and rely on EcmaScript to implement dynamic portions of the application. This is very similar to the traditional HTML and JavaScript duo.
Receiving non-XML data
OpenLaszlo usually expects your data to be provided in XML and many of its features, like UI data-binding, rely on this. However, there are situations where you would like to work with other data formats. JSON, for example, is increasingly being used as the data-interchange format for Ajax applications. You might want to consume an existing JSON-based service in OpenLaszlo or write your own.
Since the 3.1 release of OpenLaszlo, it's possible to perform
data requests whose results aren't parsed as XML by using their XMLHttpRequest
class. Before being able to use the XMLHttpRequest class you
have to add the following include to the canvas of your OpenLaszlo
application:
<include href="rpc/ajax.lzx"/>
The class behaves exactly as in classic DHTML Ajax applications, for example:
function doXhrRequest() {
var url = "http:/yourservice"; // the single slash is mandatory in OpenLaszlo
var req = new XMLHttpRequest();
req.onreadystatechange = processRequestChange;
req.open("GET", url, true);
req.send(null);
}This creates a new instance of XMLHttpRequest,
registers the call-back function that will be executed as the request
progresses, opens the request for a particular URL and sends it to the
server.
The implementation of the call-back function is analogue to what you do in any other Ajax application:
function processRequestChange(request) {
// check if the data transfer is complete
if (4 == request.readyState) {
// process the reponse text if the request was successful
if (200 == request.status) {
var text = request.responseText;
// ... use the text ...
}
}
}It's up to you to handle the received text in the manner that is best suited for your application.
Working with JSON
The rest of this article will create a very simple JSON service in Java and an OpenLaszlo client that consumes and displays it asynchronously.
Producing JSON with JavaI'm staying away from
the server-side Java technology debate and assume that your framework of
choice is able to output text with the text/plain
mime-type.
The data that we'll be displaying is held by simple
Person bean:
public class Person {
private String name;
private int age;
public void setName(String name) { this.name = name; }
public String getName() { return name; }
public void setAge(int age) { this.age = age; }
public int getAge() { return age;}
}We will create a person instance and generate the JSON data for it. There are several Java libraries that are able to perform this task, but currently my choice goes to SOJO (Simplify Old Java Objects) because it's extremely simple to setup and use.
This is the code for the server-side JSON service in Java:
Person person = new Person();
person.setName("Geert Bevin");
person.setAge(32);
Object json = new JsonSerializer().serialize(person);
// output the json data as a string response
Parsing JSON in
OpenLaszlo
OpenLaszlo doesn't ship with JSON capabilities, but
luckily Oliver Steele wrote a library that does just this. You can obtain it
from his personal
website. Once downloaded and unzipped, you have to put the
json.js file in your web directory and activate JSON
capabilities by adding this tag to your OpenLaszlo canvas:
<script src="json.js"/>
Now
you can parse the text that you received from the
XMLHttpRequest with a simple function call and obtain an object
structure that corresponds to the JSON that was sent by the server. This is
done by adding the following line inside the
processRequestChange function that we created above:
var result = JSON.parse(text);
The
result variable is an associative array and you can obtain the
values of the person bean properties like this:
var person_name = result.name; var person_age = result.age;
Hooking this up to a GUI
To wrap this article up, we'll create a simple OpenLaszlo interface with a button that triggers the JSON service request when clicked and a couple of text fields that will display the received data.
Creating the controller and viewThis can be declared by using the following snippet of LZX
code inside your canvas tag:
<hbox inset="10">
<vbox id="mainArea" inset="10" spacing="10">
<button onclick="doXhrRequest()">Get data</button>
<hbox name="personName">
<text><b>Name:</b></text> <text name="value"/>
</hbox>
<hbox name="personAge">
<text><b>Age:</b></text> <text name="value"/>
</hbox>
</vbox>
</hbox>

You'll notice that when the button is clicked, the
doXhrRequest function, which we created at the beginning of
this article, is executed.
To display the received data in the text
fields, we simple have to change the text attributes of the correct view
elements after we parsed the JSON in the processRequestChange
function:
mainArea.personName.value.setAttribute("text", person_name);
mainArea.personAge.value.setAttribute("text", person_age);Handling
network latency graciouslySince the request will be executed
asynchronously, it can take a while for the data to arrive after clicking
the button, due to network latency. This can be frustrating for the user and
give the impression that the application is slow or unresponsive. A good
approach is to display a busy status indicator when the request doesn't
finish instantly. In this example I'm going to overlay a slightly
transparent glass pane that contains the message "Loading..."
when the data takes longer that 200 milliseconds to arrive. The following
LZX snippet creates the glass-pane:
<view name="loadingMessage" visible="false" bgcolor="#000000"
opacity="0.7" width="100%" height="100%">
<text align="center" valign="middle" fgcolor="#ffffff">Loading...</text>
</view>

By placing this code before the canvas closing tag, it
will float above any other GUI element. Note that the 'visible'
attribute has been set to false by default. We'll change that
value when we want the glass pane to display.
So, as soon as the
request starts, we initiate a timer that displays the glass-pane after 200
milliseconds. This can be done by relying on another value of the
readyState attribute of the XMLHttpRequest class.
You can refer to the class
documentation for a complete overview of the possible values. For our
use-case, we need to check if the attribute value is equal to
1, which means that the request has started. This additional
condition is added to the beginning of the processRequestChange
function:
// the request has been started
if (1 == request.readyState) {
// create the delegate if is doesn't exist yet
if ("undefined" == typeof(canvas.loadingMsgDel) ||
!canvas.loadingMsgDel) {
canvas.loadingMsgDel = new LzDelegate(canvas, "showLoadingMessage");
}
// intiate or reuse a timer
LzTimer.resetTimer(canvas.loadingMsgDel, 200);
}This code uses a delegate, which basically ties an event to a
method. The event in question is the expiration of the timer. Here, the
showLoadingMessage method will be called on the canvas instance
after 200 milliseconds. The implementation of this method is easy, as you
can see in the following snippet that should be added inside your
canvas tag:
<method name="showLoadingMessage">
this.loadingMessage.setAttribute("visible", true);
</method>It simply makes the loading message visible.
Finally, we need to hide this message again when the data
arrives or interrupt the timer if the request took less than 200
milliseconds. This is done by adding two lines to the initial condition
inside the processRequestChange function:
...
if (4 == request.readyState) {
// disable a pending loading message or hide it if it's showing already
LzTimer.removeTimer(canvas.loadingMsgDel);
canvas.loadingMessage.setAttribute("visible", false);
// process the reponse text if the request was successful
if (200 == request.status) {
...

Conclusion
It's easy to process arbitrary text with
the OpenLaszlo XMLHttpRequest class and even consume JSON
services. Currently this is still primitive since it doesn't tie into the
data-binding infrastructure. After the release of OpenLaszlo 4.0 (which
should happen in Q1 2007), the dataset infrastructure should be better
abstracted, creating a uniform approach to interacting with structured data.
Until then you're still able to explicitly update the view elements that you
need.
Resources
- The OpenLaszlo project website : http://www.openlaszlo.org
- The OpenLaszlo 4.0 architecture : http://www.openlaszlo.org/legals
- OpenLaszlo Software Engineer's Guide : http://www.openlaszlo.org/lps/docs/guide/
- JSON format : http://www.json.org
- SOJO Java library : http://sojo.sourceforge.net
- JSON for OpenLaszlo : http://osteele.com/sources/openlaszlo/json
- Source Files : Download Here