Igor Polevoy
Created
8 September 2008
Prerequisite knowledge
Prior experience working with Flex Builder to create applications.
 
User level
Intermediate
Required products
Flex Builder (Download trial)
Sample files
flex_seam.zip (34 KB)
Exadel Inc. has released a new open source technology called Exadel Flamingo that connects server-side technologies such as JBoss Seam and Spring Framework to various rich client-side technologies, including Adobe Flex. The ultimate goal of Flamingo is to provide developers with agile tools for building business applications. For a short description of Exadel Flamingo, see the introductory, hands-on article I wrote on TheServerSide.com, which shows some of the powerful features that Flamingo offers.
 
Flamingo simplifies the task of building rich Internet applications using Flex and Seam.  Seam is a technology from JBoss, a division of Red Hat, and serves as an integration layer between JavaServer Faces (JSF) and Enterprise Java Beans. Developing applications with Seam is easy, and Flamingo allows you to use Seam from non-JSF clients, one of which is Adobe Flex. Seam has some other interesting features, such as the ability to directly consume server-side components on the client side, referring to components by name, additional scope support, and the bijection pattern – one of its most touted features.
 
This article describes a simple project that uses JBoss Seam, Flamingo, and Adobe Flex together to build a very basic application that stores some information in a database.  Since the sample application is deployed using JBoss, the application also takes the opportunity to use the EJB 3.0 support and the Java Persistence API (JPA). 
 
The easiest way to learn how to build applications with Flamingo is to start using it. So let's get started.

 
Setting up the development environment

To build the sample project, you need Adobe Flex, Exadel Flamingo, the Java SDK, and the JBoss Application Server installed on your machine.
 
After downloading Flamingo, create an environment variable FLAMINGO_HOME and set it to the root directory of Flamingo installation.
 
Technically speaking, Flamingo works with Adobe Flex 2, and you are free to use either version 2 or 3. Create an environment variable FLEX_HOME and set it to the root of Adobe Flex SDK installation.
 
The sample project uses a Maven-based project structure. Flamingo tools (and specifically the project generation wizard) create this project structure, but it is possible (and easy) to integrate Flamingo into existing projects.  Create an environment variable M2_HOME and point it to the Maven installation directory, and then add M2_HOME/bin to your PATH.
 
Likewise, you can use any application server with Flamingo, since Flamingo applications are standard Java WAR or EAR files once packaged.  For this article, however, I chose JBoss 4.2.x as a deployment platform because I am using Seam as the server-side technology.
 
Lastly, since this is a database-driven application, naturally you will need a database. There are many options to choose from, and Flamingo is really database-neutral. The Flamingo project generation wizard, however, can generate projects for the following databases: Hypersonic SQL, MySQL, Oracle, Posgres, MSSQL, DB2, and Sybase. If you already have a database in your environment, go ahead and use it. Otherwise you can use the HypersonicSQL database, which is included with JBoss.
 
To simplify deployment, the example project in this article uses HypersonicSQL.
 
To switch to a different database follow these steps:
 
  1. Change the Hibernate dialect in the following file: flamingo-example/ejb/src/main/resources/META-INF/persistence.xml
  2. Change the data source configuration in the following file: flamingo-example/ejb/src/main/resources/example-ds.xml
  3. Install a database driver according to the server documentation (for JBoss, install it in server/default/lib)
Examining the project structure
The goal of the sample application is to demonstrate two Flamingo features: ease of integration with JBoss Seam and native use of Hibernate Validation annotations for validating form input. Since this is a Java Enterprise project, there are four modules in it: ear, ejb, web, and flex-amf (see Figure 1). For developers who have experience with Java Enterprise technologies, this layout should look familiar. Also, Flamingo uses Maven for building projects, and those who have worked with Maven will feel right at home.
 
Figure 1. The project's four modules.
Figure 1. The project's four modules.
After you download project, build it using the following command:
 
maven install
 
Wiring Seam and Flex
Let's start by defining the persistent model for the application. This is a simple application with only one table and one respective JPA entity defined for it in the following sample file:
 
flamingo-example/ejb/src/main/java/com/exadel/flamingo/samples/seam/example/Person.java
 
