Custom Getters and Flex Remoting "gotcha"

I ran into an interesting bug in the final stages of preparing the latest release of the Broadchoice Workspace application. I had added a custom getter to an ActionScript object to calculate a complex property, along these lines:


public function get complexProperty() : SomeType
{
    performSomeCalculation()
    return someComplicatedExpression
}
This allows you to say myObj.complexProperty without needing parentheses for a function call (and with a matching custom setter, you can assign to the pseudo-property as well). It's a nice feature of ActionScript that can really make your code much more readable.

The particular getter I added was only valid when certain data in the object was non-null. In all of the mainline use cases inside the application, this was fine. The complexProperty was only ever accessed after testing the condition on the object:


if ( myObject.someCondition )
{
    doStuffWith( myObject.complexProperty )
}
Yes, someCondition was a custom getter as well.

The bug I ran into was that sometimes remote calls involving this object silently failed. I didn't get a fault back. It was almost like the call just didn't happen. Puzzled, I fired up the Flex Debugger (which is absolutely awesome!) and traced through the code. No visible exceptions, no strange paths being executed in the code. More puzzled, I fired up JBoss in the Java Debugger under Eclipse and put a breakpoint inside the server method that was called. Strangely, the code ran without hitting the breakpoint! That showed that the call really was not happening for some reason.

Back in the Flex Debugger, I set a breakpoint just before the remote call and took a very close look at the object in the Variables panel when I hit the breakpoint. It showed the custom getter as a property on the object (as expected) but the value in the debugger showed an exception was thrown retrieving the property. Then it hit me: Flex Remoting tries to serialize the object by calling the getters and it was failing due to the exception - and silently swallowing the exception without telling me, and without executing the remote call!

I updated the getter to return a default value if the condition (myObject.someCondition) was false and, sure enough, the object serialized just fine and the remote call was successfully executed!

Moral of the story: if you add custom getters to ActionScript objects, make sure they cannot throw an exception when the object is in a state where you need to send it to the server using Flex Remoting!

Concurrency, BlazeDS, data-driven architecture, and Broadchoice Workspace

Broadchoice Workspace has a contact list on the right-hand side. In the launch release we're working on now, it shows everyone you're connected to through groups. Simple enough, right? A simple SQL query that joins you to groups, and groups to member, and there you go.

It's at this point working on a RIA becomes very different from working on a HTML application.

Here's a few of the more fun use cases to consider. They're fun brain-teasers for thinking about how to handle multiple clients running the application.

Concurrent Signup

  1. You're a member of the Acme, Inc. group. Workspace is running.
  2. The owner of the Acme, Inc. group starts the Workspace and adds Ferd McBurfle, a new hire from down in accounting.
  3. Ferd gets the invitation e-mail and signs up for the application, joining the Acme, Inc. group. He should now should up in your contact list. No user gesture should have to be taken on your part: no refresh, no waiting for a periodic refresh, etc.

People View in a Group

  1. After the prior case is complete, you decide to check out the "People" tab in "Acme, Inc." Right now it shows you, the owner, Ferd, and Lumpy McGiblet, the person Ferd just replaced
  2. While you're viewing the people tab, the owner removes Lumpy McGiblet.
  3. You're not in any common groups with Lumpy anymore, so Lump should disappear from your client's view of people. Again, no gesture should have to be required on your part.

Our Approach

I've really enjoyed working on problems like this on the Workspace. Our solution to most of these situations involves using server-side services that broadcast small DTOs to running clients via JMS, "pushed" through amf-polling. Many of these same concepts are possible in ColdFusion, as well.

If you'd like to hear more about this kind of work, feel free to stop any member of the ArgumentCollection at Adobe MAX next week!

Hibernate and Flex? Please, dev in "Debug"!

If you're using Hibernate as the ORM behind a Flex application, I highly recommend running BlazeDS (or LiveCycle, or ColdFusion) with its services-config set to log "Debug" level to the console.

Why?

Short version: you may run a lot of unintended SQL, sometimes with really weird consequences.

[More]

Behind The Curtain

As you may have guessed from the content of our earlier blog posts, we're working on an AIR application that involves some sort of real-time collaboration. As you may also have guessed from the slower flow of postings since mid-August, we've been very busy working on that application!

Broadchoice Workspace blogWe're finally ready to start showing the world what we're working on and to talk about the concepts and technologies behind it. We're also taking early signups for the forthcoming limited beta program. [You can download the public release from the main Broadchoice website]

This blog post contains the first public unveiling of the application and its capabilities. The fundamental concept of the application is to provide a central way to collaborate with your colleagues (or friends). All users have a personal workspace containing files they have uploaded, a blog, a GTD-style task manager and useful bookmarks they have found.

[More]

Flex (BlazeDS), JMS, and JBoss in a Nutshell

This morning, I published another tech doc for folks' use here at Broadchoice that was appropriate for sharing with the world. It describes how to configure a topic-style JMS destination within JBoss, connect a BlazeDS destination to it, and have a Flex consumer listen for messages from the BlazeDS destinatin (and therefore the JMS topic).

It's a Google doc, is available here:

Flex (BlazeDS), JMS, and JBoss in a Nutshell

AIR and Groovy via Spring

As a fun way to while away a Saturday evening, I decided to look at Joe's Behavioral Analytics backend code to see if I could create a Flex-based AIR application that talked to services written in Groovy. There's not really much documentation out there to help so it was a very hit and miss experience but eventually I had a simple AIR application making a RemoteObject call to a Groovy class and getting data back. I'm going to have to talk to Joe about cleaning up the installation I've ended up with but here are the highlights (and I'll blog more about this once I have all the pieces cleaned up):

  • JBoss 4.2.3 GA installed as a Server in Eclipse (using the Web Tool Platform JEE stuff)
  • Spring framework 2.5.5
  • A Spring-based Flex factory that allows Flex Remoting to talk to objects via Spring (author Jeff Vroom)
  • Groovy - set up per Joe's recent instructions
  • BlazeDS providing the Flex Remoting service
Create a Dynamic Web Project in Eclipse and then unzip BlazeDS into it (per the BlazeDS installation docs). Add Spring and the flex.samples.factories.SpringFactory Java class. Configure Flex Remoting according to Lin's instructions to add the Spring factory:

    <factories>
        <factory id="spring" class="flex.samples.factories.SpringFactory"/>
    </factories>
and the context loader:

    <!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <!-- load Spring's WebApplicationContext -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
and the destination for the RemoteObject:

<destination id="place">
        <properties>
            <factory>spring</factory>
            <source>placeholder</source>
        </properties>
</destination>

Create a Flex AIR project and define a RemoteObject that refers to the destination you just defined:


    <mx:RemoteObject id="bcp"
            destination="place"
            endpoint="http://127.0.0.1:8080/bcpbackend/messagebroker/amf"
            >

        <mx:method name="test" result="testResult(event)" fault="testFault(event)"/>
    </mx:RemoteObject>

Add the placeholder bean definition to your applicationContext.xml file:


    <bean id="placeholder" class="com.broadchoice.bcp.Placeholder"/>
com.broadchoice.bcp.Placeholder is a Groovy class that contains a test method (for testing it just takes a string and returns that string plus some additional text).

BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner