Multi-Tier Application Development with Adobe Flex

This excerpt describes the process of creating a complete Flex-Java distributed application. Upgrading Flex applications to Java Enterprise Edition applications is done with Flex Data Services. FDS provides transparent access to POJO, EJBs, and JMS and comes with adapters for frameworks like Spring and Hibernate.

These powerful capabilities come free for a single-CPU server, otherwise see your local Adobe dealer. Flex can also invoke any SOAP Web Service or send an HTTP request to any URL via Web Services and HTTPService components. Here we will illustrate Flex controls, HTTPService, RemoteObject, and Consumer via two versions of a stock portfolio application. The first version will show communications between Flash and a plain old Java object (POJO) using Flex remoting. We'll also explain how to use the HTTPService to read the RSS news feed. In the other version we'll add the stock (aka security) price feed using Flex Messaging and the Java Messaging Service (JMS). While explaining the FDS capabilities, we will also walk you through a typical design with Flex containers.

Designing a Stock Portfolio Application
Our goal is to create a Web application that will receive and display a feed containing security prices and the latest financial news as in Figures 1 and 2. This section contains a sort of functional specification of such an application.
We'll populate the top portion of the screen with the stocks included in the user's portfolio. For simplicity's sake, we'll store the user's portfolio in the XML file as in Listing 1.

When the user clicks on a row with a particular stock (i.e., ADBE as in Figure 1), it will populate the lower data grid with the headlines related to the selected stock. The news should be coming from http://finance.yahoo.com/rss/headline. The column Link will contain the URL of the news, and when the user clicks on the link, a new browser window pops up, displaying the selected news article.

The top of the screen contains the toggle buttons Show Grid/Show Chart. When the Show Grid option is selected, the user will see the screen as in Figure 1, and when Show Chart is selected, the top data grid will be replaced with the pie chart (see Figure 2), preserving the same functionality (clicking on the pie slice repopulates the news headlines according to the selected security). The market data is refreshed on the screen every second or so.

The first version of the application will query the server POJO that generates random numbers. Later in this excerpt, we'll subscribe to a JMS topic and consume a real-time data feed from an external Java application.

In this application we'll use the basic MXML and ActionScript from the first chapters of this book. We assume that the reader has a basic knowledge of Java syntax. We've included mini-references on the Java Naming and Directory Interface and JMS. So let's roll up our sleeves...

Adding a Data Grid
We'll start by adding the top grid displaying the stock portfolio. The Flex dataGrid component is a natural choice for data that can be presented as rows and columns. MXML is a great tool for modularizing development. The name of the new .mxml file automatically becomes the name of a new tag that can be reused in other files. For example, the code in Listing 2 assumes that there is an MXML file named PortfolioView1.mxml (in reality it can also be an ActionScript file named PortfolioView1.as or any other file that is assigned to this tag via the component library manifest).

In case of a default namespace (xmlns="*"), our PortfolioView1.mxml from Listing 3 will be co-located in the same directory with the application file portfolio.mxml.
Let's discuss the design of PortfolioView1. It contains DataGrid portfolioGrid in a Flex Panel with the title "Portfolio." XML from Listing 1 is loaded into the portfolioModel e4x object. The list of securities from that file is fed into portfolioGrid via a binding expression {portfolioModel.security}. This expression returns an XMLList of all nodes named "security" that are direct children of the root node (see Listing 3).

Even if we won't add any more code, isn't it impressive that it takes only a dozen lines of code to read the XML file, parse it, and display it in a grid shown in Figure 3? But this application has a static nature: it does not connect to any price quote feed. In other words, you would always see $33.38 as the price for Microsoft, and $82.15 for IBM.

In Listing 3, the curly braces surrounding the expression indicate that this expression is being used as a source in data binding. It is crucial for Flex programming to fully understand the strengths and weaknesses of binding. Binding is based on event listeners automatically generated by the Flex compiler as a response to declarative binding annotations. To initiate binding generation, developers use a combination of curly braces, mx:Binding tags, and [Bindable] metadata directives. (Refer to the Adobe Flex manual for more detail.)

Next, we need to periodically connect to the server for new prices and update the Price and Value columns. So let's use a special Flex component called RemoteObject:

<mx:RemoteObject id="freshQuotes" destination="Portfolio"...> .

The RemoteObject component allows calling methods of a specified remote POJO, which is configured on the server as a destination Portfolio in a special XML file. We'd like to emphasize that Flex transparently calls Java from ActionScript.
The client needs to know the name of the destination and the method to call, for example, getQuotes(). All the dirty work of data marshaling between ActionScript and Java is done for you by the Flex framework. If, for example, a Java method returns an object of the StockQuoteDTO.java type, Flex de-serializes the Java object and builds its ActionScript peer on the client. However, for performance reasons, it's recommended that you create the peer ActionScript class and register it with the framework. Please note that all RPC communications, including RemoteObject, are asynchronous. In other words, we don't exactly call a remote method, but rather send a message to the server, requesting a call of the specific Java method. Not only is the client's request(s) executed asynchronously, but even sending to the server is done asynchronously. If you need to do multiple RemoteObject invocations in your script, Flex will batch them together and send in the end of the script execution.

