Skip to content

Archive for May 2009

17
May

(Ext.)Direct Miss

One of the biggest announcements from last month’s ExtJS Conference was the new Ext.Direct functionality in ExtJS 3.0. My criticism at the time was that there was a lot of smoke, but no fire. Almost every session mentioned it in some way or another, but they weren’t producing any enterprise-worthy server code showing how it is implemented.

Now, a month later, more details are starting to emerge, including implementations for various technologies. I sat down yesterday morning intending to take a look at the server side code in the Ext.Direct Pack; in particular the .NET and Java implementations. I was pretty disappointed with what I saw.

To understand my disappointment, you need to understand a bit of history around what Ext.Direct is attempting to do. Ext.Direct is going to be an RPC layer that exposes stub objects on the client JavaScript side that remotes the method calls to the server using JSON (or POST parameters). The protocol definition is designed to be technology-agnostic and easy to implement. In implementation, it would be the near-equivalent of DWR, except it would also run on PHP, C#, Ruby, etc…

Since I’m familiar with CORBA, RMI, SOAP and WCF, I approached Ext.Direct with a more critical eye. The biggest glaring hole in Ext.Direct is the parameter passing. Let’s take a look at a couple examples to demonstrate the problem. All the examples will assume a Java backend, and the service we’ll expose is the PersonService. I’ll work from the interface, since we don’t care about the implementation details:

public interface PersonService {
 
}

Easy

We’ll add a method to PersonService to demonstrate the simplest scenario:

public int getPersonCount();

The payload from Ext.Direct would look something like this:

{ "action":"PersonService",
   "method":"getPersonCount",
   "data":[],
   "type":"rpc",
   "tid":2}

This is the absolute easiest method to deal with. The operation takes no parameters, and the return value is a primitive. Ext.Direct can deal with this easily, but so could any AJAX library, so no secret sauce here.

Object

One of the key advantages to an RPC protocol is the ability to pass Objects. Well complicate things a bit by adding the following method to the PersonService:

public Person getPerson(int id);

For our example, we’ll assume the Person class looks like this. I’m not including setters/getters to try and keep it short:

public class Person {
  private int id;
  private String name;
  private int age;
  private Date birthDate;
}

In the method I added above, the JSON payload from Ext.Direct stays pretty simple:

{ "action":"PersonService",
   "method":"getPerson",
   "data":[1],
   "type":"rpc",
   "tid":2}

This should return the Person with the ID of 1, and depends on the server code to correctly serialize the Person object to JSON.

Harder

Now let’s make things painful. I’m going to include a method to add a Person.

public void addPerson(Person person);

This is where the wheels fly off of Ext.Direct. Since the protocol specifies the data element as an array, I’m not clear on how Ext.Direct would deal with this from the client side. Every example so far works with primitives as parameters, so I haven’t determined what it would do with a Person.

Ext.Direct would be much happier if I defined the addPerson method like this:

public void addPerson(int id, String name,int age, Date birthdate);

Then, the JSON payload would look like this:

{ "action":"PersonService",
   "method":"addPerson",
   "data":[1,"John Doe", 25, "Sun May 01 1985 00:00:00 GMT-0500 (Central Daylight Time)"],
   "type":"rpc",
   "tid":3}

Even in this “happy path” scenario for dealing with an object, your server-side implementation would need to be able to correctly deserialize the stringified javascript date object, which is not anything the current implementations handle.

The protocol specification states that the data element can also be a JSON object with named parameters, but it is not supported in the first implementation. This is going to be absolutely critical if Ext.Direct is going to evolve into a real RPC protocol. For example, using a JSON object for the data element in the above example would result in a JSON payload like this:

{ "action":"PersonService",
   "method":"addPerson",
   "data": {id: 1,
           name: "John Doe", 
           age: 25, 
           birthdate: "Sun May 01 1985 00:00:00 GMT-0500 (Central Daylight Time)"},
   "type":"rpc",
   "tid":3}

This would at least allow the server code a means to try and instantiate an instance of the Person object, as long as the server code is implemented in a language that allows for reflection of the Object.

My grief with Ext.Direct is that correctly implementing the server-side code to support the specification is a non-trivial endeavor. One big piece missing is the metadata. In other RPC mechanisms, there is strongly-typed metadata which can be used to create the stubs. For example, CORBA has IDL and SOAP has WSDL.

