30 Minutes Flex Test-Drive for Java Developers

By Christophe Coenraets
Last update: September 6th, 2006

UPDATE (1/12/2007): I put together a Tomcat-based Test Drive Server that includes these samples running out-of-the box. Read this post for more info.

The objective of this test-drive is to give you, in a very short amount of time, an understanding of how Flex works and what it can do. This test-drive consists of a series of samples kept as concise as possible (typically between 10 and 50 lines of code) to clearly expose features of interest. The samples focus primarily on using Flex with a Java back-end. The intended audience is Java developers with no prior knowledge of Flex.

A few things to know before you start...

  1. The Flex programming model is made of:
  2. The Flex source code (.mxml and .as files) is compiled into Flash bytecode (.swf) that is executed at the client-side by the Flash virtual machine.
  3. There are different ways you can use the Flex compiler (mxmlc):

    You typically don't use the web compiler in a production environment. However, we are using it in this test-drive to minimize the number of components to install on your machine (all you will need to install is a war file).

  4. The Flex product line includes:

    You can develop and deploy Flex applications entirely for free using the SDK and the IDE of your choice. I will highlight the examples in this test-drive that require the Flex Data Services.

Installing the Test Drive Files

Since we will be using the Flex Data Services, you need a J2EE server, or, at a minimum, a Servlet container.

  1. Download the testdrive war file.

    Note: the only difference between the 5.5.x and 5.0.x version is the configuration of JOTM in META-INF\context.xml (the way you configure UserTransaction has changed in Tomcat 5.5).

  2. Deploy testdrive.war in your application server
  3. Access http://localhost:8080/testdrive (change the host name and port number as appropriate).

 

Sample 1: Accessing data using HTTPService

Run the sample:

  1. Access http://localhost:8080/testdrive/sample1/SampleXML.mxml

    Notice that there is a delay the first time you access an application in this test-drive. This is because we are using the web compiler which compiles your application into bytecode the first time it is accessed (similar to the JSP compilation model). Subsequent requests to the same application will be much faster since the application is already compiled. In a production environment, you would typically deploy precompiled applications.

    Note: Depending on your configuration, you may need to increase the heap size of your application server's JVM to use the web compiler. This would not be required in a production environement since you typically don't use the web compiler. If you get a java.lang.OutOfMemoryError exception while trying to access a sample for the first time, you must increase your heap size.

  2. Click "Get Data": The DataGrid is populated with XML data returned by catalog.jsp
  3. Also notice some of the built-in DataGrid features:

Code walkthrough:

Open the following files in a code editor:

Using HTTPService, you can send HTTP requests to a server, and consume the response. Although the HTTPService can be used to consume different types of responses, it is typically used to consume XML. You can use the HTTPService with any kind of server-side technology: JSP, Servlet, ASP, Ruby on Rails, PHP, etc. You specify the target service in the url property of HTTPService.

Flex provides sophisticated data binding capabilities. You can bind the value of a property to the value of another property, or to an expression in general. In this example, the dataProvider property of the DataGrid is bound (using the curly braces notation) to the lastResult property of the HTTPService.

HTTPService calls are asynchronous. The result event is triggered on the HTTPService when the data becomes available to the client application. The fault event is triggered if an error occurs at the server-side, or if the network becomes unavailable. (See sample 5, for an example of coding result and fault event handlers).

By default, the XML document retrieved from the server is deserialized into an object graph. This allows you to navigate through the result using the dot notation. You can also get the result as an XML document by specifying resultFormat="e4x" on the HTTPService. In that case, you can parse the document using E4X (ECMAScript for XML).

More info:


Sample 2: Accessing data using Web Services

Run the sample:

  1. Access http://localhost:8080/testdrive/sample2/SampleWebService.mxml
  2. Click "Get Data": The DataGrid is populated with data returned by the ProductWS web service hosted on my blog.

Code walkthrough:

Open the following file in a code editor:

Access the wsdl file for the web service used in this example:

Using the WebService tag, you can invoke SOAP-based web services deployed in your application server or on the internet. Objects returned by a web service are automatically deserialized into ActionScript objects. Similarly ActionScript objects passed as arguments to a web service operation are serialized according the wsdl description.

Notice that we also added DataGrid column definitions (using DataGridColumn) in this example.

More Info:


Sample 3: Accessing data using Java RPC

Run the sample:

  1. Access http://localhost:8080/testdrive/sample3/SamplePOJO.mxml
  2. Click "Get Data": The DataGrid is populated with data returned by the getProducts() method of the ProductService Java class.

Code walkthrough:

Open the following files in a code editor:

Using RemoteObject, you can directly invoke methods of Java objects deployed in your application server, and consume the return value. The return value can be a value of a primitive data type, an object, a collection of objects, an object graph, etc.

The value of the destination property of RemoteObject is a logical name that is mapped to a fully qualified java class in remoting-config.xml.