The results of remote invocations are returned via events. RemoteObject provides the result event for success or fault for failures. You should write the corresponding handler functions. Flex will call these methods, supplying an Event object as a parameter. It's your responsibility to get the information from the event and act accordingly. Friendly advice: you will save yourself hours of time if you supply a fault handler.

In the next code snippet we set concurrency to last, because if Flex decides to batch the outgoing requests, we do not want to send out more then one request in a batch; if a user clicks on the screen sending more than one request in quick succession, the last request will suppress all previous ones. Similarly, when the results are coming back, we are interested only in the one we sent last (see Listing 4).

The tag <mx:RemoteObject> allows using result and fault handling on both the object and method levels. The method settings will take precedence over the RemoteObject's ones. For server-side support, you have to download and install Flex Data Services 2 Express Edition (www.adobe.com/products/flex/), and deploy it as a Web application in the J2EE server of your choice, for example, in Tomcat. FDS comes with a set of XML files, which you will use to configure your server-side objects.

To register a POJO class with a Flex client we need to update the configuration file on the server side. This lets you hide details of the service provider (i.e., actual Java class names) by specifying so-called destinations where you specify access constraints, etc. The following section in Listing 5 has to be added to the remoting-config.xml file.

Clients won't know that the actual name of our POJO is com.theriabook.ro.Portfolio, but they'll be able to refer to it by the nickname Portfolio. Flex looks for classes specified in destination mappings on the Web Application classpath including JARs inside WEB-INF/lib and classes under WEB-INF/classes. The Java class Portfolio.java (see Listing 6) is a simple random number generator simulating market-like real-time price changes for several hard-coded securities.

The StockQuoteDTO.Java (see Listing 7) contains the last price of a particular stock. However, the client can really benefit from knowledge of the structure and the datatypes of the returned DTOs. Listing 8 shows the ActionScript's counterpart for the StockQuoteDTO.java object. While Flex does not need this definition in order to deserialize the Java object that includes member variables of standard types (by default it creates a dynamic object and adds the required properties of the Java object that's being deserialized), it does help performance (since the deserialized object is immediately allocated in memory), ensures the output datatypes, and enforces the type conversion.

The [RemoteClass...] metadata tag above the class definition tells the Flex de-serialization method to use this particular class for de-serialization whenever the server sends com.theriabook.jms.dto.StockQuoteDTO object down.

When the client successfully gets the quotes, it processes them and asks for new ones, as shown in Listing 9.

The E4X provides a very elegant solution for navigating an XML object here. The applyQuotes function iterates though the quotes from our portfolio and gets the XMLList based on the matching Symbol attribute via evaluation of the portfolioModel.security expression. (Symbol==quote.symbol.) This looks similar to XPath, but it's easier, isn't it?

Since there's a chance that the E4X expression above will return an empty XMLList, it's better to check for zero-length to avoid exceptions.

We are modifying the same XMLList that has been set as the data provider of our grid. In fact for data grids, Flex maintains an internal XMLListCollection with this XMLList as a source. When the program changes the data in the XMLList, these changes are automatically reflected on the screen. Error reporting is often done by calling Alert(), which brings up a pop-up window. But we suggest a less obtrusive way, whereby as an error condition disappears, the normal display restores without user interaction. Let's put a simple red Label control right above the data grid. Later we'll embed it in the Panel's title. An error, if any, will be displayed in this Label control, and to make it a bit fancier, the detailed error description will be displayed as a tooltip whenever the user moves the mouse over this field:

<mx:Label color="red" toolTip="{errorTip}" text="{errorText}" width="100%"/>

To implement this functionality, in the scripting section we will create two bindable variables:

[Bindable]
private var errorText:String;
[Bindable]
private var errorTip:String;

When an error occurs, the onFault function sets the values of the variables errorText and errorTip, and their bindable nature will immediately display these values in the <mx:Label>. But most important, we will attempt to recover by pulling the new quotes set. (see Listing 10). Do not forget to clean the errorText and errorTip variables in the function onResult, if the next attempt to pull the quotes will be successful.

Let's spend some time discussing the process of initiating the quote request. The function pullQuotes() gets initially invoked upon creation of the Panel:

<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" title="Portfolio" . . .
creationComplete="pullQuotes();">

To generate a remote call of some anonymous function every second, we'll use the setTimeout mechanism. The anonymous function initiates the call of the Java object proxied by the remoting destination freshQuotes:

private function pullQuotes():void{
setTimeout(function ():void {freshQuotes.getQuotes();},1000);
}

Listing 11 has the complete code of the first version of PortfolioView1.mxml, which contains just a data grid.

Adding the Charting Component
The population of the data grid is complete, and we are ready to work on adding a Flex charting component (see Figure 4).

Let's create a simple application that adds the pie chart below the data grid and gives the grid and the chart 50% of the screen height each:

