Accessibility
 
Home / Developer Center / Blackboard Sample Application

Developer Center Article

Using Java to facilitate ActionScript development
 
The Flash debugger, available within Macromedia Flash MX, is an incredibly useful tool. Figure 6 is a screen shot of the Flash debugger showing some of the Course data returned by the server. Does this data look familiar?
 
Figure 6: The Flash debugger with returned Course data
 
The data that was created on the server and saved in Java objects is delivered to the client in ActionScript objects, the client's native format. The benefits of this capability are truly profound. Think of the amount of work this saves!
 
Here are some examples of how course data can be accessed in ActionScript:
 
   var courseName1 = course.name;             // "Anthropology 101"
   var courseName2 = course["name"];         // "Anthropology 101"
   var user11email = course.users[11].email; // "hjones@abc.com"
 
So easy!
 
Automatic Java-ActionScript translation (the actual term is serialization) works for many other data types, and it works going from client to server as well.
 
The following table contains supported ActionScript data types and their Java equivalents:
 
ActionScript data type Java data type
Number (primitive data type) Double
Boolean (primitive data type) Boolean
String String
ActionScript (AS) object Map
null null
undefined null
Ordered array ArrayList
Named array Map
Date object Date
XML object org.w3c.dom Document
The following table contains the supported Java data types and their ActionScript equivalents:
 
Java data type ActionScript data type
Object[] Array
Array of primitive types Array
Boolean boolean
Number number
Character String
Date Date
java.sql.ResultSet,
flashgateway.sql.PageableResultSet
Recordset
Throwable ActionScript Object
org.w3c.dom.Document XML
flashgateway.io.ASObject ActionScript Object
flashgateway.io.ASXMLString XML
Map ECMA Array
Collection Array
Dictionary ActionScript Object
Serializable ActionScript Object
Notification about newly-arrived data
After dataAccess receives the Course Object, it notifies the UI that course data is available. The notification framework was intentionally omitted in the code examples above, in order to show how dataAccess is initialized. Now we will backtrack to show how notification is initialized.
 
This code is executed when BBGMDataAccess.as is included in the main (UI) program:
 
   // make an event source w/ listener support
   AsBroadcaster.initialize(BBGMDataAccess.prototype);
 
This adds event notification capability to our data access class. When the main (UI) program creates the data access object, it registers itself as a listener:
 
if (dataAccess == undefined){
          dataAccess = new BBGMDataAccess(gatewayURL, service);
          dataAccess.addListener(this);
 
DataAccess adds the UI program object (passed as "this" in the example) to its list of listeners. When the data access layer receives a reply from the server, it uses the ASBroadcaster method broadcastMessage to notify its listeners that data has been received. This code from the data access class shows how replies to the getCourse request are handled.
 
BBGMDataAccess.prototype.getCourse_result = function(course){
        this.broadcastMessage("onBBGMSGetCourse", course);
}
 
BroadcastMessage specifies two parameters: the name of the listener method and the data that has changed. Here is the listener method in the main (UI) program:
 
onBBGMSGetCourse = function(obj){
       this.courseObj = obj;
       updateGroupDisplay();
}
 
Using ASBroadcaster (rather than using a direct call, to updateGroupDisplay in this example) permits a clean separation between the data access layer and the component(s) that use the data provided by the data access layer. One advantage of this approach is that the data access layer can be developed without knowing how the data it delivers is used. The connection between the UI and the data access layer is established at run time, rather than at compile time. This makes the solution more flexible. Additionally, the UI can be changed without impacting the data access layer. This allows a completely different UI to be delivered. For example, if PDA or device delivery is also desired, the data access layer would not be changed at all. This approach also permits parallel development. For more information on this topic, search the web for MVC or model-view-controller architecture.
 
Using the Façade
Taking advantage of Java's treatment of interfaces proved to be very advantageous on this project. This approach facilitates parallel development of client and server components. Additionally, this eliminates potential problems that could occur when the components are integrated.
 
In Java, an interface specifies the contract between two programs: a caller and a callee. In the Blackboard project, we used an interface to specify the contract between the client and server programs.
 
This is the Java code that specifies the BBGMFacadeInterface.
 
public interface BBGMFacadeInterface {
  public Course getCourse(String pkcourseId) throws Exception ;
  public CreateGroupResponse createGroup(int requestId,
                                         String pkcourseId,
                                         HashMap parameters)
                                         throws Exception;
  public Response updateGroup(int requestId,
                              String pkcourseId,
                              String groupId,
                              HashMap parameters) throws Exception;
  public Response removeGroup(int requestId,
                              String pkcourseId,
                              String groupId) throws Exception;
  public Response createAssignments(int requestId,
                                    String pkcourseId,
                                    ArrayList assignments)  
                                    throws Exception;
  public Response removeAssignment(int requestId,
                                   String pkcourseId,
                                   HashMap assignment) throws Exception;
}
 
The interface specifies all methods that are available to the client. For each method, it lists all inputs and outputs. Note that it does not include implementation logic (in other words, nothing is within curly braces). The Java compiler verifies that any class claiming to implement an interface provides all interface methods with exactly the correct input and outputs.
 
Remember this line from BBGMFacadeDevelopmentImpl earlier?
 
public class BBGMFacadeDevelopmentImpl implements BBGMFacadeInterface,
                                                     Serializable
 
This part is new:
 
public class BBGMFacadeProductionImpl implements BBGMFacadeInterface,
                                                     Serializable
 
 

Figure 7: A diagram of the programs that were built around the BBGMFaçadeInterface.
 
We created two implementations for BBGMFaçadeInterface: FaçadeDevelopmentImpl for development, testing and demonstration; and BBGMFaçadeProductionImpl to interface with the Building Blocks API. We also wrote two clients. The development work proceeded as follows:
 
Phase one – infrastructure: TestClient —>  FacadeDevelopmentImpl
Phase two – component development: TestClient —>  FacadeProductionImpl
  Flash client —> FacadeDevelopmentImpl
Phase three – integration: Flash client —> FacadeDevelopmentImpl
 
In Phase 1, all the details of the Façade were ironed out, and test programs for client and server were developed. In Phase 2, the more challenging client and server component development was done in parallel, using the solid interface specification and test harnesses created in Phase 1. The client and server components were "hooked up" in Phase 3. This proved to be a very effective development strategy—that would not have been possible without Java interface technology.
 
Request/Reply Tracking
The BBGM Façade implements 6 methods. This article has examined only one of these: getCourse. GetCourse is called only once, when the BBGM client initializes. The other methods can be called any number of times and in any order. We created a Response class to keep track of the replies, with the following code:
 
public class Response implements Serializable{
  public int requestId;

  public Response(int requestId) { //constructor
    this.requestId = requestId;
  }
}
 
The BBGMFacadeInteface specifies that for all methods (except getCourse) the first input parameter is a request ID, and a Response object, which contains the request ID, is returned. If you look at the code, you will see that each request is sent with a unique request ID, and that ID is returned in the Response object. Thus, a unique identifier makes the entire round trip. This was important for keeping track of outstanding updateGroup requests on the "All Groups In Course" window. It was also very useful for debugging and QA work.
 
In the final section, we'll take a look at error handling.
 
 
 
Previous
Contents
Next