The sample Flex application for this article will display a DataGrid control containing a few employees, with the option to browse for and upload a photo for each person. The Flex application sends to the Java servlet a POST request, which includes not just the image file but also the employee ID. The servlet uses the employee ID as the filename, deletes any previous pictures for that employee, writes the image to disk, and responds to Flex with an XML document. In turn, Flex displays the newly uploaded image along with the server’s response.
To start, create a new project in Flex Builder named FileUpload. Begin by adding a few components: a VBox, a Form, and a DataGrid. The Form will display the server response while the DataGrid will list each employee’s name, ID, department, location, and photo.
Give the components these properties:
<mx:VBox width="750"> <mx:Form width="720" borderColor="white" borderStyle="solid" > <mx:FormHeading label="Flex Upload"/> <mx:FormItem direction="horizontal" width="100%" label="Server Response:"> <mx:TextInput editable="false" id="txtServerResponse" /> </mx:FormItem> <mx:FormItem direction="horizontal" width="100%" label="Server Response (Raw):"> <mx:TextArea editable="false" id="txtServerResponseRaw" width="100%" height="150" /> </mx:FormItem> </mx:Form> <mx:DataGrid id="gridEmployees" variableRowHeight="true" wordWrap="true" rowHeight="100" height="336"> <mx:columns> <mx:DataGridColumn dataField="name" headerText="Name"/> <mx:DataGridColumn dataField="@id" headerText="ID" /> <mx:DataGridColumn dataField="department" headerText="Department" /> <mx:DataGridColumn dataField="location" headerText="Location" /> <mx:DataGridColumn headerText="Photo" id="imageCol" width="319" /> </mx:columns> </mx:DataGrid> </mx:VBox>
Note the last column in the grid with ID imageCol;
this will hold the image upload component you’ll create later. For now, preview
the app to see what you have (see Figure 1).

Figure 1. The Flex app without any data.
To simplify deployment to production, you can use a custom XML file to store server paths and other application-level variables. The values aren’t hardcoded inside the app; instead they’re in a text file that can be easily changed. You only have to modify this one file instead of changing your Flex app and recompiling.
Create an assets folder at the root of your app; right-click
it and choose New > File. Name the file properties.xml. The app
will use two values that change from development to production: the path to the
servlet and the path to the server’s upload folder. They’re named UploadHandler and UploadFolder,
respectively.
Type the following into the properties.xml file:
<properties> <property> <name>UploadHandler</name> <value>http://localhost/upload/UploadHandler</value> </property> <property> <name>UploadFolder</name> <value>http://localhost/upload/uploads/</value> </property> </properties>
The application reads the XML file using an HTTPService call
from the Application container’s creationComplete handler. Add a script
block to the app:
<mx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.http.HTTPService; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; private var xmlProperties:XML; private var servicePropReader:HTTPService; public var uploadServletURL:String; public var uploadFolderURL:String; /** * CreationComplete event handler. Calls an initialization * method. */ private function handleCreationComplete():void { getProperties(); } /** * Reads the custom <code>properties.xml</code> file. * * <p>Fetches the data using the <code>HTTPService</code> call. * The file contains some variables that might change between the * development and production servers. This way, there's no need * to modify the app and recompile; simply change the values in * the XML file.</p> * * <p>The E4X (ECMAScript-for-XML) enables easy access to elements and attributes. * See link below for details.</p> * * @see mx.rpc.http.HTTPService * @see http://livedocs.adobe.com/flex/3/html/help.html?content=data_access_6.html */ private function getProperties():void { servicePropReader = new HTTPService(); servicePropReader.url = "assets/properties.xml"; // Set the URL. servicePropReader.resultFormat = "e4x"; // E4X for easy data access. servicePropReader.contentType = "application/xml"; /* Add event listeners for the result and fault events. */ servicePropReader.addEventListener(ResultEvent.RESULT, propertyReaderResultHandler); servicePropReader.addEventListener(FaultEvent.FAULT, propertyReaderFaultHandler); servicePropReader.send(); // Call the service at the specified URL. } /** * ResultEvent event handler for the servicePropReader HTTPService. * * <p>If we're in this handler, then the call was successful. We set * some global variables to values from the XML file. Note the E4X * methods of reading the XML elements and attributes. * * @param event ResultEvent object holds details on what triggered this event. * * @see mx.rpc.events.ResultEvent; */ private function propertyReaderResultHandler(event:ResultEvent):void { xmlProperties = XML(event.result); uploadServletURL = xmlProperties.property.(name=="UploadHandler").value; uploadFolderURL = xmlProperties.property.(name=="UploadFolder").value; } /** * Fault event handler for the servicePropReader HTTPService. * * <p>If we're in this handler, then the call failed. We pop up an * alert to display the error to the user.</p> * * @param event FaultEvent object holds details on what went wrong. * * @see mx.rpc.events.FaultEvent; */ private function propertyReaderFaultHandler(event:FaultEvent):void { Alert.show(event.fault.message,"Could not load properties XML file."); }
A few things to note in the above code: The resultFormat property of the HTTService call is set to “e4x”, short for the
ECMAScript for XML (E4X) language extension. This format provides
straightforward access to the XML document, without the need to convert it to
an ArrayCollection. To fetch the value element of the node with the name equal to UploadHandler,
you use the following code:
uploadServletUrl = xmlProperties.property.(name=="UploadHandler").value;
Also note that the variables’ types are set when they’re
declared. For example, uploadServletUrl is of type String.
This is an example of early (static) binding; the Flex compiler knows
the properties and methods of the object at compile-time. This can have
dramatic performance benefits. In contrast, with late (dynamic) binding,
you declare the variable as a generic type (such as Object) and then set
the specific type at runtime. Though more flexible, the latter technique has a
performance penalty.
Don’t forget to change the Application tag to call
the new handleCreationComplete() method:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="left" paddingLeft="50" paddingTop="20" creationComplete="handleCreationComplete();">
Don’t worry about the paths in the properties.xml file now; as you create the Java servlet, you can modify the paths. The Java servlet is relatively simple to create, too. It receives the file from Flex and writes it to disk.