Ext.Direct is missing a metadata layer to facilitate the passing of Object values. It is going to be difficult to implement a complete server-side stack to handle the permutations that will arise. Developers will either need to dumb-down the exposed services to handle the limitations of Ext.Direct, or else they will end up doing a lot of custom work on top of the server side implementation to handle the type coercion.

I’m still not convinced Ext.Direct is the right path for ExtJS to be barking down. There are already established, tested protocols for handling RPC via JavaScript (DRW, WCF), and ExtJS already works quite well with basic AJAX over the HTTP protocol. Ext.Direct is adding a level of complexity to ExtJS which could easily turn into a rabbit hole that sucks up all their time. I would prefer they focus their precious development hours on the client library and leave the communication layers decisions to us. RPC is a complicated problem with a lot of history around it, and there is no reason for them to try and invent a new wheel in this space.

9
May

Flexible Spring

As I mentioned in my prior post, I’ve been going through the great Flex in a Week from Adobe. I finally hit Day 3 and had a need to play with BlazeDS for the second lesson. Being a fan of the Spring Framework, I decided to use the recently released Spring Blaze DS Integration 1.0rc1 (Spring-Flex). This ended up turning in to a bigger beatdown than I expected, for several reasons.

I really wanted to use the Spring-Flex integration because I like the annotation-driven dependency injection option that Spring brings to the table. Unfortunately, I could not find a single comprehensive document or example showing how to setup a project from end-to-end using Flex and Spring-Flex. I started with my Spring template project, adding in the BlazeDS dependencies and configuration. I then stripped out the stuff I didn’t care about for this example. Then I went digging through the various reference guides and blog posts trying to figure out the correct configuration I needed on both the Java and Flex side.

After about three days of hair pulling, the pieces finally started to fall in to place. Once I understood the configuration, it became a breeze to configure services to be exposed by Spring-Flex and to call those services from Flex via a RemoteObject. I’ve linked the complete Java project and Flex project archive below:

Spring-Flex Project

Flexbuilder Project Archive

There is a README.txt file in the root of the Java project directory that walks through the setup. This project is configured to talk to a MySQL database using an iBatis DAO layer and includes the setup scripts, all run from Ant. The build file also makes use of Ivy to grab dependencies, thus reducing the number of jars I have to include.

The Flex project is configured to talk to the exposed employeeService on localhost, so you’ll need to change the configuration of the RemoteObject if you want to point to a different destination.

Here are some of my lessons learned that will hopefully help others:

#1: Life is easier if you keep BlazeDS’s services-config.xml file in the default location: WEB-INF/flex/services-config.xml. The version of this file that comes with the BlazeDS turnkey download has a small problem. It does not specify default channels, which is what FlexBuilder will use to figure out what is going on. Look at the version I have in the Java file and notice at the top:

<services>
  <default-channels>
    <channel ref="my-amf" />
  </default-channels>
</services>

You’ll want this in your services-config.xml file if you plan on specifying an application server in FlexBuilder.

#2: And on the subject of application servers, you actually don’t even need to specify the server technology. I built my solution as a standalone Flex project with a standalone Java project and had the two talking together without a problem.

The secret to making it work is in how you configure the RemoteObject in FlexBuilder. Here is the configuration for my RemoteObject:

<mx:RemoteObject id="employeeRO" 
  destination="employeeService" 
  showBusyCursor="true"
  fault="handleFault(event)">
  <mx:channelSet>
    <mx:ChannelSet>
      <mx:AMFChannel id="amf" uri="http://localhost:8080/flex/messagebroker/amf"/>
    </mx:ChannelSet>
  </mx:channelSet>
  <mx:method name="getEmployees" result="allEmployeesHandler(event)"/>
  <mx:method name="doCreate" result="employeeHandler(event)"/>
  <mx:method name="doUpdate" result="employeeHandler(event)"/>
  <mx:method name="doDelete" result="employeeDeleteHandler(event)"/>
</mx:RemoteObject>

Specifying the ChannelSet enables you to take control of where the RemoteObject is binding to instead of relying of FlexBuilder magic. Just change the URI to point to the correct location.

There is one little catch. You need to set the FlexBuilder build output directory to Tomcat’s webapps/flex directory (after you have deployed the war file), or you’ll get a security exception about breaking out of the sandbox. I’m guessing that the flex file is looking for the services-config.xml file to figure out what it is supposed to do, and if it is not in the correct directory relative to the SWF file, your application will barf. So deploy the flex.war file from the Java project first, then play with the flex half of it.