Java objects returned by server-side methods are deserialized into either dynamic or typed ActionScript objects. In this example, we don't have an explicit ActionScript version of the Product Java class. Product objects are therefore deserialized into dynamic objects. In sample 5, we work with an explicit Product class in ActionScript.

More info:


Sample 4: Flex Programming Model 101

Run the sample:

  1. Access http://localhost:8080/testdrive/sample4/MasterDetail.mxml
  2. Click a phone in the list: the details for the selected phone appear in the right panel

Code walkthrough:

Open the following files in a code editor:

Like in any other object-oriented programming language, a Flex application is made of a collection of classes. Using Flex, you can create classes using MXML or ActionScript. You typically create view classes in MXML, and Model and Controller classes in ActionScript.

When you create an mxml file, you are actually creating a class. The root node of the mxml document indicates the class you extend. For example, creating a file named MasterDetail.mxml with an <Application> root node is equivalent to creating an ActionScript class with the following signature:

public class MasterDetail extends Application {

}

Similarly, creating a file named ProductView.mxml with a <Panel> root node is similar to creating a class with the following signature:

public class ProductView extends Panel {

}

Once you have defined a class, you can use it programatically or declaratively (as a tag in MXML) without the need for an additional descriptor file. Public properties are automatically available as tag attributes. For example, in MasterDetail.mxml, we define the <ProductView> tag and bind its product attribute to the selected item in the product list.

Also notice the support for CSS style sheets.


Sample 5: Updating Data

Run the sample:

  1. Access http://localhost:8080/testdrive/sample5/SampleUpdate.mxml
  2. Select a phone
  3. Modify some data in the right panel. For example, the price.
  4. Click Update: changes are sent to the back-end and persisted in the database by the ProductService class.

Code walkthrough:

Open the following files in a code editor:

In Product.as we use the [RemoteClass(alias="flex.testdrive.store.Product")] annotation to map the ActionScript version of the Product class (Product.as) to the Java version (Product.java). As a result, Product objects returned by the getProducts() method of ProductService are deserialized into instances of the ActionScript Product class. Similarly, the instance of the ActionScript Product class passed as an argument to the update method of the RemoteObject is deserialized into an instance of the java version of the Product class at the server-side.


Sample 6: Publish/Subscribe Messaging (Data Push Use Case)

Run the sample:

