Flex Pasta » Java

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.

Chart

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?

Cairngorm users know a chain event:  a way to execute, in order, multiple remote requests such as http, remote object, or web service calls.

 The Good

  • Executes multiple requests in order
  • Ability to use data returned from an earlier event on the chain to make a request for a subsequent event on the chain

The Bad

  • When events are chained that do not need to be in sequential order
  • When events are chained that do not need a previous result’s data

The Ugly

  • A chain event is a performance hit!  It makes one request, waits for the result, then makes the next, waits for the result, and so on.  It’s bad for the end user to have to wait for all these events to fire in order.  The problem is compounded when chain events are over used.
  • The code.  Using chain events with Cairngorm involves ugly code that makes bugs more likely.
  • Business logic use cases are needed in more numbers and are more difficult to design, implement, and maintain.  For example, what happens when a 5 chain event incurs a fault abnormally during event 3?  What happens when event 2 comes back with a result, but it is not in the format expected?  How does a support team troubleshoot a user’s problem when they’re failing on one part of a chained event?

One alternative option to a chain event is the Transfer Object Pattern.  Here are the goals of the Transfer Object Pattern:

  • Reduce high method invokations by encapsulating the calls in a generic object.
  • Reduce the chatiness of the application by eliminating requests across the network

Example:  From Chain Event to Transfer Object Pattern

The Chained Event:

Event 1: Call a remote Java method: public Customer doLogin(String username, String password) - It takes a user name and password and returns me a Customer object.

Event 2: Given the Customer object from event 1, I now use it to call public List<Accounts> getCustomerAccounts(Customer customer) -  This method takes the customer object I got from Event 1, and then retrieves the customer’s list of Account objects.

The Transfer Object Event:

The transfer object pattern has only one event.  It will call a remote Java method called public LoginResult doLogin(LoginRequest loginRequest)

LoginRequest would look something like this:
public class LoginRequest
{
private String username;
private String password;
}
…getters and setters….

The LoginResult would look something like this:
public class LoginResult
{
private Customer customer;
private List<Account> accountList;
}
…getters and setters…

The workload is now away from the Flex chained event and put on Java.  In this case, I only have one request/response at login, rather than two.  This improves performance and wait time for the end user.  It also makes my Flex code less cluttered(without all those “what ifs” for the chained event).  The Java code needs some modifications but is still simple and easy to maintain.  Adding on is also very easy.  Say I also want to return a list of statement objects at login.  I simply add the new list object to the LoginResult class without having to add the plumbing for more remote calls.  There is minimal work in Flex to get the data I need and without the clutter of adding on to a chain event.

The Transfer Object pattern is an example of another approach to a chain event.  It may not work in all cases, but is worth considering!

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.