BT

Flex for XML and JSON

Posted by Jack Herrington on Oct 12, 2008 |

 

Beauty and brains. Flex and Java. Or is it the other way around? Who can say? What I know is that Flex and Java work really well together to create amazing Rich Internet applications (RIAs). What is Flex you ask? Flex is an open source framework that you can use to build Flash applications using the tags-based MXML language (along with ActionScript 3).

Watch: Flex for XML and JSON screen cast presented by Jack (Quicktime MOV, 33MB)

You can get started by downloading the Flex IDE, called Flex Builder, from the Adobe site (http://adobe.com/flex). Flex Builder is a commercial product, but it has a long free trial period that will give you enough time to figure out if it's worth your money. In this article, I'm going to demonstrate how to use Flex and Java together. Java will run the server. Flex will run on the client. The protocol between the two can really be anything you want. But in this case I'll use XML first, then use Javascript Object Notation (JSON), since both of those are the standards we are seeing the most in this Web 2.0 world.

Building the Server Piece

The XML example starts with the simple JSP file shown in Listing 1.

  Listing 1. xml.jsp
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">
<jsp:directive.page import="java.text.*"/>
<jsp:directive.page import="java.lang.*"/>
<jsp:directive.page contentType="text/xml"/>
<days><jsp:scriptlet>
<![CDATA[
double compa = 1000.0;
double compb = 900.0;
for (int i = 0; i<=30; i++) {
compa += ( Math.random() * 100 ) - 50;
compb += ( Math.random() * 100 ) - 50;
]]>
</jsp:scriptlet>
<day>
<num><jsp:expression>i</jsp:expression></num>
<compa><jsp:expression>compa</jsp:expression></compa>
<compb><jsp:expression>compb</jsp:expression></compb>
</day>
<jsp:scriptlet>
<![CDATA[ }
]]>
</jsp:scriptlet>
</days>
</jsp:root>

This service exports some random stock data for two companies (compa and compb) for thirty days. The first company's value starts at $1000, the second at $900, and the JSP code applies a random factor each day to the values.

When I use the 'curl' client from my command line to access the service I get back something like what's shown below:

 % curl "http://localhost:8080/jsp-examples/flexds/xml.jsp"
<days><day><num>0</num><compa>966.429108587301</compa>
<compb>920.7133933216961</compb>
</day>...</days>

The root tag is the <days> tag which includes a set of <day> tags. Each of these <day> tags has a <num> tag for the day number, a <compa> value for the stock price of company A, and a <compb> tag with the stock price from company B. The values of the two stock prices change with each request as they are randomly generated.

Building the Interface

Now that we have a web service that outputs stock prices, we need a client application to view it. The first one we will build is a grid style interface that simply shows the numbers. To create the Flex project, we select Flex Project from the New menu in the Flex Builder IDE. This is shown in Figure 1.

Figure -1. The ew Flex Project dialog

From here all we need to do is give the project a name. I'll call it xmldg for 'XML Data Grid.' This will create an xmldg.mxml file that has an tag in it. We will replace this simple do-nothing application with the code in Listing 2, which does a whole lot.

Listing 2. xmldg.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"> <mx:XML source="http://localhost:8080/jsp-examples/flexds/xml.jsp" id="stockData" /> <mx:Panel title="Stock Data" width="100%" height="100%"> <mx:DataGrid dataProvider="{stockData..day}" width="100%" height="100%"> <mx:columns>
<mx:DataGridColumn
dataField="compa" /> <mx:DataGridColumn dataField="compb" /> </mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>

This xmldg application code has two primary components. The first is the <mx:XML> tag which tells Flex that there is an XML data source out there and gives it the URL. This will create a local variable called stockData (specified by the id attribute) which the <mx:DataGrid> component can use as a dataProvider.

The rest of the code is just interface. There is an <mx:Panel> object that gives a nice little wrapper around the grid. Then the <mx:DataGrid> object that shows the data. Within the <mx:DataGrid> is a set of <mx:DataGridColumn> specification objects which tells the grid what data to show.

When we launch this from Flex Builder we should see something like what is shown in Figure 2.

Figure -2. The xmldg application in action

From here we can scroll the list, resize the window, and watch the data grid change size.

To add a little filtering capability, we will update the code with an <mx:HSlider> control, a horizontal slider, which will specify on which day the grid should start the data display.

For example, if we set the slider to 6 it will only show data from day 6 onward. The code for this is shown in Listing 3.

Listing 3. xmldg2.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:XML source="http://localhost:8080/jsp-examples/flexds/xml.jsp" id="stockData" />
<mx:Panel title="Stock Data" width="100%" height="100%" layout="vertical"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10">
<mx:HBox>
<mx:Label text=
"Start Day" />
<mx:HSlider minimum="0" maximum="30" id="dayslider" snapInterval="1" />
</mx:HBox>


<mx:DataGrid dataProvider="{stockData..day.(num >= daySlider.value )}"
width="100%" height="100%"> <mx:columns>
<mx:DataGridColumn
dataField="num" headerText="day" /> <mx:DataGridColumn dataField=="compa" headerText="Company A" /> <mx:DataGridColumn dataField=="compb" headerText="Company B" /> </mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>

There are a few more tags, but the story remains much the same. There is an <mx:Panel> tag that contains everything. Within that is an <mx:HBox> (horizontal box) tag that includes an <mx:Label> and the <mx:HSlider> control. The slider is used in the dataProvider field of the <mx:DataGrid>.

Let's have a closer look at the dataProvider attribute:

{stockData..day.(num >= daySlider.value )}

This is using ActionScript's E4X syntax to pare down the data set to the <mx:DataGrid>control to only those tags where the <num> value in the data is greater than or equal to the slider value. Flex is smart enough to watch for the change events that come from the slider to automatically update the data grid for us.

When we bring this up from Flex Builder it looks like what is shown in Figure 3.

Figure -3. The filterable grid

From here we can adjust the slider and see how that affects the data in the grid. Figure 4 shows what happens when I set the slider to 12.

Figure -4. The slider set to 12 on the data grid

This is just a simple example of what can be done using E4X in ActionScript. The E4X syntax makes dealing with XML so easy to do that you'll never want to deal with XML any other way.

Graphing

Data grids are a bit boring, at least to me. I'm a visual guy. So let's put a graph on this thing. To do that, we create a new project called xmlgph(for XML graph) and replace the xmlgph.mxml file that is created with the code in Listing 4.

 Listing 4. xmlgph.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:XML source="http://localhost:8080/jsp-examples/flexds/xml.jsp" id="stockData" />
<mx:Panel title="Stock Data" width="100%" height="100%" layout="vertical"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10">

<mx:HBox>
<mx:Label
text="Start Day" />
<mx:HSlider? minimum="0" maximum="30" id="dayslider" snapInterval="1" />
</mx:HBox>

<mx:LineChart id="chart" dataProvider="{stockData..day.(num >= daySlider.value )}"
width="100%" height="100%">
<mx:series>
<mx:LineSeries xField="num" yField="compa" displayName="Company A" />
<mx:LineSeries xField="num" yField="compb" displayName="Company B" />
</mx:series>
</mx:LineChart>
<mx:Legend dataProvider="{chart}" />
</mx:Panel>
</mx:Application>

This code is exactly like xmldg2, but the <mx:DataGrid> control has been replaced by an <mx:LineChart> control that will display a chart of the values instead of a grid. There is also an <mx:Legend> control that will display the names of the company associated with each color of line. The two <mx:LineSeries> objects are the charting equivalent of the <mx:DataGridColumn> objects. These let the line chart know what data to display on which axis.

When we launch this from Flex Builder we should see something like what is shown Figure 5.

Figure -5. The Line Chart example

Not bad, huh? And because the <x:HSlider> control is still around, we can change the starting day of the graph just by moving the slider.

In fact, with a few small changes we can allow for the graph to show a 'window' of days by providing users with two thumbs in the slider that they can move independently. The code for this is shown in Listing 5.

 Listing 5. xmlgph2.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:XML source="http://localhost:8080/jsp-examples/flexds/xml.jsp" id="stockData " />
<mx:Panel title="Stock Data " width="100% " height="100% " layout="vertical "
paddingBottom="10 " paddingLeft="10 " paddingRight="10 " paddingTop="10 ">

<mx:HBox>
<mx:Label
text="Date Range " />
<mx:HSlider minimum="0 " maximum="30 " id="daySlider " snapInterval="1 "
thumbCount="2 " values="[0,30] " />
</mx:HBox>

<mx:LineChart id="chart"
dataProvider="{stockData..day.(num>=daySlider.values[0] &&
num<=daySlider.values[1])}
"
width="100%" height="100%">
<mx:series>
<mx:LineSeries
xField="num" yField="compa" displayName="Company A" />
<mx:LineSeries xField="num" yField="compb" displayName="Company B" />
</mx:series>
</mx:LineChart>
<mx:Legend
dataProvider="{chart}" />
</mx:Panel>
</mx:Application>

