-J2EE Developer at Turkiye Is Bankası Core Banking Exchange project -Java-Flex Developer in TAV IT. Built softwares for several international airport (istanbul, ankara, izmir, tblisi, batumi, emfidha) with JPA/Spring/CXF/BlazeDS on server side and Flex on rich clients. -JavaEE&Process Project Laader at HSBC. -Presenter at Eclipsist 2008, on Rapid Rich Internet Application Development. Murat has posted 8 posts at DZone. View Full User Profile

Flex Meets Google App Engine

05.15.2009
| 29880 views |
  • submit to reddit

Adobe did a very good job with Flex and they are far ahead of their rivals in RIA area. Meanwhile Google is doing great with several Java projects (such as Guice, GWT) and bringing Java support to Google App Engine. Actually Google even has an open source Flex component library called flexLib.


Java on Google App Engine is a very important step. Since I graduated I've heard most of friends bringing up ideas but not trying to build them, mostly because of the costs of Java hosting. Java is a elegant and sophisticated platform which is fun to work on but never offers cheap and easy hosting alternatives like PHP. Google App Engine can finally change this. It offers zero cost startup, flexible payment options as your project grows and also provides a very easy development environment. All you need is just to install the Eclipse plugin and start coding. Even when a new GAE project is created, a basic GWT example is already included.


I really like the scene where Obi-wan Kenobi meets Anakin Skywalker in Episode I. Qui-Gon introduces Anakin and says “Anakin Skywalker meet Obi-Wan Kenobi”. It is an important scene bringing two different people together for a very long time. This post will be an introduction of Flex to Google App Engine. Two great but totally different worlds. We will build a very basic servlet to feed data to our Flex application, and use Google's datastore to easily persist the data. Before starting the tutorial I assume GAE plugin and Flex builder plugin is already installed to your Eclipse instance.
You must have noticed the new three buttons on toolbar. Just click the “New Web Application Project”.

Next give a package and project name.


You must have noticed the wizard already added GreetingService, GreetingServiceImpl and a GWT class with the name of your project (in this case “FirstProject”). This is a good start especially for starting GWT but not useful for us. Just leave them there and open web.xml file under war/WEB-INF and add a servlet description.

We are ready to create a servlet to feed our Flex Client. Right click org.flexjava.server package and add a new class file extending HttpServlet as shown below.

Now its time to design our backend service. I don't really like hello world projects so even if we are coding a basic project lets find a real (but still basic) phonebook project worth to code. For the basic functionality we need retrieve the list of the contacts stored in the datastore and we also need to add new ones.


We need an Entity for our contacts. Lets create a new Class named Entry and add the annotations to make our Entry class persistance capable.

 

package org.flexjava.server;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable
public class Entry {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;
@Persistent
private String name;
@Persistent
private String phone;

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// Add all getter/setters...
}

GAE's datastore is quite easy to use. Just create a persistanceManager and use makePersistant or newQuery methods to save or retrieve data.

PersistenceManager persistenceManager = pmfInstance.getPersistenceManager();
//..
persistenceManager.makePersistent(entry);
//..
persistenceManager.newQuery(query).execute();

Lets start coding our servlet using those.

package org.flexjava.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class FlexServiceImpl extends HttpServlet {
//persistanceManager
private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");

@SuppressWarnings("unchecked")
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//PrintWriter to return and receive data from flex client
PrintWriter writer=resp.getWriter();
writer.println("\n");
PersistenceManager persistenceManager = pmfInstance.getPersistenceManager();
//reading parameters from http request
String operation = req.getParameter("operation");
String name = req.getParameter("name");
String phone = req.getParameter("phone");
//if adding new contact is requested
if (operation.equalsIgnoreCase("save")){
Entry entry=new Entry();
entry.setName(name);
entry.setPhone(phone);
persistenceManager.makePersistent(entry);
writer.println("Success");
//if retrieving all contact list is requested
}else if (operation.equalsIgnoreCase("get")){
//Query to retrieve all Entry data
String query = "select from " + Entry.class.getName();
List entries = (List) persistenceManager.newQuery(query).execute();
writer.println("");
for (Entry entry : entries) {
writer.println("");
writer.println(""+entry.getName()+"");
writer.println(""+entry.getPhone()+"");
writer.println("");
}
writer.println("");
}
}
}

Our GAE code is ready, now we can move on to Flex. To enable our project Flex compatible, right click project and select add Flex Project Nature.

Click next to continue.

Select war folder as the output folder so the build files will be deployed to server.

Since we just added Flex nature and created a mxml file, Flex Builder finds it confusing to prepare the HTML wrapper files for the SWF build. To make Flex builder's life easier go to errors tab, right click the error and select recreate HTML Templated. If there are no errors just skip this and continue.

Now we are free to design our own user interface. Switch to design view drag and drop 2 labels, 2 text boxes, a button and a datagrid component.

Now we can switch to source mode to code. We are going to use very little coding, most of the work will be done by auto XML parsing and binding the data between components and variables.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="callService('get')">
<mx:TextInput x="114" y="20" id="nameTxt"/>
<mx:TextInput x="114" y="60" id="phoneTxt"/>
<mx:Label x="29" y="22" text="Name"/>
<mx:Label x="29" y="62" text="Phone"/>
<mx:Button x="332" y="60" label="Save" click="callService('save')"/>
<!-- datagrid is directly binded to phonebook variable -->
<mx:DataGrid x="29" y="138" dataProvider="{phonebook.entry}">
<mx:columns>
<!--datafields determine which property belongs to that column-->
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Phone" dataField="phone"/>
<mx:DataGridColumn headerText="Record Id" dataField="@id"/>
</mx:columns>
</mx:DataGrid>
<!--HTTPService can easily post and receive xml data-->
<mx:HTTPService id="httpXmlDataService" url="http://localhost:8080/firstproject/flex" resultFormat="e4x" result="resultHandler(event)" useProxy="false">
<!--xml request will be automatically formed with bindings-->
<mx:request xmlns="">
<operation>{command}</operation>
<name>
{nameTxt.text}
</name>
<phone>
{phoneTxt.text}
</phone>
</mx:request>
</mx:HTTPService>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var command:String;
[Bindable]
private var phonebook:XML;
//xml var to hold the received data,note bindable attribute
//to enable binding

public function resultHandler(event:ResultEvent):void{
if (event.result!=null){
var xml:XML=event.result as XML;
if (xml.result=="success"){
callService("get");
}else{
phonebook=xml;
}
}
}
public function callService(command:String):void{
this.command=command;
httpXmlDataService.send();
}
]]>
</mx:Script>
</mx:Application>

So little and our client is ready, right click the project and select run as Web Application. 

GAE Plugin adds an embedded datastore and a server to your project to test. Whenever you click run the embedded services will be running and even an internal browser will run your client. Since our project name and mxml file has the same name, the default page on web.xml file point to our Flex application. Please dont forget to modify in your web.xml file if yours differ.

Easy? Well yes but still this does not release the real power and integration of Java and Flex. Next time we will focus on BlazeDs to make Flex to talk to Google App Engine. Stay tuned ;)

Legacy
Article Resources: 
Published at DZone with permission of its author, Murat Yener.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Murat Yener replied on Sat, 2009/05/16 - 3:15am

Hi, Yesterday i got an email from yang11(http://java.dzone.com/users/yang11) stating the following error in the servlet code; "...it gives me an error "Type mismatch: cannot convert from element type Object to Entry". Can you help me solve this problem..." Sorry for the copy paste error, go to line 40 of FlexServiceImpl servlet and replace it with the following;
List<Entry> entries = (List<Entry>) persistenceManager.newQuery(query).execute();
This should work.. Thanks Yang..
p.s. Just realised how this error happened :) I post this article first on my site www.flexjava.org which uses blogger. Blogger thought List<Entry> is an html tag and deleted from the code part. Later when i copy and paste it to here this part was missing... Sorry for that and pls let me know if there are any other problems...

Jonny Yorke replied on Wed, 2009/05/20 - 5:45am

Hey!

Great article. Can you publish the entire project..? I'm probebly missing a very basic thing and looking at the actual project structure will help me. Thanks!

Murat Yener replied on Wed, 2009/05/20 - 4:17pm

Sure, i added the project export. Please let me now if anything is wrong..

Thanks...

Fred Rahmanian replied on Thu, 2009/05/21 - 12:11pm

Is it possible (and does it make sense) to use GAE for data store only? What are the security implications? Would Putting a cross domain file on GAE suffice? Thanks for a great article. Fred R.

Murat Yener replied on Thu, 2009/05/21 - 3:29pm in response to: Fred Rahmanian

To be honest I am not a GAE expert, but it does make me excited and I really think it is going to fill a gap between developer ideas and cheap hosting (free startup). Never thought of using it only for data store but depending on your subject actually yes you may... GAE for Java is in very early stage so security issues must be evaluated. Even thought it is in early stage I find it great to see it works with other platforms than GWT and offers a stable and easy development environment. Ohh and thanks for your nice comments, hope the article can give some ideas for starting up.

Murat

Chetan Sachdev replied on Sat, 2009/05/30 - 2:29pm

Very nice article although syntax highlighter is playing with the code so it took me a few minutes to recognise that I am not getting XML and getting raw strings :D Have a look at FlexServiceImpl

for (Entry entry : entries) {

writer.println("");

   writer.println(""+entry.getName()+"");        writer.println(""+entry.getPhone()+"");        writer.println("");}

 Very nice article, integrated flex and gae in about 30 minutes (includes all installation time)

 

Thanks, now jumping to next article with BlazeDS integration.

 

Murat Yener replied on Wed, 2009/06/03 - 9:47pm in response to: Chetan Sachdev

Thanks for nice comments, and you are absolutely right. It is all the same copy/paste error. I attached a poject export, hope it helped..

Ola Bratt replied on Mon, 2009/07/06 - 1:34am

Love you, cant show it! Amazing how easy that was. I agree on the "star wars"-symbolism.

Antonio Monroy replied on Tue, 2010/04/06 - 11:04am

I'm starting in GAE, my question is how I can enable the option to Flex Project Nature, for Add Flex Project Nature. Thanks in advance

Antonio Monroy replied on Tue, 2010/04/06 - 11:27am

Hello again, in my previous comment the type of my project was type "Flex Project" and now in a new project was of type "Project", the latter type of project allows me the option to "Add Flex Project Nature". I continue my project and I will comment the result. Thanks.

Antonio Monroy replied on Wed, 2010/04/07 - 1:14pm

The project sent me error, could not find the file "crossdomain.xml", added the crossdomain.xml in the folder war, now no longer sends error but does absolutely nothing, any suggestions please. the content of crossdomain.xml is
"I omitted the signs <>"
xml version="1.0" encoding="UTF-8"?
cross-domain-policy
site-control permitted-cross-domain-policies="all"/
allow-access-from domain="*" secure="false"/
allow-http-request-headers-from domain="*" headers="*" secure="false"/
/cross-domain-policy

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.