Flex Pasta » Flex 3

Adobe opened source the Flex SDK since the 3.x release. Not only does this gives Flex developers the ability to see the source code and understand how the SDK works, but it also allows the community to provide bug fixes and enhancements. Adobe has said publicly that they would like to create sub projects from the Flex SDK that the community can contribute. The open source of the Flex SDK gives the community the fire power to submit code bug fixes. Developers should try and fix bugs in the SDK when they come across them. The following tutorial shows how to set up a Flex Project and have it build against the Flex SDK source code. These steps will allow a developer to make changes to the Flex SDK and build the project to see the changes.

1. Download and install Tortoise SVN. Tortoise is an open source subversion client that is needed to download the Flex SDK from the adobe repository.
2. Right click on a folder and click Checkout from the context menu.
3. The Toroise SVN screen should appear. Enter the URL of the repository. At the time of this being published, the URL is http://opensource.adobe.com/svn/opensource/flex/sdk/trunk.
4. Once the download of the source has completed(it takes a while!), open Eclipse.
5. Import the framework project. File > Import.
6. Press Next. Find the root directory where trunk is checked out, and enter this plus development\eclipse in the Select root directory box. This will show all of the Flex SDK projects.
7. Leave all of the projects selected and click finish.
8. Setup a linked resource variable in eclipse called FLEX_SDK and which points to the root directory of the SDK. Window > Preferences > General > Workspace > Linked Resources.
9. Enter FLEX_SDK as the name and the location where the Flex SDK is checked out. Press OK and then close the preferences window.
10. Right now the focus will be on only building the framework project. Go ahead and close the other ones. Right click on them and select close project.
11. At this point there should be no errors or warnings in the problems window. A clean might be required. Select Window > Clean and select the framework project.
12. Create a blank Flex Project. File > New Project > New Flex Project
13. Enter a project name and press Finish.
14. Now the FlexSDKTest project is setup, however, it is running against the compiled and installed version of the Flex SDK. To be able to make changes to the SDK source, the FlexSDKTest project must use the framework library project as its parent. To do this, right click on the FlexSDKTest Project and select properties, then select Flex Build Path > Library path tab.
15. Select the Flex 3 library and remove it. Click Add Project and select the framework project from the list. 16. Press the Add SWC button. Find the playerglobal.swc for the version using. The path usually is ${FLEX_SDK}/frameworks/libs/player/9/playerglobal.swc.
17. Press the OK button to close the properties window. Everything is set up to run code directly against the framework source. Just to make sure, run a simple test. Add a button to the FlexSDKTest application.
18. Open Button.as in the framework project. In the set label function, add code to the label’s value that modifies it: value = ‘I can change the SDK source code! BOOYAH!!!!’;
19. Save the file and build the projects. Run the FlexSDKTest application. The button’s label should read “I can change the SDK source code! BOOYAH!!!!”.

That’s it!! It’s off to the races for submitting enhancements and bug fixes to the Flex SDK repository. The flex bug tracking database can be found at http://bugs.adobe.com/flex/

mx:DataGrid and mx:DataGridColumn can sometimes pack powerfully picky precision.  Anyone who has ever tried using the word wrap feature knows just the pain.  Take a look at the following code and resulting output.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical” creationComplete=”cc()”>

<mx:Script>

<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]public var arrayColl:ArrayCollection = new ArrayCollection();
private function cc():void
{
arrayColl.addItem([“Poem 1″, “Sally sells seashells by the seashore.  She sells seashells on the seashell shore.  The seashells she sells are seashore shells, Of that I’m sure. She hopes she will sell all her seashells soon. If neither he sells seashells Nor she sells seashells, Who shall sell seashells? Shall seashells be sold?”]);
arrayColl.addItem([“Poem 2″, “Shelly sells seashells by the seashore.  She sells seashells on the seashell shore.  The seashells she sells are seashore shells”
]);
}
]]>

</mx:Script>
<mx:DataGrid dataProvider=”{arrayColl}” width=”500″ height=”200″ wordWrap=”true” fontFamily=”Verdana” fontSize=”12″/>

</mx:Application>

Despite specifying wordWrap=”true”, my text doesn’t wrap!  After searching through the mx:DataGrid and mx:DataGridColumn properties, I came across
variableRowHeight=true.  Within seconds, text was wrapping nicely.  How great would it be if this was mentioned in the wordWrap asdoc?  Here is the resulting output:

With the explosion of Flex leading the way in web 2.0, I often wonder, 5 years from now, will Flex dominate the RIA landscape?

What Flex has going for it:

  • A great looking UI out of the box
  • Adobe: A big corporate name investing money in its promotion. While free ajax frameworks are great as well, there are a lot of options out there that clutter the picture of a front runner against Flex.
  • BlazeDS - AMF. It is proven to be the fastest web 2.0 transfer and rendering framework out. It also makes coding easy for Java developers.
  • It is open source! Yes, Flex Builder does cost money, but for corporations wanting an enterprise RIA, this is nothing. The important thing is that the code is available for the community to improve.
Pinky & The Brain

Where Flex struggles:

  • Marketing: Nobody knows about Flex! While this is improving, many people, developers, managers, CEOs, etc have never heard of it! If they hear about it, they would probably be using it. Adobe should run a Super Bowl commercial. Flex doesn’t apply to the general audience, but hey, GoDaddy has Danica Patrick doing Super Bowl Ads. If the general audience registers websites then their next step would be making the website. Maybe Pinky and The Brain could be the spokesmice?
  • The Google Effect. It is why this blog and every other blog is NOT written in Flex. Google and other search engines can’t read them! They can’t read the text or the cool drag and drop features they might do. AJAX sites are limited web crawlers as well, but not as much as Flex.

Great Points, but I’m a little scared by this Pinky and the Brain stuff. What is it?

Pinky and the Brain is an emmy winning cartoon with the following theme:

Pinky: “Gee Brain, what do you want to do tonight?”
The Brain: “The same thing we do every night, Pinky- try to take over the world.”

Check out the intro on youtube:

Like many Flex/Java applications, they are started from scratch and use java 1.5 or greater. I was surprised that there were no annotations for BlazeDS to make it easier to mark up remote objects and services. Being that BlazeDS is open source, I thought it would be valuable to use annotated classes for remote objects. I created a custom BeanProxy(a class that defines what properties go from Java to actionscript, and vice versa). Note: I have submitted the code to Adobe for acceptance into the BlazeDS code base. I plan on expanding the code further, and I hope others will contribute as well. The link to the enhancement request can be found here: Please vote for the issue! Inclusion into the BlazeDS code base will help make it maintainable in the long run.

Now for a step by step guide about the annotations, and how to use them. First, I will point out that somethings I have done in the code are not ideal but are necessary to be compatible will BlazeDS which is primarily a java 1.4 app.

  1. Download the Jar and source: BlazeDS Annotations Jar and Source Files
  2. Take one of your domain classes/remote objects and implement IAnnotatedProxy and mark the class with the @FlexClass Annotation. The IAnnotatedProxy is a marker interface and its existence is simply to tell BlazeDS it has annotatations and should use the AnnotatedBeanProxy instead of the normal BeanProxy.
  3. Add this one liner to the servlet init of your webapp: PropertyProxyRegistry.getRegistry().register(IAnnotatedProxy.class, new AnnotatedBeanProxy());
  4. Begin adding @FlexField annotations to your “getter” methods on your remote objects. As I will explain in more detail, I have broken up what the @FlexField annotation does into two parts:
    1. Annotations that manipulate whether a field is included in BlazeDS AMF serialization.
      1. @FlexField( fieldType = FlexFieldType.ReadWrite) - Default option. Acts just like domain objects do today with BlazeDS, it reads a field if and only if both a matching getter and setter exist.
      2. @FlexField( fieldType = FlexFieldType.Exclude) - Does not include this field in AMF serialization even though a matching getter and setter may exist. Benefits are 1) Performance, 2) Security, and 3) Unnecessary Clutter. Keep in mind though, if you have a field populated with data going from Java to Flex, when it comes back from Flex to Java, the fields you excluded will be null.
      3. @FlexField( fieldType = FlexFieldType.Transient) - Include this field in serialization from Java to Flex if it has a “getter” method, but it does not require a matching “setter” method. The primary benefit here is I may have a field such as a calculation that doesn’t have a “setter” because it is a calculation. Yet I want the field to be translated over to the flex front end because I will use it for display only purposes to the end user.
    2. Annotations that manipulate data during serialization primarily for security purposes. Note, for use of the following annotations, remote objects on both the flex and Java side MUST extend mx.rpc.remoting.JavaObject. Before using the following annotations, make sure to fully understand what they are doing.
      1. @FlexField( fieldType = FlexFieldType.ReadOnly) - This field is included in serialization to and from Java and Flex. However, when data is coming from Flex into Java, encoded data in the JavaObject’s key determines the value of the field. Example: An account number field with the value of 999 is passed from Java to Flex. The account number is encoded in the JavaObject’s “key” field. Now the user goes to save their account settings, so data is sent back from Flex to Java. If the account number is anything other than “999″, a (runtime) ReadOnlyException is thrown. The primary benefit here is security. I want the user to be able and see, but not edit the account number on the Flex side. There may be other fields in the domain class they can edit, but this field is off limits.
      2. @FlexField( fieldType = FlexFieldType.CreateOnly) - This field is included in serialization to and from Java and Flex, and is almost identical to the ReadOnly Annotation. The difference here is that, if the field has no value(is null) when it goes from Java to Flex, the field can be created on the flex side and sent back. An example here is a foreign fey field. I have a customer creating an order. The order contains a customer id field. I want to let the customer create an order with their customer id for the first time, but after that, want to make sure that data is not tampered with later.

