Moving to Flash, Part 5: Network Communication
This is part 5 in a series of posts that address the issues involved in porting a large Java RIA to Flash. I recommend reading the previous posts as well:
Part 1: We’re Moving to Flash. Here’s Why
Part 2: Important Differences Between Java and ActionScript 3
Part 3: Beginning the Actual Port
Part 4: Anonymous Classes and the Adapter Pattern
Another main difference between Java and ActionScript is in how data is communicated to and from the server. In just about any Rich Internet Application this is going to be an important part of your architecture, so it’s important that it is handled correctly.
Synchronous vs. Asynchronous Communication
In Java it is possible to make a blocking call when requesting data from the server. Typically this will happen on a background thread and the programmer handles the returned data in the same thread. In ActionScript, it is not possible to block while data is being requested from the server. This can cause some challenges if you’re trying to port a project to ActionScript.
Java Threads
Fundamentally, the only real difference here is where the threading happens. This exact same functionality could be implemented in Java as well, you just need to manage the data yourself. In Java however, there is no guarantee when the remote call will return. The thread on which the request occurs will continue processing in parallel with your main event thread, so you may want to implement a task queue that guarantees that the handling of returned data happens at a particular time. If you don’t do something like this, you will probably have to handle synchronization issues because you will now have two threads running simultaneously. This will be covered in a bit more detail later in the post.
Because of these issues, if you’re using a programming language that has a threading model similar to Java’s, you may want to rework a few things before starting into the port, but it isn’t necessary. We did it afterward so it’s clearly possible.
ActionScript Data Requests
In ActionScript, data can be requested using many different methods. With all of them, you handle returned data by adding event listeners to the object. For example:
public function executeRequest(tHandler:Function, tErrorHandler:Function) {
// Create the URL loader which will perform the actual communication with the server.
var tURLLoader:URLLoader = new URLLoader();
// Register an event listener that will respond to the completion event
// and notify the response handler.
tURLLoader.addEventListener(Event.COMPLETE, function completeHandler(tEvent:Event):void {
// Instantiate a new response object which makes retrieving data
// from the response simple.
var tResponse:ServerResponse = new ServerResponse(tURLLoader.data);
// Pass the response to the handler.
tHandler(tResponse);
});
try {
// Execute the load. A successful callback will be passed to the
// handler, and any Error will be passed to the error handler.
tURLLoader.load(tURLRequest);
} catch (tEx:Error) {
if (tErrorHandler != null)
tErrorHandler(tEx);
}
}
This little piece of code actually has a lot going on, and is indicative of the model we’re using for communicating the server response back to the client. Let’s look at the completeHandler() function first.
When the data is returned to the client, completeHandler() creates a ServerResponse wrapper around the data and passes that off to the handler that was passed in. The URLLoader’s data property holds the byte array that was returned from the server. The ServerResponse is what is used to unwrap that data. It contains functions such as nextInt(), nextString(), etc. that will pull the values out of the array and return them to the caller.
There are also two different anonymous functions passed in to the executeRequest() function. I’ll note that there are much safer ways to do this. In my last post, I described a DynamicImplementation class that would be perfect for passing in data handlers to this method. The handlers are currently very simple only because we know that there is a single parameter to each one.
The important point here is that we are providing the data handler to the exceuteRequest() function so that we can process the returned data when it is returned. In Java, the model was that the ServerResponse itself would be returned as a result of the executeRequest().
Using a Task Manager
I’ve also mentioned in previous posts that you may want to use Runnables for posting tasks to a global task manager. One problem with moving from a multi-threaded to a single-threaded environment is in determining when exactly the data is being processed. If your communication was happening on a separate thread in Java and you were using the above model, then you may need to perform synchronization in your response handler. However, if you guaranteed that data manipulation never happened on any thread other than the event queue you could forget about this.
Using a task manager would allow you to pass in a Runnable to the executeRequest() function which can be posted to the task manager to be processed during the start of your main event thread. This is very similar to the model that Flash uses for when the events are processed as the result of the remote call.
Conclusion
Now that we have our communication architecture in place, we’re pretty much finished. This series of posts describes just about everything that we needed to do in order to get a working prototype up and running and it only took two weeks, including learning ActionScript. There are a few things that I didn’t mention in this series, such as the differences in drawing objects in Java and Flash and our underlying physics engine. If there’s interest, maybe we’ll post some information about this in the future.
We’ve described the big pain points that we’ve encountered along the way and the solutions that we’ve come across. It’s been a very interesting process and really makes me appreciate the work that we did up front to enable this port. If you’re thinking of moving to Flash, hopefully some of these posts will help you save some time yourself.
Tags:ActionScript, communication, Flash, Java, network, port![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=dfa333d1-9a12-4466-a533-f11e1da288c1)
11. November 2008 at 2:04 pm :
Just wanted to point out that the links to the previous posts point to wp-admin…
And thanks for an interesting series of posts!
11. November 2008 at 2:11 pm :
@Marc Fixed! Thanks for catching that.
12. November 2008 at 3:16 am :
Very nice series of articles so far. A really enjoyable read for me as an ActionScript developer.
.
As for communication with the server, I would recommend you to use AMF. With AMF you can send typed objects from and to your backend. These objects are compressed and very fast to serialize and deserialize on the client.
.
This URL might give you some extra information: http://www.jamesward.com/census/
.
.
Greetz Erik
12. November 2008 at 1:14 pm :
Why isn’t this called moving to Flex? Did you seriously make it AS3 and not Flex?
If so, that’s really sad because you should start over now in Flex.
12. November 2008 at 5:02 pm :
@Erik Thanks for the comment. We have a Java server that we are communicating with. It expects data in a specific format, so to minimize changes we did a direct port of the functionality. The only thing we had to change on the server was the type of compression used. I don’t know much about AMF but in the future this might be a better option.
@Jason It is Flex, under the hood. It all runs in the Flash player though, hence the title. More people recognize the name Flash as well. In any case, this set of posts highlights changes to the core architecture which is independent of the UI displaying the data.
23. April 2009 at 6:33 am :
hai can anybody help me with port communication in as3
23. April 2009 at 8:23 am :
@dipin I’m not sure that I quite understand your question. However, there is a great resource for these types of issues through the flexcoders yahoo group: http://tech.groups.yahoo.com/group/flexcoders/. You’ll probably find someone in that community who will be able to help you.