#3: Once you have the dependencies sorted out, configuring the Flex broker is literally a one-line configuration option. Check out web/WEB-INF/flexDispatch-servlet.xml in the Java project and notice this line:

<flex:message-broker />

That’s all you need. Really. This one line of config uses “sensible defaults” to initialize BlazeDS. It will read services-config.xml from the default location (see tip #1) and setup the endpoints for you based on the configuration.

#4: I’m a fan of annotation-driven configuration for Spring, and Spring-Flex does not disappoint. Here is the implementation of the EmployeeService class:

@Service("employeeService")
@RemotingDestination
public class EmployeeServiceImpl implements EmployeeService {
 
    @Autowired
    private EmployeeDao employeeDao;
 
    @RemotingInclude
    public List<Employee> getEmployees() {
        return employeeDao.getEmployees();
    }
 
    @RemotingInclude
    public Employee getEmployee(String id) {
        return employeeDao.getEmployee(id);
    }
 
    @RemotingInclude
    public List<Employee> getEmployeesByDepartment(String department) {
        return employeeDao.getEmployeesByDepartment(department);
    }
 
    @RemotingInclude
    public void doCreate(Employee employee) {
        employeeDao.createEmployee(employee);
    }
 
    @RemotingInclude
    public void doUpdate(Employee employee) {
        employeeDao.updateEmployee(employee);
    }
 
    @RemotingInclude
    public void doDelete(Employee employee) {
        employeeDao.deleteEmployee( employee.getId() );
    }
}

The top @RemotingDestination tells Spring-Flex this is a service that is going to be exposed via BlazeDS. You can provide an optional parameter specifying which channels to use, if you have several configured. Then, each method you want to expose is annotated with the @RemotingInclude annotation. Methods that should not be exposed can be annotated with the @RemotingExclude annotation.

So if you’re following along with Flex in a Week, or have just been trying to get Spring-Flex up and talking to a Flex application, give the demo a try and look over the source code. This corresponds to the second video of Flex in a Week, Day 3. I wish I would have known some of these things starting out, so hopefully I can save other people some time.

5
May

Flex in a Week

One of my unexpected take-aways from the ExtJS conference last month was that I need to start looking at Flex again. This isn’t necessarily for the Flex framework itself, but because of AIR. I’ve started to see a lot more AIR applications popping up, and my Twitter client (Twhirl) is even AIR based. ExtJS with AIR makes for an extremely powerful combination.

So to build a foundation for AIR, I decided to learn Flex. After a strong year of JavaScript, Flex starts to make a lot more sense from a syntax standpoint. And ironically, the best way I’ve found to learn Flex is free: Flex in a Week.

Adobe has produced a truly outstanding series of video training classes for Flex. Although it is structured as five days worth of materials, I’m only getting through half a course each day due to quiet time constraints with a two-year old in the house. I have been very impressed with the quality and level of detail. The videos aren’t full of fluff and get quickly to code. There are exercises interspersed with the training videos, but I’ve passed over them, opting instead to follow along with the videos.

The only downfall to my choice to follow the videos instead of the exercises is that Adobe didn’t make it easy to find some of the supporting pieces you need to follow the videos. For example, there is an XML data file called employees.xml used for a lot of the code in the videos that is nowhere to be found. Ultimately, I found a CSV version of the data file in an AIR Sample, along with the images used for building the employee directory application.

In the interest of helping out others who start on Flex in a Week, here are the supporting files necessary for following along with the code. I’ve only finished the second day, so I’ll try and add any additional parts I find missing.

  • employees.xml – the XML data file with the employee information (right-click to save it)
  • headshot images – the thumbnail images for the directory, both normal and small sized

I’m hoping to finish up the tutorial this week and jump into more complex things with Flex. I’ve been very impressed so far, although not enough to eat crow yet on my negativity towards Flash in general.

What about Flex books? I picked up Programming Flex 3: The Comprehensive Guide to Creating Rich Internet Applications with Adobe Flex and it has been a total disappointment. The book is very poorly structured and it jumps all over the place without a coherent plan. It swings between excessive detail of the Flash engine, followed by trivial, poorly explained examples of the Flex widgets. I may find value in it later as a reference, but am dumping it for now.

I did pick up another book that I really like a lot: Learning Flex 3: Getting up to Speed with Rich Internet Applications (Adobe Developer Library). This one is well structured and gets to the things I’m interested in, not the nitty-gritty details of the Flash player. I would recommend this one for anyone who is at a similar point in their Flex learning experience.