Flex Pasta » BlazeDS
Time travel between Flex, BlazeDS, and Java can be quite complicated to keep the three correctly in sync. Time travel, aka remote objects that carry date members, can mean different things to each piece of software. Java is very time zone aware, where as Flex is very time zone unaware. Since time in Java, BlazeDS, and Flex is defined in milliseconds since 1970, it can mean translation via BlazeDS can result in inconsistencies. How can this be?
Java
When it comes to time zones and daylight savings time, Java is very smart. It uses the Olson Database to determine how to translate a time in milliseconds since 1970 into an actual date/time based on the current timezone. The Olson Database knows when daylight savings time started and ended in each time zone each year. If you remember, prior to 2007, daylight savings time in the United States started the first weekend in April and ended the last weekend in October. But, it an effort to be more energy conscious, the government changed it to the second weekend of March through the first weekend in November. Java knows about daylight savings time and time zones as they existed in the past. Therefore, milliseconds since 1970 for a date of March 15th, 2006 in Java maybe different than on another platform.
BlazeDS
BlazeDS(and the Flex RPC library) translate time via AMF between Flex and Java. It knows nothing about time zones or daylight savings time. When sending a remote object that contains a date, it will be converted to date.getTime() - milliseconds since 1970. BlazeDS is always translating dates in the present and has no understanding of the client and server’s time awareness.
Flex
Flex only knows about daylight savings time now. Meaning, Flex will think March 15th, 2006 was during daylight savings time. But in 2006, daylight savings time didn’t start until April so Java will have a different answer than Flex to milliseconds since 1970? To be fair, it is not Flex or Flash that aren’t time zone savy. It is the user’s browser and computer that are ultimately at fault. The flash player will just pull the information from them. Imagine if a user enters a date/time today(during daylight savings time). At some point in the future, the government changes daylight savings time to start tomorrow. After the change occurs, the date the user entered will be correct in Java(because Java knows of daylight savings time in the past), but will be one hour off when displayed in Flex.
Creating an identical date/time object in both Flex and Java can cause different results for milliseconds since 1970. Take for example a user entering a birth date on a Flex form as March 15th, 2006 and another user entering a birth date as March 15th, 2009. The following screen shots show a simple Flex app with a date chooser and a label showing the time in milliseconds since 1970.
When the user selects March 15, 2009, the date is correctly translated to Java via BlazeDS as March 15th, 2009. Notice that Java says EDT(Eastern Daylight Time).
Now look at the same test for March 15, 2006.
Notice for the March 15th, 2006 date translation is incorrect. The date given to us via BlazeDS will actually be on March 14th at 11pm. Java correctly identifies the time zone EST(Eastern Standard Time). Java is correct. Back in 2006, March 15th was during eastern standard time. Because this date today is in eastern daylight time, Flex incorrectly reports milliseconds since 1970 to a number off by one hour.
Now the incorrect birth date is put in the database as March 14th!! Want to run a query to find all people born on March 15th, 2006? That could be a problem. There are several ways to solve this problem. One might be creating a JustADate class that has year, month, day fields on it so BlazeDS will send it without using getTime(). Another option might be sending date only fields as strings to avoid the getTime() translation. When working with dates in Flex, BlazeDS, and Java, be sure to consider time travel and its inconsistencies!
“Once confined to fantasy and science fiction, time travel is now simply an engineering problem.” -Michio Kaku
It has been about a year now since Adobe announced it was open sourcing the Flex SDK, BlazeDS, and the Flex Compiler. Today on my way home, I started thinking about improvements to the Flex Open Source Adobe that I would like to see in the future.
5. Upgrade LCDS/BlazeDS to Java 5.
I am not sure the reasoning for having BlazeDS written in Java 1.4. Most projects using Flex are going to use Java 1.5 since they are most likely newer software. If for whatever reason, BlazeDS to Java 5 is not viable, at least create a separate Java 5 project that extends the BlazeDS code base. This project could use features of Java 5 to give developers more tools. In particular, annotations with remote objects would be a huge advantage for developers. Bean property configuration, service method security, better enum handling, code generator support, etc would all be great.
4. Bring the Flex Compiler Source Code out from the shadows
After attending MAX last month, I heard little about improvements to the Flex Compiler for Gumbo. I guess the compiler isn’t the sexy part of Flex so maybe that is why. But the compiler is just as important as the Flex SDK itself, so I would love to understand how it works. I think the community would benefit with more exposure to the compiler code base.
3. Make it easier to set up the Flex SDK, BlazeDS, and the Flex Compiler for local builds
The most looked at code base of the three components is probably the Flex SDK, just because we can hit F3 in eclipse and go look at the source code. However, how many people out there(other than Adobe employees) know how to check out the source code for the Flex SDK, BlazeDS, and the Flex Compiler and then be able to make changes to the code? I have been able to do it for the Flex SDK and BlazeDS, but it took some time(I also don’t think my config was ideal). I spent a couple of hours trying to figure out the Flex Compiler with no luck. I am hopefull for a little documentation for those of us out on an island trying to set it up.
2. Improve the ability to run different versions of the Flex SDK
If you go out and download Flex Eclipse plug-in site today, you will probably get Flex version 3.2. The rest of the development team might be using another version; say version 3.0 on the project. Figuring it might be a good idea to have the same version of Flex as your coworkers, you visit opensource.adobe.com to download version 3.0. The nice interface in FlexBuilder lets you have multiple Flex SDK’s installed and you can easily flip the compiler between different versions of the SDK. One problem: Charts. When you download the plugin, you get the charts bundled with the source code, but when you download releases from the open source page, charts are left off(I’m not sure the reason). This means a project using charts won’t compile for you without some hacking to get it to work.
1. Avoid using mx_internal/private in the Flex SDK
There are important instances where the private keyword is usefull(when I don’t want a subclass to override it or even be able to call it). However, and I admit to doing this as well, we tend to use the private keyword by default when we don’t want a method to be public. The protected keyword would be a much better option for the majority of methods in the Flex SDK. I have found it difficult at times to extend Flex components and even BlazeDS code because the methods are private or mx_internal. Maybe it was the intent of the authors to keep these methods private to avoid future upgrade hassles, but it can be problamtic to extend them. My latest example of one such problem involves creating a ColumnChart. I created the chart and had a ColumnSeries. The chart was simple and I set the properties labelAlign=”center” labelPosition=”outside”. I was wanting to center the labels at the top of the bars on the outside.
As you can see in the picture, the labels are left aligned. The as-doc states that labels on the outside can only be left aligned. I want to try and extend column series to get the labels in the middle. I find the method:
private function renderExternalLabels
I can’t extend it since it’s private. Ok, so I find where renderExternalLabels method is called.
mx_internal function updateLabels()
This goes on for four or five methods before there is one that can be extended. The point is that marking methods protected more aggressively can help everyone out who is trying to extend these components.
Those are my top five wishes for Flex Open Source. What are your wishes?
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.
- Download the Jar and source: BlazeDS Annotations Jar and Source Files
- 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.
- Add this one liner to the servlet init of your webapp:
PropertyProxyRegistry.getRegistry().register(IAnnotatedProxy.class, new AnnotatedBeanProxy()); - 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:
- Annotations that manipulate whether a field is included in BlazeDS AMF serialization.
- @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.
- @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.
- @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.
- 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.
- @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.
- @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.
- Annotations that manipulate whether a field is included in BlazeDS AMF serialization.
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.
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.
As first discussed in a previous post, “The Pros and Cons of Cairngorm“, I noted the need for a more lightweight framework for developing in Flex and Air. I am releasing version 1.0 of The Penne Framework, a simplified Flex and Air framework, as a second option to the popular Cairngorm Framework. This page has the Penne base code, and a java/flex example application using Penne(called the Italian Store) with remote objects. I have created a diagram which summarizes how Penne differs from Cairngorm.
About the Diagram
Let’s discuss the command class in Cairngorm, because this is the meat of the difference between Cairngorm and Penne. In Cairngorm, I will have one command class for a type of event. For example, I might have a remote service that returns a list of customers. This would have one command class. Then I could have another command class for getting all of the customer orders. In Penne, there is one request and result class for both of these remote calls. The request would have 2 methods in this case:
1: getAllCustomers(),
2: getAllCustomerOrders().
The result class would have
1: getAllCustomers(custList:ArrayCollection),
2: getAllCustomerOrders(orderList:ArrayCollection).
In a large project, the number of classes to create in Cairngorm would be drastically higher than Penne. There is a ton of overhead work to create in even a simple remote call in Cairngorm. With Penne, it is easy to grow your project without as much busy work.
Penne still keeps a strong structure for code layout. It is easier for a developer to see what is happening. Instead of looking at an event that is mapped to a command, which is mapped to a delegate, which calls an external service, in Penne I just call the method directly from a view class. It is very clear the remote service I am calling and from where. If I use BlazeDS and remote objects, my java remote methods can directly matchup to my flex request/response classes. There is a huge reduction in steps to figure out a path to a bug with Penne.
Hang on a Minute, How can Penne just delete all those event classes?? How will Penne ever have code reuse??
Penne is not getting rid of event classes. They are just not part of the framework. I am no longer required to create one for every type of remote service call. If creating a component such as a date chooser, or datagrid, then standard events are used to allow parent components to interact with them. Depending on the task, this kind of flexibility in a component is usually NOT needed. With Penne, call the request method directly from within a view component, and the result will cause bindings to fire changes back to the view components. Only use events for remote service calls when it is required for code reuse or the parent component needs to be aware, not for any other reason. I don’t create events because I have to anymore, I create them because they are NEEDED for something more than just kicking off a remote service call.
What about the model? Certainly Penne can’t get rid of that too?!?!
The model isn’t gone in Penne. Model variables still exist in the application. ModelLocators still exist just like in Cairngorm. Penne, however, offers a secondary option for remote services. Penne allows the developer to place “model” variables inside the response classes if desired. By placing the result directly in a variable in the same class, tt becomes much easier to see what binded variable goes with which remote service call. In my view layer I can just say PastaRemoteResult.getInstance.pastaTypes. In Cairngorm, if you opened up a model class and I said to someone, “Where does this model variable customerList get set?” They would probably start sweating and begin opening up all of the command classes trying to remember which one(s) it is. Then after it’s found a text search will be done to find the corresponding view where the CairngormEvent that goes with that command gets invoked. It is tough enough for the person who wrote the code to know where everything lives. Just wait until a new hire comes to code on the application has no idea what is going where. With Penne it is simple and structured. Everything is easy to find. If for some reason I need to control things like viewstacks and state management, I can still create a separate “model” class just for this, but all remote service calls’ model variables live in the response class.
Conclusion
The Penne Framework improves upon Cairngorm by simplifying it without sacrificing separation of duties. Penne drastically reduces the number of classes created in a large enterprise project. This reduces code complexity and readability. As an added benefit, Penne will reduce my pesky Flex Builder compile times!
Take a look at Penne, I welcome feedback and suggestions. The Design approach to flex can be improved. I hope Penne can start to accomplish this goal!
The Code
Here are the three zip files to download. One is the Penne.zip which includes the Penne source and Penne.swc. The other two are the Italian store. There are 3 projects in all which can be imported right into eclipse. I am using flex 3, java 1.5, with eclipse europa. The example Italian Store application is extremely simple. It shows how Penne can be used and offers comments as to how Penne works.