In this example, a Java component publishes simulated real time values to a message queue. The Flex client subscribes to that queue and displays the values in real time.

  1. To start the feed component at the server-side: access http://localhost:8080/testdrive/sample6/startfeed.jsp.
    (You can stop the feed by accessing http://localhost:8080/testdrive/sample6/stopfeed.jsp)
  2. Open a browser and access http://localhost:8080/testdrive/sample6/FeedClient.mxml
  3. Click the "Subscribe to 'feed' destination" button: Pushed values appear in the text field

Code walkthrough:

Open the following files in a code editor:

Flex supports publish/subscribe messaging through the Flex Message Service (part of the Flex Data Services). The Flex Message Service manages a set of destinations that Flex clients can publish and subsribe to. Flex provides two components, Producer and Consumer, that you use to respectively publish and subscribe to a destination. To subscribe to a destination, you use the subscribe() method of the Consumer class. When a message is published to a destination you subscribed to, the message event is triggered on the Consumer.

In Feed.java, the Flex Java API (MessageBroker, AsyncMessage) is used to publish messages to the Flex destination. The Javadoc documentation for the Java API is available here. Another option to exchange messages bewteen Flex and Java applications is to map Flex destinations to JMS topics, essentially allowing a Flex client to publish and subscribe to JMS topics. In addition to JMS, the Flex Message Service adapter architecture allows you to integrate with any kind of messaging system.

Flex destinations are configured in messaging-config.xml. You can configure a destination to deliver the messages using a real-time protocol or using polling.

Additional resources:

Check out the portfolio viewer sample for a more complete example of data push.


Sample 7: Publish/Subscribe Messaging (Collaboration Use Case)

Run the sample:

  1. Open http://localhost:8080/testdrive/sample7/Chat.mxml in two different browser windows
  2. Type a message in one of the chat clients and click "Send": the message appears in the two chat clients

Code walkthrough:

Open the following files in a code editor:

This sample builds on the concepts and APIs introduced in the previous example. To publish a message from a client, you use the send() method of the Producer class.

The messaging and real time infrastructure available in Flex enables collaboration and data push applications to be built in a scalable and reliable manner while preserving the lightweight web deployment model.

Additional resources:

Check out the Google Map collaboration sample.


Sample 8: Data Management Services

Testing persistence:

  1. Open a browser and access http://localhost:8080/testdrive/sample8/SampleDataService.mxml
  2. Click a DataGrid cell, modify the data in that cell, and press Enter
  3. Click the Refresh button in your browser: Notice that the new value appears in the cell indicating that the data has been successfully persisted.

Testing data synchronization across clients:

  1. Open the same application in a second browser window
  2. Resize the two browser windows so that you can see both at the same time on your screen
  3. Modify data in one browser, and press Enter: notice that the update is automatically pushed to the other client

Code walkthrough:

Open the following files in a code editor:

In addition to the RPC services described in samples 1, 2, and 3, the Flex Data Management Services provide an innovative and highly productive approach to synchronize data across tiers and between clients. The Flex Data Management Services consist of a client-side API and server-side services:

At the client-side, "managed objects" keep track of changes made to the data, and notify the back-end of these changes. In SampleDataService.mxml, all you have to do is:

You don't have to keep track of changes made to the data, nor do you have to invoke remote services to notify the back-end of the changes (create, update, delete) made at the client side.

At the server-side, the Data Service receives the list of changes and passes it to your server-side persistence components. The Data Service also pushes the changes to other clients. In this example, the "product" DataService configured in data-management-config.xml uses the java-dao adapter, indicating that we will take care of the persistence code with our own Java classes (another option is to use the Hibernate adapter). There is no specific contract imposed on the Java class that provides the persistence implementation: You map methods such as fill and sync to actual methods in an assembler class (in this case: ProductAssembler). In the assembler class, you typically delegate the actual persistence implementation to existing persistence classes (in this case: ProductService).



Sample 9: Data Visualization

Run the sample :

  1. Access http://localhost:8080/testdrive/sample9/Dashboard.mxml
  2. Click on any data point on the line chart, the column chart at the bottom of the screen is updated to display a product breakdown for the selected month.

Code walkthrough:

Open the following files in a code editor:

Flex provides and extensive library of charting components such as LineChart and PieChart used in this example. Other charting components include ColumnChart, BarChart, AreaChart, BubbleChart, CandlestickChart, PlotChart, HLOCChart.

Flex charting components work like the other data aware components: you use the dataProvider property to bind a chart to data.

Because they leverage vector graphics, charting components can be redrawn and animated at the client-side, helping the end-user to better understand data trends and transitions.

Additional resources:


Sample 10: Rich Media

Run the sample:

  1. Access http://localhost:8080/testdrive/sample10/SampleMedia.mxml
  2. Click on a question in the list: a video appears, adding a rich media experience to this traditional "FAQ" application.

Code walkthrough:

Open the following files in a code editor:

HTTPService is used to retrieve an XML document that contains the list of questions, video links, and cuepoints.

The source attribute of the VideoDisplay component is bound to the selectedItem in the List, so that the "answer video" automatically starts palying when a question is clicked.

The cuepoint event is used on VideoDisplay to synchronize the captions (the captions are not part of the video, but where read from the XML document).

Also notice how the resizeEffect is used on the Panel component, to animate the panel when it is resized.

Finally the applications has two view states: the default state and the "videoPlaying" state. View states allow you to declaratively (using MXML) represent different states of the applications. In this simple case, the Panel is expanded in the videoPlaying state to reveal the VideoDisplay component.


Appendix A: Data Access and Rendering Performance

To test data retrieval and rendering:

  1. Access http://localhost:8080/testdrive/appendixa/Perf.mxml
  2. Specify a number of rows to retrieve
  3. Click "Get Data"
  4. Watch the number of milliseconds it took to retrieve and render the data

To test client-side sorting:

  1. Specify 20000 rows
  2. Click "Get Data"
  3. Click on a column header to sort 20000 rows at the client-side

Code walkthrough:

Open the following files in a code editor:

At the client-side, we use RemoteObject to remotely invoke the getItems method on the CensusService class deployed in the application server. The CensusService class accesses the embedded HSQLDB database and returns the number of rows requested. Using RemoteObject, the data is transferred in a binary format over HTTP.


Appendix B: Creating Custom UI Components

Run the sample:

  1. Access http://localhost:8080/testdrive/appendixb/Store.mxml
  2. Modify the price range using the slider: filtered items are animated in and out of the list to help the user visualize the products affected by the filter

Code walkthrough:

Open the following files in a code editor:

Although many Flex applications are built entirely using the UI components available in the Flex framework, you can create custom UI components by extending classes in the Flex framework. AnimatedTileList.as provides an example of a class that extends Canvas to provide an animated version of the TileList component.


Summary and Next Steps

This test-drive has provided you with a first experience of Flex, primarily focused on Java integration. However, we have just scratched the surface, and there are many other online resources focusing on the different aspects of the product. flex.org is a great place to start to become familiar with these resources. The developer experience is an important aspect of Flex. So also make sure you download FlexBuilder to start building your own Flex projects.

Don't hesitate to send me your questions/comments on this test-drive and any suggestion to improve it. Thanks! christophe at coenraets dot org.