Web 2.0 and Security

With Web 2.0, application security is a big concern. Data is much more exposed to the curious eyes of an end user (especially primary and foreign keys) than in a traditional web app. My post on BlazeDS and Security goes into more detail. One of the driving forces for these annotations is for object security.

Annotations: To be Continued….

The annotations here create a starting point for use in BlazeDS. I hope the community will build on these annotations. The next goal is to tackle securing remote service methods using annotations. Feel free to post ways you would like to see annotations used with BlazeDS in the future.

A common hurdle a developer may face is dealing with exceptions in BlazeDS. When an exception is thrown in Java, how do we handle this in flex? Here is a simple and flexible approach inspired by Scott Morgan.

1. Create a Java Class that extends RuntimeException.

package com.flexpasta.exception;
public class FlexException extends RuntimeException
{
public FlexException(String message)
{
super(message);
}
}

2. Create a matching flex class called FlexException, and put the usual RemoteObject tag in their so BlazeDS will know what to look for. Also remember in actionscript, each object must be instantiated at least once, so be sure to do that somewhere with FlexException.

3. In Java, whenever there is a known exception, or some error where the end user needs to be shown a message, throw a FlexException and pass in the message the user should see in the constructor. Let’s say the user just entered an invalid password. throw new FlexException(”Wrong Password Entered, Please Try Again.”);

4. Flex receives the Exception in the form of a fault. In the fault handler, you call this method:

/**
* Parse the incoming fault for an FlexException class. If the exception class is found and it has a matching actionscript class,
* show an alert to the user with the correspoding messages. If we don't recognize the Exception type, show a generic error.
*
* @param fault
*
*/
public static function handleException(fault:Fault): void
{
var msg : String = fault.faultString;
var clazz : Class = getExceptionClass(fault);
var instance : Error = null;
if (clazz != null)
{
Alert.show(msg,'Error');
}
else
{
Alert.show('Error! Please try again. If this issue persists, contact the system administrator');
}
}
/**
*
* Return the Class corresponding to the exception by parsing the fault string. If a corresponding actionscript error class is found,
* return it. Otherwise, return null.
*
* @return
*
*/
public static function getExceptionClass(fault:Fault) : Class
{
var clazz:Class = null;
var index:int = myFault.faultString.indexOf("FlexException");
if (index != -1)
{
var cname:String = myFault.faultString.substr(0,index-1);
try
{
clazz = getDefinitionByName("com.flexpasta.FlexException") as Class;
}
catch (e:ReferenceError)
{}
}
return clazz;
}

When we see a Flex Exception, we show the message to the end user. If for some reason we have an unplanned error in Java, like NullPointerException, a message is displayed to the end user: ‘Error! Please try again. If this issue persists, contact the system administrator’. A generic message to handle all unplanned errors.

5. What if the app needs to DO something special with certain Java Exceptions? Say the user has just entered 3 password attempts, and I want to be able to handle locking their account through an exception.

  • Create a new class in Java called UserLockedException that extends FlexException
  • Create a matching actionscript UserLockedException.
  • Add code in the flex fault handler to look for a UserLockedException, when the fault handler sees it, it can still display a message to the end user, but now flex knows to take a different code path to complete the process.
  • Conclusion

    It is pretty simple with BlazeDS to create a base exception handling system. Depending on project needs, this approach can easily be modified or enhanced. In flex, it is important to setup a strong exception handling that accounts for both planned and unplanned exceptions.