@Entity@Name("person")public class Person implements Serializable { private Integer id; private String firstName; private String lastName; private String email; ...//setters and getters omitted for clarity}
Listing 1. Definition of the Person entity.
 
In Listing 1, you see a typical definition of an entity called Person with four properties. This could very well be a Hibernate entity; the only unusual aspect is the @Name annotation. This Seam annotation makes this class a Seam component. So far the code in Listing 1 does not include anything specific to Flamingo. This shows that it is possible to use Flamingo to build a Flex-based user interface for an existing Seam application.
 
Next, let's look at the definition of a client class which represents the server entity in the following sample file:
 
flamingo-example/flex-amf/src/main/flex/Person.as
 
[Bindable][RemoteClass(alias="com.exadel.flamingo.samples.seam.example.Person")]public class Person{ public var id:Number; public var firstName:String; public var lastName:String; public var email:String;... }
Listing 2. Definition of the client-side class.
 
The code in Listing 2 creates a client-side class called Person, makes it bindable to client UI components, and connects it to the Person Seam component on the server side.
 
To connect the client and server, you need to configure two files.  The first file is flamingo-example/flex-amf/src/main/resources/services-config.xml and it contains the entry shown in Listing 3.
 
<endpoint uri="http://{server.name}:{server.port}/flamingo-example/seam/resource/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
Listing 3. The endpoint entry in services-config.xml.
 
The second file is flamingo-example/web/src/main/webapp/WEB-INF/web.xml and it contains the code shown in Listing 4.
 
<servlet> <servlet-name>Seam Resource Servlet</servlet-name> <servlet-class> org.jboss.seam.servlet.SeamResourceServlet </servlet-class></servlet> <servlet-mapping> <servlet-name>Seam Resource Servlet</servlet-name> <url-pattern>/seam/resource/*</url-pattern> </servlet-mapping>
Listing 4.  Code from web.xml.
 
Since the JPA implementation in JBoss is done with Hibernate under the hood, I will use it to execute the file flamingo-example/ejb/src/main/resources/import.sql when the application starts to seed the person table with a few records.
 
The next thing to do is to construct some client code. Flamingo really is designed to help develop database-driven applications, so I will build a very simple GUI just to show the usage of Flamingo.
 
The GUI has two graphical components: a list of persons that reflects the data in the database table person, and a simple form for adding new people. The full code can be found in the following file:
 
flamingo-example/flex-amf/src/main/flex/main.mxml.
 
[Bindable]private var people:ArrayCollection; [Bindable]private var selectedItem:Person; <mx:RemoteObject id="person" destination="Person" result="resultHandler(event)" fault="faultHandler(event)"> <mx:method name="save" result="updateTable(event)" fault="faultHandler(event)"/> ...
Listing 5. Code from main.mxml.
 
private function resultHandler(event:ResultEvent):void{ people = event.result as ArrayCollection;}... <mx:Button label="Refresh" click="{person.findAll()}"/> <mx:DataGrid id="peopleGrid" width="400" height="250" dataProvider="{people}" itemClick="selectPerson()"> <mx:columns> <mx:DataGridColumn headerText="id" dataField="id" width="50"/> <mx:DataGridColumn headerText="First Name" dataField="firstName"/> <mx:DataGridColumn headerText="Last Name" dataField="lastName"/> <mx:DataGridColumn headerText="E-Mail" dataField="email"/> </mx:columns> </mx:DataGrid>
Listing 6.  Defining the data grid and result handler.
 
The code in Listing 5 defines two bindable variables, one for a collection of Person objects, the other just for one. It also defines a RemoteObject, with Id: person, whose destination is a server-side Person entity.
 
Listing 6 provides a glimpse of the power of Flamingo. The data grid peopleGrid is a graphical Flex class that displays tables of data. This data grid is bound to a collection called people, which is defined in Listing 5.
 
The Refresh button, when clicked, calls the method person.findAll(). This is a special method and is part of a very powerful Flamingo feature called Dynamic Persistent Methods. While outside the scope of this article, this feature will be covered in a future article. Although this method is not declared in any of the classes in the project, Flamingo does provide it at run time. In short, it queries all records from the database and when the query returns, a function resultHandler() is executed (see Listing 6).
 
Inside resultHandler(), the collection people is set with new values from the database. Because this collection is bound to a grid, the grid immediately reflects the results of the query.
 
So far, the application reflects the content of a person table in the database to a data grid in the GUI. As you can see, standard technologies were used. Developers do not have to learn much to use Flamingo, and getting data on the screen has been a breeze. What about adding a new entry into the table? For this you need to create a new form (see Listing 7).
 
<mx:Form width="100%"> <mx:FormItem label="First Name" width="100%"> <mx:TextInput id="firstNameTB"/> </mx:FormItem> <mx:FormItem label="Last Name" width="100%"> <mx:TextInput id="lastNameTB"/> </mx:FormItem> <mx:FormItem label="E-Mail" width="100%"> <mx:TextInput id="emailTB"/> </mx:FormItem> <mx:Button label="Save" click="savePerson()"/> </mx:Form>
Listing 7. Adding a form.
 
The code in Listing 7 shows a simple form for entering information to fill in the properties of a Person class.  After you enter the data in the text fields and click the Save button, the information is sent to the server side.
 
private function savePerson():void{ var tmp:Person = new Person(); tmp.firstName = firstNameTB.text; tmp.lastName = lastNameTB.text; tmp.email = emailTB.text; person.save.send(tmp);} private function updateTable(event:ResultEvent):void{ person.findAll(); }
Listing 8. Code for creating a new Person.
 
If you look carefully at the definition of the RemoteObject person in Listing 5, you will notice that it overrides a default handler for the save() method to updateTable(). This means that when a user clicks the Save button, a call is sent to the server side, and if this is successful, the function updateTable() is executed. Inside this method a call is made to person.findAll(), and the same happens as above: the data grid is updated with the entire contents of the database table. As you can see, with only a few lines of code, you can exchange data between Flex and the database with ease.
 
Flamingo validation
You now have a perfectly functioning little CRUD (Create, Read, Update, and Delete) application (yes it can delete, this code is omitted from article for clarity), but any respectable database application must be able to validate user input. Flamingo provides direct transparent validation in a form of integration with the Hibernate Validator framework. For more information on this framework, see http://www.hibernate.org/412.html. The Hibernate Validator is a very convenient way of implementing validation by sprinkling some easy-to-understand annotations on entities. It provides quite a few ready to use annotations for various needs, including max/min length, digits, e-mail, and even credit card validation. If you cannot find a ready-made annotation for your needs, you can use regular expression annotation or even bind to methods of a class and write any validation rule you want.
 
Let's use this Hibernate Validator and Flamingo validation integration for validating user input. Flamingo will execute the validation rule on the server side and will return a message to the Flex application if the validation fails. You may wonder why you would want to do validation on the server side, since in Flex you can write any code you want to validate on the client side. There are several possible reasons:
 
  • You already have an existing Seam application with all the validation requirements defined
  • You don't want to re-invent the wheel
  • There is no code to write (unless you are doing custom validation)
  • If you are doing custom validation against data in the database, you will need to make a server call anyway
  • Flamingo uses efficient binary protocols to communicate with server, so the performance impact will be small (if noticeable at all)
  • You want an extremely convenient way for validating user input
To use server-side validation, add a Hibernate Validation to the Person entity, as shown in Listing 9.
 
@Length(max=20, min=2, message="First name should be between 2 and 20 characters")private String firstName;
Listing 9. Adding a server-side validation to the Person entity.
 
Listing 9 is only a fragment of the code, but it shows that I added the @Length annotation to the firstName property. This definition almost reads like English: I want the first name to be at least 2 characters and at most 20 characters long. When the user enters a value that is not within the specified range, a corresponding message is fired.
 
The second step I need to make is to wire the validation to a graphical component. In Listing 7, there is a TextInput with the id firstNameTB. To connect the Hibernate Validator and the text input together, I added the Flamingo validator definition shown in Listing 10 to the Flex application.
 
<flamingo:EntityValidator id="validator1" destination="Person" validationTarget="firstName" source="{firstNameTB}" property="text" required="false" />
Listing 10.  Flamingo validator definition.
 
After I add this definition, rebuild the application, and deploy it on the server, I can test the finished product. When I try to add a new person, type a single character into the First Name field, and then place a cursor into another field, Flamingo immediately fires a validation rule on the server, and if it does not validate, passes a message to Flex (see Figure 2).
 
Figure 2. Results of a Flamingo validation test.
Figure 2. Results of a Flamingo validation test.

 
Where to go from here

Given how little code was written and how much functionality it provided, you can see the value Flamingo provides for rapid development of Flex- and Seam-based applications. Connecting Seam and Flex components was really easy, and so was the use of server-side validation. Exadel Flamingo provides many other capabilities as well, such as Dynamic Persistent Methods, advanced code generation tools, and a choice of AMF or a Hessian binary protocol for server communication. I will be covering these advanced functions in future articles.
 
I encourage you to download and play with the example project for this article. For more information on Flamingo, download the Developer Guide and explore the Flamingo Flex API at http://www.exadel.com/flamingo/docs/.