All we have done is add the thumbCount and values attributes to the <mx:HSlider> tag, and updated the dataProvider in the <mx:DataGrid> tag. Because this is XML, I had to encode some of the entities in the dataProvider. When we run this from Flex Builder we see something like Figure 6.

Figure -6. The windowed line chart

That about does it for the XML portion of the demonstration. From here I'll show you how to build a Flex application that consumes JSON services.

Building the JSON Server

Creating the JSON reading application starts with creating a JSON data source. Once again, we'll fall back on trusty JSP to build the JSON encoded data stream. The JSP code for the server is shown in Listing 6.

 Listing 6. json.jsp
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">
<jsp:directive.page import="java.text.*"/>
<jsp:directive.page import="java.lang.*"/>
<jsp:directive.page contentType="text/json"/>
[<jsp:scriptlet>
<![CDATA[
double compa = 1000.0;
double compb = 900.0;
for (int i = 0; i<=30; i++) {
compa += ( Math.random() * 100 ) - 50;
compb += ( Math.random() * 100 ) - 50;
if ( i > 0 ) out.print( "," );
]]> </jsp:scriptlet>{"compa":<jsp:expression>compa</jsp:expression>,"compb":<jsp:expres
sion>compb</jsp:expression>}<jsp:scriptlet>
<![CDATA[ }
]]>
</jsp:scriptlet>]
</jsp:root>

