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!

Recentering Flex Alerts on Application Resize

I recently had a bit of a challenge to tackle with our Workspace application and thought I would share some details. As many of you probably know from trying out the application, Workspace is meant to be kept open to fully capitalize on it's collaborative features. The application provides a lot of behavior that is based on real-time communication, such as content being updated or users being added to Spaces. All of this works quite well right now, and we are already working on more features as well as some simplification of the interface to allow new users to get up and running more quickly.

We have, however, noticed a small but annoying glitch that happens as a result of certain real-time notifications that trigger Flex Alerts. Namely, if the application is minimized and an Alert is triggered, when the application is maximized, the Alert does not appear in the proper place. Normally, an Alert will automatically center itself in the window where it appears. But if the application is minimized, this centering does not happen. So when the app is maximized again, the modal Alert is located far in the upper left corner of the screen, with most of it's content off the screen completely. Users had a hard time figuring out what was happening, and since the Alert is modal, the app can't be used until the Alert is closed. This resulted in a lot of confused users!

I set out to solve this issue by triggering a re-centering of any open Alerts when the application is resized, but this turned out to be more difficult than it first appears. At first, this seemed like it should be fairly simple: the Flex SystemManager object contains a property called popUpChildren, which references any PopUp objects that are open. So no problem, right? Just loop over this list and recenter them.

In a frustrating turn of events, Flex Alert objects are not stored in this list. I'm not sure why, but they aren't. This seems like an oversight or bug, but the fact remains that looking at the popUpChildren wouldn't work. This list appears to only contain any PopUp instances created using the PopUpManager, but not any Alert instances. Nor is there a similar list such as alertChildren. It turns out that Alerts are added to the SystemManager's display list but are not actually kept track of anywhere.

The first part of the solution was to add an application resize event handler that loops through all children of the SystemManager's display list and locates any that are instances of the Alert class:


var systemManager : SystemManager = Application.application.systemManager;

// Look for children of SystemManager that are Alerts, and recenter them.
for ( var i:int = 0; i < systemManager.numChildren; i++ )
{
    var thisChild : Object = systemManager.getChildAt( i );
    if( thisChild is Alert )
    {
        PopUpManager.centerPopUp( thisChild as IFlexDisplayObject );
    }
}

This code actually does work and will recenter the Alert. But in another frustrating turn (and what certainly appears to be another bug), the re-centered Alerts did not display correctly. Any text within the Alert box that was "off the screen" prior to re-centering would not display. I tried triggering an invalidateDisplayList() and invalidateProperties(), but nothing would get the Alert to re-draw the text correctly. I was banging my head against the monitor when my astute colleague Joe Rinehart made a suggestion that turned out to give the desired result:


var systemManager : SystemManager = Application.application.systemManager;

// Look for children of SystemManager that are Alerts, and recenter them.
for ( var i:int = 0; i < systemManager.numChildren; i++ )
{
    var thisChild : Object = systemManager.getChildAt( i );
    if( thisChild is Alert )
    {
        PopUpManager.removePopUp( thisChild as IFlexDisplayObject );
        PopUpManager.addPopUp( thisChild as IFlexDisplayObject, this );
        PopUpManager.centerPopUp( thisChild as IFlexDisplayObject );
    }
}

Essentially, you have to kick Flex in the head by removing the Alert, re-adding it, and then re-centering it for good measure. All of this seems like a lot of hoops to jump through to accomplish something that seems like it should be rather easy to do, but there you have it. Going forward, we'll probably set up some sort of centralized manager class that can be used to create and keep track of both Alerts, PopUps, and any other components that need to display at the very top display list of the application (such as Callouts and Tooltips), and we're also looking at some Growl-like notifications to minimize the use of Alerts. But that's a topic for another day (probably in the very near future though). In any event, hopefully this post will help anyone who ends up in a similar situation!

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]

Creating Flex "remoting proxies" in Groovy

When you're developing a RIA based on a set of business services, it's rare that your domain model is simple enough to just expose the raw services to Flex. Often, you'll have spots where you need to work in thinner DTOs or do a little extra work specific to Flex.

While you can do a fair amount of this with AOP, that's often like hunting flies with an elephantswatter. Instead, I've been creating remoting services that defer any method not explicitly defined to the business service they wrap. If I need to add a smattering of "advice" before or after a method call, I then just define the method and add my bits.

Here's an example, using a fictitious "LoginService" being proxied by "FlexLoginService."


class FlexLoginService
{
    // Injected by Spring
    LoginService loginService


    /**
     * By default, defer invocations to wrapped LoginService
     */

    def methodMissing(String name, args)
    {
        return loginService.invokeMethod(name, args)
    }