<?xml version="1.0" encoding="utf-8"?>
<!--portfolio2.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" >
<PortfolioView2 id="pv"/>
</mx:Application>

The fragment of the PortfolioView2.mxml is shown in Listing 12.

Flex Panel containers have a layout property (horizontal, vertical, and absolute). Since the vertical layout is the default, our chart is positioned right under the grid. Please note that chart's dataProvider is based on the same XMLList portfolioModel.security as is the dataProvider of the portfolioGrid. In other words, we have two views of the same data model. The data binding feature results in immediate updates of both controls on each change of the model. Java Swing developers will appreciate the benefits of this feature as opposed to the JavaBean and property listeners hassle (see Listing 13).

For the pie chart, we've selected a callout type of label positioning, specified so the size of the pie is proportional to the attribute Value, and we've added a 3D depth to the chart by setting explode Radius to 0.02. Note how we've assigned the function name showPosition to the labelFunction attribute of the pie chart. The signature of the labelFunction assumes that the first argument brings the element of the dataProvider corresponding to the current wedge in the series.

Chart/DataGrid Toggling
Imagine a deck of playing cards: only the top card is visible. Hide the top card and you'll see the next one. We'll use the deck of two "cards": one card will display the grid, and another one - the chart. To Java Swing developers this should look like the CardLayout. In Flex jargon it's called <mx:ViewStack>. A fragment of PortfolioView3.mxml introduces MXML components <mx:ViewStack>, <mx:ToggleButtonBar>, and <mx:Canvas> (see Listing 14).

The most suitable Flex containers for toggling the views are ViewStack or its direct descendant TabNavigator. (See Figure 5) The latter uses more screen real estate to paint the tabs. So we'd rather put the view toggling controls on the unused area of the Panel's title bar. The ViewStack component provides programmatic indexed access to the child containers and shows them one at a time. The simplest Flex container is called Canvas, so we wrap up the DataGrid and the PieChart separately inside it. A Canvas is a descendant of the Container ActionScript class and has the properties label and icon. There are two "non-programmatic" ways to use these properties. First, certain containers use them implicitly, for instance, TabNavigator automatically arranges its tabs to display labels and show icons from the nested child containers. The second way is to explicitly use the ViewStack as a data provider for the descendants of the NavBar control such as ButtonBar, LinkBar, and, in our case, ToggleButtonBar. When you use a ViewStack as a data provider, the label and icon properties of the ViewStack container's children are used to populate the navigation items. The ViewStack feeds ToggleButtonbar and ToggleButtonbar controls the ViewStack in return (see Listing 15).

The toggle buttons Show Grid/Show Chart use images, and it's a good idea to embed these resources right into the SWF file. This way the browser can download the entire client in one HTTP request (but the size of the SWF file becomes larger). For the same reason, the multi-file Java applets are packaged into a single JAR.

In Listing 15, we use canvases to wrap, but now we're going wrap up the entire Portfolio Panel. Yes, the Panel will become a child of the Canvas. Here is why we need it. The Canvas is the simplest container, and it's also the absolute positioning container. In other words, if you place A and B as children of the Canvas, they overlap unless each of them has specific x and y coordinate settings. So we're planning on overlapping the ToggleButtonBar and the PortfolioPanel in a single Canvas. As an additional measure, to make the ToggleButtonBar appear on the far right, we put the ToggleButtonBar inside the HBox container. Make sure that the RemoteObject and the XML are moved out to become children of the Canvas; they have to be at the outermost level - this is an MXML requirement (see Listing 16).

Dealing with Financial News
Let's set up the scene for the financial news first, and then we'll add them to the screen that we've developed so far. The data you see here are provided by an RSS feed. RSS stands for Real Simple Syndication and is used for presenting such data as news, blogs, or other Web content in a form of XML that contains summaries of the articles as well as links to the full version of the content. We use it simply to illustrate the client/server communication via the Flex component called <mx:HTTPService>, which facilitates HTTP POST and GET requests from the Flash player to a remote URL with automatic embedding of the parameters. In particular, we'll be using the RSS news generator offered by Yahoo! Finance. Just enter the following URL in your browser: http://biz.yahoo.com/rss.html.
You should see a screen similar to the one depicted in Figure 6. This Web site lets you enter a stock symbol, for example, ADBE.

You'll see a little orange XML button, with a new URL that looks like http://finance.yahoo.com/rss/headline?s=adbe. Just follow this link, which will bring you to the RSS XML feed with the latest news about the symbol ADBE.

In Part 2 of this excerpt we'll be done with programming master-detail relationships; our users will click on the row in the portfolio grid and see the news, then click on one of the lines in the column Link, which opens a new Web browser's window with the full news content.

•   •   •

•   •   •

 

This article is an excerpt from Chapter 5 of Rich Internet Applications with Adobe Flex & Java by Yakov Fain, Dr. Victor Rasputnis, and Anatole Tartakovsky, published by SYS-CON Books/2007.

© 2008 SYS-CON Media