This is exactly like the XML service, but instead of creating XML tags we create JSON encoded data.

When I run the 'curl' utility from the command line to get the page it looks like:

 % curl "http://localhost:8080/jsp-examples/flexds/json.jsp"
[{"compa":992.2139849199265,"compb":939.89135379532}, ...]

That's just the kind of thing that a Javascript client would love to see.

Consuming JSON Services

Flex is written in ActionScript 3, the programming language of the Flash player. It's similar to Javascript, but it lacks the eval function. So how do we turn JSON text into ActionScript data? Thankfully, the free ActionScript 3 core library (http://as3corelib.googlecode.com) comes with both a JSON decoder and a JSON encoder installed.

The code in Listing 7 shows the JSONDecoder object in action.

 Listing 7. jsondg.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
creationComplete="jsonservice.send()">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import com.adobe.serialization.json.JSONDecoder;

private function onJSONResult( event:ResultEvent ) : void {
var data:String = event.result.toString();
data = data.replace( /\s/g, '' );
var jd:JSONDecoder = new JSONDecoder( data );
dg.dataProvider = jd.getValue();
}
]]>
</mx:Script>
<mx:HTTPService id="jsonservice"
url="http://localhost:8080/jsp-examples/flexds/json.jsp"
resultFormat="text" result="onJSONResult(event)" />
<mx:Panel title="Stock Data " width="100% " height="100% ">
<mx:DataGrid id="dg" width="100%" height="100%">
<mx:columns>
<mx:DataGridColumn
dataField="compa " />
<mx:DataGridColumn dataField=
"compb " /> </mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:Application>

Because the server is returning JSON as text, we can't use the <mx:XML> tag to get the data. So we use the <mx:HTTPService>> tag instead. It works a lot like the <mx:XML> tag. You give it a URL of the service, and then tell it the result format (i.e. text) and the ActionScript function to call when the HTTP service replies with the data.

In this case, I set the result function to the onJSONResult code that I specify in the <mx:Script> tag. This method takes out any whitespace and passes the JSON text onto the JSONDecoder object. It then sets the dataProvider on the <mx:DataGrid> control to the value returned from the JSONDecoder.

All of this is completely secure because ActionScript has no eval function. The JSONDecoder class is a simple state machine parser that builds objects from the text on the fly. In the worst case, it might just take a long time if the JSON text is too large.

Where to Go from Here

Flex is based on Flash, and Flash can talk to just about anything. It can talk directly to SOAP-based web services. It can even talk binary with protocols such as the Adobe Message Format (AMF).

If this is your first time using Flex, you might want to look into using Flex to build a Flash widget that you can post on your site to present data in a visually attractive way. To make sure that the Flash application is small enough to make for a fast download, be sure to make use of the Runtime Shared Library (RSL) functionality in the new Flash player. This allows you to cache big libraries (like the Flex library) in the client and then reuse them between different Flash applications.

Flex and Java are a strong team. Java provides excellent backend support on the server. And Flex along with ActionScript 3, provide a common cross-platform GUI layer that is easy to write and easy to adopt.

Hello stranger!

You need to Register an InfoQ account or to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

typos by Matt Dorn

3 typos in Listing 3 cause errors:

* Line 9: "dayslider" should be "daySlider"
* Lines 15-16: "==" should be "="

Re: typos by Peter Gustafsson

Another one in listing 7.

<mx:DataGridColumn dataField="compa " />
<mx:DataGridColumn dataField="compb " />

remove trailing white-space

<mx:DataGridColumn dataField="compa" />
<mx:DataGridColumn dataField="compb" />

thanks for a very helpful article.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

2 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2013 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT