In the next version of our Flex-JSP application we’ll show you how to post data from a Flex form to
JSP. We’ll put a simple form under the data grid above to enter the data about the new employee as
in Figure 4.8. Pressing the Add Employee button will submit the entered data to the JSP, which will
attach them to existing employees and return back so the data grid can be repopulated to include
the newly inserted employee.
To design the form, we’ll be using the <mx:Form> Flex objects container, which differs from the
HTML tag <form>. The latter is an invisible container that holds some data, while <mx:Form> is
used to arrange the input controls on the screen with their labels. We’ll also use <mx:Model> to
store the data bound to our <mx:Form>. Let’s also make the employee’s name a required field and
add a so-called validator to prevent the user from submitting the form without entering the name.
It will look like:
<mx:StringValidator id=”empNameVld” source=”{empName}” property=”text” />
<mx:Model id=”employeeModel”>
<root>
<empName>{empName.text}</empName>
<age>{age.text}</age>
<skills>{skills.text}</skills>
</root>
</mx:Model>
<mx:Form width=”100%” height=”100%”>
<mx:FormItem label=”Enter name:” required=”true”>
<mx:TextInput id=”empName” />
</mx:FormItem>
<mx:FormItem label=”Enter age:”>
<mx:TextInput id=”age” />
</mx:FormItem>
<mx:FormItem label=”Enter skills”>
<mx:TextInput id=”skills” />
</mx:FormItem>
<mx:Button label=”Add Employee” click=”submitForm()”/>
</mx:Form>
Listing 4.29 The employee entry form and its model
The required=true attribute displays a red asterisk by the required field but doesn’t do any validation.
The <mx:StringValidator> displays the prompt “This field is required” and makes the border
of the required field red if you move the cursor out of the name field while it’s empty, and shows a
prompt when you return to this field again as in Figure 4.8. But we’d like to turn this default validation
off by adding the triggerEvent property with a blank value:
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 119
<mx:StringValidator id=”empNameValidator” source=”{empName}”
property=”text” triggerEvent=””/>
We’ll also add our own AS3 validateEmpName()function. Now the click event of the Add Employee
button will call validateName(), which in turn will either call the submitForm()function if the name
was entered or display a message box “Employee name can not be blank”.
Validators are outside the scope of this chapter, and so we’ll just mention that Flex comes with a
number of pre-defined classes that derive from the base class Validator. They ensure that the input
data meet certain rules. The names of these classes are self-explanatory: DateValidator, EmailValidator,
PhoneNumberValidater, NumberValidator, RegExValidator, CreditCardValidator, ZipCode-
Validator, and StringValidator. These validators work on the client side, and round-trips to the server
aren’t required. A program initiates the validation process either as a response to an event or by a
direct call to the method validate() of the appropriate validator instance as in Listing 4.30
The final version of the Flex portion of our application is shown below.
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
applicationComplete=”employees.send()”>
<mx:HTTPService id=”employees” useProxy=”false” method=”POST”
url=”http://localhost:8080/test/employees.jsp” result=”onResult(event)” />
<mx:DataGrid dataProvider=”{employees.lastResult.people.person}” width=”100%”>
<mx:columns>
<mx:DataGridColumn dataField=”name” headerText=”Name” />
<mx:DataGridColumn dataField=”age” headerText=”Age”/>
<mx:DataGridColumn dataField=”skills” headerText=”Skills”/>
</mx:columns>
</mx:DataGrid>
<mx:StringValidator id=”empNameValidator” source=”{empName}”
property=”text” triggerEvent=””/>
<mx:Model id=”employeeModel”>
<root>
<empName>{empName.text}</empName>
<age>{age.text}</age>
<skills>{skills.text}</skills>
</root>
</mx:Model>
<mx:Form width=”100%” height=”100%”>
<mx:FormItem label=”Enter name:” required=”true”>
Learning Flex Through Applications
120 RIA WITH ADOBE FLEX AND JAVA
<mx:TextInput id=”empName” />
</mx:FormItem>
<mx:FormItem label=”Enter age:”>
<mx:TextInput id=”age” />
</mx:FormItem>
<mx:FormItem label=”Enter skills”>
<mx:TextInput id=”skills” />
</mx:FormItem>
<!–mx:Button label=”Add Employee” click=”submitForm()”/–>
<mx:Button label=”Add Employee” click=”validateEmpName()”/>
</mx:Form>
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
import mx.controls.Alert;
private function validateEmpName():void{
if (empNameValidator.validate().type == ValidationResultEvent.VALID){
submitForm();
} else{
Alert.show(“Employee name can not be blank”);
}
}
private function submitForm():void {
employees.cancel();
employees.send(employeeModel);
}
private function onResult(event:Event):void{
trace(‘Got the result’); // works only in the debug mode
return;
}
]]>
</mx:Script>
</mx:Application>
Listing 4.30 DataGrid_EX4-JSP2.mxml
When the user hits the Add Employee button on the form, our HTTPService will submit the employeeModel
to a modified employees.jsp, which will now get the parameters from the HTTPRequest object,
prepare the new XML element newNode from the received data, concatenate it to the original
three employees, and return it back to the client, which will display all the employees in the datagrid:
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 121
<%
String employees=”<?xml version=\”1.0\” encoding=\”UTF-8\”?><people><person><name>Alex
Olson</name><age>22</age><skills>java, HTML, SQL</skills></person><person><name>Brandon
Smith</name><age>21</age><skills>PowerScript, JavaScript, ActionScript</skills></person>
<person><name>Jeremy Plant</name><age>20</age><skills>SQL, C++, Java</skills></person>”;
// Get the parameters entered in the GUI form
String name=request.getParameter(“empName”);
String age=request.getParameter(“age”);
String skills=request.getParameter(“skills”);
String newEmployee=”<person><name>” + name+ “</name><age>” + age + “</age><skills>”
+ skills +”</skills></person>”;
if (name == null){
newEmployee=””;
}
// the xml goes back to the Web browser via HTTPResponse
out.println(employees + newEmployee + “</people>”);
%>
Listing 4.31 The new version of employee.jsp
Figure 4.8 The employee form and default validator’s message
You’ll see more examples of the use of HTTPService object in Chapter 5, where we’ll retrieve financial
news from Yahoo!, and in Chapter 13, where we’ll download photos from the popular Flickr.
Learning Flex Through Applications
122 RIA WITH ADOBE FLEX AND JAVA
com. In Chapter 5 we’ll also use HTTPService through a proxy configured with FDS.
Note: There are other ways to pass the data from Flex to a server-side Web application. For example,
you can create an instance of the URLVariables object, create the data to be passed as its properties,
attach URLVariables to URLRequest.data, and call navigateToURL().
Archive for the 'Flex with JAVA' Category
In Chapter 5, we’ll use Flex Data Services to connect a Flex client with plain old Java objects (POJO)
on the server using the object <mx:RemoteObject>. FDS is great software, but you may already
have some Web applications written in another technology and just want to put a pretty Flash Player
face on your existing Java Web applications that use JavaServer Pages (JSP). So the next couple
of pages will show you how to “teach” Flash Player to communicate with a JSP without having to
use FDS.
Retrieving Data from JSP
We’ll be using JSP here, but you can replace JSP with any technology you’re comfortable with: servlets,
Active Server Pages, Python, PHP, et al. Whatever can spit out the data to a Web browser should
work the same way.
We’ll show you a really simple application written in Flex 2 that talks to a JSP that generates XML
with the information about employees:
<people>
<person>
<name>Alex Olson</name>
<age>22</age><skills>java, HTML, SQL</skills>
Learning Flex Through Applications
116 RIA WITH ADOBE FLEX AND JAVA
</person>
…
</people>
Listing 4.26 A fragment of the XML employees data
Let’s just hardcode this XML (we’ve got three persons) into a JSP that consists of one out.println()
statement, where the XML goes between the double quotes:
<%out.println(“…”); %>
The complete JSP looks like this (just put your XML in one line so you won’t be bothered with
string concatenations):
<%
out.println(“<?xml version=\”1.0\” encoding=\”UTF-8\”?><people><person><name>Alex Olson</
name><age>22</age><skills>java, HTML, SQL</skills></person><person><name>Brandon
Smith</name><age>21</age><skills>PowerScript, JavaScript, ActionScript</skills></person>
<person><name>Jeremy Plant</name><age>20</age><skills>SQL, C++, Java</skills></person></
people>”);
%>
Listing 4.27 employees.jsp
Deploy this JSP under some servlet container. In the popular Apache Tomcat this means to save
it as employees.jsp under the webapp\test directory. As a sanity check we make sure that we’ve
deployed this JSP correctly: entering http://localhost:8080/test/employees.jsp in the Web browser
has to return the employee data. Now open Flex Builder and create the application:
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
applicationComplete=”employees.send()”>
<mx:HTTPService id=”employees” useProxy=”false” method=”POST”
url=”http://localhost:8080/test/employees.jsp” />
<mx:DataGrid dataProvider=”{employees.lastResult.people.person}” width=”60%”>
<mx:columns>
<mx:DataGridColumn dataField=”name” headerText=”Name”/>
<mx:DataGridColumn dataField=”age” headerText=”Age”/>
<mx:DataGridColumn dataField=”skills” headerText=”Skills”/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 117
Listing 4.28 DataGrid_E4X_JSP.mxml
This code uses the <mx:HTTPService> component that lets you connect to a specified URL either
directly or through a proxy. The HttpService object is designed to communicate with any URI that
understands HTTP requests and responses. In the code above we’ve just specified the URL for the
JSP from Listing 4.24. The data provider of our data grid uses binding (see the curly braces) and
E4X syntax to parse the XML and populate this table with the elements located under the <person>
XML tag that’s coming from our employees.jsp. In the next section we’ll explain Flex data binding
in more detail.
On the applicationComplete event, the code employees.send() makes an HTTP request to the URL
specified in the HTTPService, and our JSP readily returns the XML that’s bound to the data grid.
Compile and run this program, and it’ll show you the following:
Figure 4.7 The output of DataGrid_E4X_JSP.mxml
Keep in mind that such a direct connection from HTTPService to a JSP is only permitted if your
JSP and Flex application are coming from the same domain, or if the Web server you’re connecting
to has the crossdomain.xml file specifying a cross-domain connection policy with the appropriate
permission for yours or all domains. You can read more about configuring crossdomain.xml in the
product manual under “Building and Deploying Flex 2 Applications.”
Namespaces in AS3 as in MXML are used to limit the scope (visibility) of methods, properties, or
constants. They’re also used to avoid naming conflicts in cases where you create your own custom
components that may have the same names as the Flex Framework or other vendor’s counterparts.
You can think of access control keywords – public, private, protected, and internal – as built-in
namespaces. If a method has been declared as
protected calculateTax(){}
you can say that the calculateTax()method has a protected namespace. But AS3 lets you define your
own namespaces to use instead of these standard language qualifiers.
To introduce your own namespace, you need to take the following steps:
• Declare a namespace
• Apply the namespace
• Reference the namespace
Let’s write a simple program for an accountant who calculates taxes, but customers who belong
to the Mafia would pay only half the amount. To do this, we’ll start by declaring two namespaces:
regular and riabook.
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 113
package com.theriabook.namespaces {
public namespace mafia=”http://www.theriabook.com/namespaces”;
}
Listing 4.21 riabook.as
Please note that using a URI in the namespace declaration is optional. The listing below doesn’t use
any explicit URI, but the compiler will generate one.
package com.theriabook.namespaces {
public namespace regular;
}
Listing 4.22 regular.as
To apply the namespaces, we’ll define a Tax class with two calcTax()methods that will differ in their
namespace access attributes and the amount of tax “calculated”:
package com.theriabook.tax{
import com.theriabook.namespaces.*;
public class Tax
{
regular static function calcTax():Number{
return 3500;
}
riabook static function calcTax():Number{
return 1750;
}
}
}
Listing 4.23 The AS3 class Tax
package com.theriabook.test
{
import com.theriabook.namespaces.*;
import com.theriabook.tax.Tax;
import mx.controls.Alert;
use namespace regular;
// use namespace mafia;
public class TestTax
{
public static function myTax():void {
Learning Flex Through Applications
114 RIA WITH ADOBE FLEX AND JAVA
var tax:Number;
tax=Tax.calcTax();
Alert.show(“Your tax is “+ tax,”Calculation complete”);
}
}
}
Listing 4.24 TestTax.as
Since we apply the namespace for the regular customer, s/he will have to pay a tax of $3,500. The
MXML code that uses TestTax is shown below:
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
layout=”absolute” creationComplete=”initApp();”>
<mx:Script>
<![CDATA[
import com.theriabook.test.TestTax;
public function initApp():void {
TestTax.myTax();
}
]]>
</mx:Script>
</mx:Application>
Listing 4.25 TestTax.mxml
The output of this program looks like Figure 4.6. Switch to another namespace by changing the use
statement to look like
use namespace riabook;
and the amount of the tax to be paid will be substantially lower. Besides the directive use that affects
the entire block of code, AS3 permits finer-grained notation to refer to a specific namespace
with a name qualifier (a double colon). In our example, this may look like:
tax = Tax.riabook::calcTax();
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 115
Figure 4.6 The output of the TextTax.mxml for regular customers
Using namespaces provides an additional means of visibility control. The methods, class properties
of the constants, can be physically located in different packages, but marked with the same
namespace qualifier, and a one-line namespace change can engage a completely different set of
methods/properties across the entire application.
If this was a Java book, we could have patted ourselves on the back for providing a nice example of
polymorphism. Let’s think of a more generic approach – do we even need to use interfaces to ensure
that a particular object instance has a required function like increasePay? Of course not. Java
has a powerful introspection and reflection mechanism that analyzes which methods exist in the
class in question. It’s important to remember though that in Java, object instances have only those
methods that were defined in their classes (blueprints). This is not the case with AS3.
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 111
There is another urban myth that reflection is slow, and you should use it only if you have to. But
this consideration isn’t valid in programs that run on the client’s PCs, because we don’t have to
worry about hundreds of threads competing for a slice of time on the same server’s CPU(s). Using
reflection on the client is fine. Even on the server proper the combination of reflection with caching
allows you to avoid any performance penalties.
AS3 provides very short and elegant syntax for introspection, and we’d like to spend some time illustrating
polymorphism without the typecasting and strict Java-style coding.
Let’s revisit our sample application. Workers get pay and benefits and vacations; consultants are
paid hourly wages. But retirees may have some form of receiving pensions, the board of directors
might get paid but no benefits – are they workers? No, they’re not and their objects may not necessarily
implement the Payable interface, which means that the typecasting from Listing 4.19 would
cause a runtime exception.
How about raising the compensation of every Person even if it doesn’t implement Payable? If one
of these objects sneaks into the workers array , simple casting to Payable as shown below will throw
an exception:
Payable p = Payable(workers[i]);
Let’s rewrite the loop from Listing 4.19 as follows:
for(var i:uint = 0; i < workers.length; i++) {
var p:* = workers[i][“increasePay”];
output.text+=p==undefined?”no luck”:p(5);
}
This short loop deserves an explanation. First, we’ve declared a variable p of type *. This declaration
means that p can be any type. Using an asterisk a bit more open than var p:Object; allows the variable
p to have a special value of an undefined type as used in the above code sample.
Let’s dissect the following line:
var p:* = worker[i][“increasePay”];
It means “Get a reference to the increasePay()function from the array element workers[i].” You may
ask, “Why use the brackets around increasePay instead of the dot notation?” The reason is that dot
notation would ask the compiler to find and validate this function, while the brackets tell the compiler
not to worry about it, the program will take care of this little something inside the brackets
during runtime.
Basically, the single line above performs the introspection and gets a pointer to the increasePay
function for future execution in the line:
Learning Flex Through Applications
112 RIA WITH ADOBE FLEX AND JAVA
output.text+=p ==undefined?”no luck”:p(5);
If this particular element of the workers array doesn’t have increasePay defined (its class must be
declared dynamic), add “no luck” to the text field. Otherwise execute this object’s version of increasePay,
passing the number five as its argument. The line above is still a potential problem if
the class doesn’t have the increasePay function, but has a property with the same name. The better
version looks like this:
output.text+=!(p is Function)?”no luck”:p(6);
Let’s emphasize that again: this increasePay method doesn’t have be defined in any interface.
Java programmers would call this wild anarchy. Of course, adhering to strict rules and contracts in
Java leads to more predictable code and less surprises at runtime. But modern Java moves toward
dynamic scripting, adding implicit typecasting, runtime exceptions, etc. Overuse of interfaces, private,
protected, and other “nice clean object-oriented techniques” doesn’t promote creative thinking
in software
As in Java, AS3 interfaces are special entities that define the behavior (methods) that can be implemented
by classes using the keyword implement. After explaining what’s crucial to OOP interfaces,
we’ll discuss how to write generic code without them.
To illustrate how you can design AS3 programs with interfaces, we’ll add some behavior to the
classes from Listing 4.14. Let’s work on the following assignment.
A company has employees and consultants. Design classes to represent the people working in this
company. The classes can have the following methods: changeAddress, giveDayOff, increasePay. Promotion
can mean a day off and a salary raised a specified percentage. For employees, the increasePay
method should raise the yearly salary and, for consultants, it should increase their hourly rate.
First, we’ll add all the common methods that are applicable to both employees and consultants to
the Person class.
package com.theriabook.oop {
public class Person {
var name:String;
public function changeAddress(address: String): String {
return “New address is” + address;
}
private function giveDayOff(): String {
return “Class Person: Giving an extra a day off”;
}
}
}
Listing 4.15. The Ancestor class: Person
In the next step, we’ll add a new behavior that can be reused by multiple classes: the ability to increase
the amount of a person’s paycheck. Let’s define a Payable interface:
package com.theriabook.oop
{
public interface Payable
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 107
{
function increasePay(percent:Number): String;
}
}
Listing 4.16. Interface Payable
More than one class can implement this interface:
package com.theriabook.oop
{
public class Employee extends Person implements Payable
{
public function increasePay(percent:Number):String {
// Employee-specific code goes here …
return “Class Employee:Increasing the salary by “+ percent + “%\n”;
}
}
}
Listing 4.17 The AS3 class Employee implementing the Payable interface
package com.theriabook.oop
{
public class Consultant extends Person implements Payable {
public function increasePay(percent:Number): String{
// Consultant-specific code goes here …
return “Class Consultant: Increasing the hourly rate by ” + percent + “%\n”;
}
}
}
Listing 4.18 The Consultant class implementing Payable
When the Consultant class declares that it implements a Payable interface, it “promises” to provide
implementation for all the methods declared in this interface – in our case there’s just one
increasePay()method. Why is it so important that the class “keeps the promise” and implements all
the interface’s methods? An interface is a description of some behavior(s). In our case the Payable
behavior means the existence of a method with the signature boolean increasePay(int percent).
If any other class knows that Employee implements Payable, it can safely call any method declared
in the Payable interface (see the interface example in the Promoter class in Listing 4.19).
Learning Flex Through Applications
108 RIA WITH ADOBE FLEX AND JAVA
In Java, besides method declarations, interfaces can contain final static variables, but AS3 doesn’t
allow anything in the interfaces except method declarations.
Interfaces are another workaround for adjusting to the absence of multiple inheritance. A class
can’t have two independent ancestors, but it can implement multiple interfaces, it just has to implement
all the methods declared in all the interfaces. One way to implement multiple inheritance
(that we often use but don’t recommend it) is to use an “include” statement with the complete
implementation of all classes implementing interface:
public class Consultant extends Person implements Payable {
include “payableImplementation.as”
}
public class Employee extends Person implements Payable {
include “payableImplementation.as”
}
For example, a Consultant class can be defined as:
class Consultant extends Person
implements Payable, Sueable {…}
But if a program such as Promoter.mxml (see Listing 4.19) is interested only in Payable functions, it
can cast the object only to those interfaces it intends to use. For example:
var emp:Employee = new Employee();
var con:Consultant = new Consultant();
var person1:Payable = emp as Payable;
var person2:Payable = con as Payable;
Now we’ll write an MXML program Promoter that will use the Employee and Consultant classes
defined in Listings 4.17 and 4.18. Click on the button and it’ll create an array with a mix of employees
and consultants. Iterate through this array and cast it to the Payable interface, then call the
increasePay()method on each object in this collection.
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>
<mx:Label y=”10″ text=”Inheritance, Interfaces and Polymorphysm” width=”398″
height=”35″ fontWeight=”bold” horizontalCenter=”-16″ fontSize=”16″/>
<mx:Button x=”93″ y=”66″ label=”Increase Pay” width=”172″ fontSize=”16″
click=”startPromoter()” id=”starter”/>
<mx:TextArea x=”26″ y=”114″ width=”312″ height=”133″ id=”output” wordWrap=”true”
editable=”false” borderStyle=”inset”/>
<mx:Script>
CHAPTER 4
RIA WITH ADOBE FLEX AND JAVA 109
<![CDATA[
import com.theriabook.oop.*;
function startPromoter():void{
output.text="Starting global promotions...\n";
var workers:Array = new Array();
workers.push(new Employee());
workers.push(new Consultant());
workers.push(new Employee());
workers.push(new Employee());
for(var i: int = 0; i < workers.length; i++) {
// Raise the compensation of every worker using Payable
// interface
var p: Payable = workers[i] as Payable;
output.text+= p.increasePay(5);
//p.giveDayOff(); would not work. Payable does not know
// about this function
}
output.text+=”Finished global promotions…”;
}
]]>
</mx:Script>
</mx:Application>
Listing 4.19 Promoter.mxml
The output of this program will look like:
Figure 4.5 The output of Promoter.mxml
Learning Flex Through Applications
110 RIA WITH ADOBE FLEX AND JAVA
The line p.increasePay(5) in the listing above may look a little confusing. How can we call a concrete
increasePay method on a variable of an interface type? Actually we call a method on a concrete
instance of the Employee or a Consultant object, but by casting this instance to the Payable
type we’re just letting the AVM know that we’re only interested in methods that were declared in
this particular interface.
Polymorphism – When you look at our Promoter from Listing 4.19, it looks like it calls the same
increasePay()method on different types of objects, and it generates different outputs for each type.
This is an example of polymorphic behavior.
In the real world, array workers would be populated from some external data source. For example,
a program could get a person’s work status from the database and instantiate an appropriate concrete
class. The loop in Promoter.mxml will remain the same even if we add some other types of
workers inherited from the Person class! For example, to add a new category of worker – a foreign
contractor, we’ll have to create a ForeignContractor class that implements the increasePays method
and might be derived from the Person class. Our Promoter will keep casting all these objects to the
Payable type during runtime and call the increasePay method of the current object from the array.
Polymorphism allows you to avoid using switch or if statements with the checking type operator
is. Below is a bad (non-polymorphic) alternative to our loop from Promoter.mxml that checks the
type of the object and calls the type-specific methods increaseSalary() and increaseRate() (assuming
that these methods were defined):
for(var i: int = 0; i < workers.length; i++) {
var p: Person = workers[i] as Person;
if (p is Employee){
increaseSalary(5);
} else if (p is Consultant) {
increaseRate(5);
}
}
Listing 4.20 A bad practice example
You’d have to modify the code above each time you add a new worker type.