    /**
     * Wrap the "login" method to deal with the UserDTO sent from Flex
     * - the business service expects a full-size User object
     */

    login (UserDTO userDTO)
    {
        def user = new User(username: userDTO.username, password: userDTO.password)
        loginService.login(user)
    }

}

Behind The Curtain ... continued

A few days back Sean gave us all a sneak peak of the Broadchoice Workspace. He also mentioned we're all very busy lately, and guess what ... the Broadchoice Workspace is not the only application we're working on. Today I'm going to introduce the Broadchoice Workspace Analytics platform.

[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]

JMS + Swiz = Evil Realtime Flex.

We're building out some prototype applications here at Broadchoice based on a Groovy + AIR stack that have multiple cases of data "push" to the AIR client.

At first, we took a traditional route of setting up destinations and Consumers for the different realtime cases, but that got pretty old pretty quickly, and we've put together a nifty system using server-side JMS and the Swiz framework. This'd also work with Cairngorm or any other MVC Flex framework that uses a central event dispatcher / front controller.

What's the architecture?

Swiz includes the idea of a CentralDispatcher that allows events to be dispatched outside of the UI component tree, allowing controllers (very Model-Glueish!) or even views to listen for application-level events.

On the server side, we've created a class (ApplicationEventMessage) that models a request for the client-side to create and dispatch (via Swiz) a DynamicEvent containing arbitrary properties.

By setting up a delegate that uses a Consumer (autowired by Swiz, of course!) the receives pushed ApplicationEventMessage instances to the client, we're using JMS on the server side to essentially dispatch events on the client side.

What's the result?

We've got a little controller on the client side subscribed to events of type "notification" that shows a nice little notification overlay in the application. When a user logs in, we want a notification of this login to get pushed to all other clients. Instead of setting up a new destination, a new consumer, and all of that rigamarole, we can just dispatch JMS message via the single consumer to send a message to client requesting that a DynamicEvent of type "notification" with a message property of "John Doe logged in" be created and dispatched.

Here's all the server-side code I had to write (in Groovy using Spring's JmsTemplate):



def message = new ApplicationEventMessage(
    eventType: "notification",
    data: [
        message: "John Doe logged in"
    ]
)
    
jmsTemplate.send(
    [
         createMessage: { Object[] params ->

             def session = params[0]
             return session.createObjectMessage(message)
         }
    ] as MessageCreator
)

Taking it one step further, I wrapped this up in a simple service (wired into other services via Spring) that the rest of the team can use. For example, Brian Kotek was working on a small filesharing system and wanted to notify clients of new uploads.

Here's literally all he had to do to send out client-side notifications:


def message = new ApplicationEventMessage(
        type:"fileUploaded",
        data: [
            message: fileItem.name + " was added to the shared files."            
        ]
)

messageDispatcher.dispatch(message)

But Why JMS?

We're going to be targeting multiple platforms with some upcoming products. JMS is by no means Flex-specific, allowing us to use this same notification system to send realtime updates to clients other than Flex and AIR.

Swiz and MockAsyncToken

I've been taking a look at the applicability of Chris Scott's Swiz Framework for use here at Broadchoice. So far, it's exactly what I'd expect - a fairly noninvasive way of wiring dependencies inside a Flex / AIR application that allows use of inversion-of-control.

One thing that threw me, though, was that Swiz approaches business delegates (wrappers for business services like RemoteObjects) from a total RPC standpoint. Instead of passing an IResponder to a new delegate instance each time you wish to use it like most Flex frameworks encourage, you simply write a delegate, instantiate it once in your BeanLoader, and use it as a singleton. Each of its methods that make server-side calls just return AsyncToken instances.

I really like this, as it makes the difference between a simple RemoteObject and a delegate wrapper completely irrelevant - your controller doesn't have a clue if it's talking to a delegate or not.

It did, however, throw me off from something I typically do. I normally write a "mock" delegate for any business service that "pretends" the server is there. Its useful in both unit tests and day to day coding: server may be down, backend code not written, etc.

In order to get this to work with Swiz, however, I had to simulate the presense of an AsyncToken and its related RPC events. Hence, I've cobbled together a MockAsyncToken and MockResultEvent that let you quickly set what you'd like a mock delegate to return:



// Mock'd RPC function
public function getUser() : AsyncToken
{
// just pass the desired server response to the MockAsyncToken's constructor
return new MockAsyncToken(new User());
}

...bam. Instant mock delegate. Thanks to Swiz, the rest of the app doesn't care that it's even there, and if I can use a plain RemoteObject, I never even have to write the "real" delegate.

Code for MockAsyncToken and MockResultEvent (dependency) is attached. Use at your own peril.

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