Its fairly common these days to see Flex applications running inside Salesforce.com. But what if you'd like to run your Flex applications on another SaaS provider like Google App Engine or Amazon EC2. We are going to set up a simple Flex application that fetches Accounts and Opportunities from Salesforce.com using an open source remoting library that runs on Google App Engine. Here a quick peak at the final application:
Flex can communicate with a Java backend using HTTP, SOAP-based web services or Adobes proprietary AMF format. There are a number of open source AMF implementations including Aodobe BlazeDS, WebORB and GraniteDS. These implementations allow you to communicate via JMS or Flex remoting and are more efficient and exponentially faster than using XML across the wire. For this application we are going to be utilizing GraniteDS. The GraniteDS remoting service is a high performance data transfer service that allows your Flex applications to directly invoke Java object methods on your application and consume the return values natively. The objects returned from the server-side methods are automatically deserialized into either dynamic or typed ActionScript objects.
Setting Up Your Environment
To get started you'll need to download the Adobe Flex 3.0 Builder 3 or Flex 3 Builder Plug-In. Theres a 60 day trial if you dont already have a license. Installation is pretty straight-forward if you are familiar with the Eclipse installation process. The plug-in is a little easier and quicker to install.
If you don't have a Google App Engine account, you can create one here. You'll also need to download and install the Google App Engine SDK and Eclipse plug-in. You can find details on this process here.
Creating Your Project
Now that our environment is setup, create a new Web Application Project and uncheck Use Google Web Toolkit. Since we are going to be using Flex as the front end for our application you will want to add the Flex Project Nature to your project. Right click on the project name in the left panel and select Flex Project Nature -> Add Flex Project Nature. Choose Other as the application server and click Next and then Finish. This will automatically create your Flex main.mxml file for you in the src directory.
After the file has been created you should see the following error message in the Eclipse Problems tab, "Cannot create HTML wrapper. Right-click here to recreate folder html-template." To fix this simply right click on the error message and select Recreate HTML Templates.
Adding Required Libraries
There are a number of libraries that we are going to need for Salesforce.com and GraniteDS. Download the latest version of GraniteDS from here, unzip the files, find the granite.jar in the graniteds/build/ directory and place it into your projects /WEB-INF/lib/ directory.
Youll also need to get the latest version of Xalan-J from here. Unzip the files and copy serializer.jar and xalan.jar into your projects /WEB-INF/lib directory.
There are two jar files you will need for the Salesforce.com integration. Download the Force.com Web Service Connector files from here and copy them to your project's /WEB-INF/lib directory:
partner-library.jar - the objects and methods from the Force.com partner WSDL
wsc-gae-16_0.jar - the Web Service parsing and transport for GAE-Java
You’ll need to add these new jar files to your Java build path in Eclipse by right clicking on the project name and selecting Properties. Select Java Build Path -> Libraries and add your jars from the lib directory.
Server Configuration
So now that we have all of requirements in place we can start configuring our application. Place the following code into your /WEB-INF/web-xml file between the tags to tell App Engine which classes GraniteDS utilizes.
You'll also want to change the welcome-file to specify main.html instead of the generated index.html file.
GraniteDS communicates with the servlet container via a remoting destination. A Remoting destination exposes a Java class that your Flex application can invoke remotely. The destination id is the logical name that your Flex application uses to refer to the remote class. This eliminates the need to hardcode a reference to the fully qualified Java class name. This logical name is mapped to the Java class name as part of the destination configuration in services-config.xml. Create a new folder under /WEB-INF/ called flex and create the following services-config.xml file.
Our remoting destination points to a class called Gateway that we will create shortly. Now we need to tell the Flex compiler where to find the services file that defines our remoting destination. Right click on the project name in the left panel and select Properties -> Flex Compiler. Replace your compiler arguments with the following:
Now that our server is configured we can start working on the Flex client. Our client is fairly simple and allows a user select an Account and view/create Opportunities for it. The Flex portion of the application is represented by a single MXML file. For larger applications you would typically break your application into an MVC model and possibly use some sort of Flex framework like Cairngorm, Mate or PureMVC. Since our application is so small there is really no need to implement any sort of framework.
One of the most important parts of this file is the RemoteObject tag at the top. The id of the tag (gateway) is used by the application to reference the object while the destination (Gateway) is same destination we set up in our services-config.xml file specifying our remoting destination of com.appirio.Gateway.
The individual methods specified by the RemoteObject tag map directly to methods in the Gateway class that we are about to define.
One last thing we need for the front end are Account and Opportunity value objects. Right-click the src folder and select New -> ActionScript Class. Enter the class name as and click Finish. Add the following code to these classes. Notice that the code uses the [RemoteClass(alias=" com.appirio.Account")] annotation to map the ActionScript version of the Account class (Account.as) to the Java version (Account.java). As a result, Account objects returned by methods of the Java object in the service layer that are deserialized into instances of the ActionScript Account class automatically for you.
Server-Side Code
So now back to the server-side to finish up our application. We need to add the POJOs to model our Account and Opportunity object returned from Salesforce.com. These classes will consist of the same members as the ActionScript classes so that GraniteDS can translate them back and forth for us.
The last part of our application is the Gateway class that GraniteDS uses as the remoting endpoint. This class contains the methods that our Flex front-end calls via the RemoveObject tag.
Our last step before uploading our application to Google App Engine is to build and export for deployment. Right click on the project name in the left panel and select Export. Choose Flex Builder folder -> Release Build -> Next. In the Export to folder section browse to your war for the project. We want to build our Flex application to this folder so that the App Engine plug-in will deploy this code to App Engine along with our Java code.
Our last step it is to create a new App Engine application and upload our code to Google's servers. There is detailed help for uploading with the Eclipse plug-in here.