Sunday, July 18, 2010

Starting down the trail with Silverlight and REST Services

The current project that I am working on includes a user interface that can be characterized as a browser-based rich client application. To date, the client components have been written in either JavaScript or Flex. The components interact with a JEE application server through a set of RESTful APIs. I recently started investigating the potential to implement components based on Microsoft Silverlight in anticipation of potential client requirements.

While not explicitly defined, my goals included the following:
1. Asses how easy would it be for someone like me to create user interfaces with Silverlight
2. What level of effort is involved in working with our REST-based APIs in Silverlight
and a as bonus
3. Could such components run on Linux through Moonlight

This post is a running summary of what I have been able to accomplish to date:

Initial Steps

To start out, I setup a development environment in a VM consisting of Windows 7 and Visual Studio 2010 Ultimate. To help familiarize myself with Silverlight, I started reading through Matthew MacDonald's Pro Silverlight 3 in C#. I choose to implement the components in C# because of our team's strong background in Java and the similarities between the two languages. The book provided most of the information I needed and I'm sure will be a good reference as I continue with Silverlight.

After some initial experimenting with the tools, I selected one of our existing components and decided to attempt to reproduce it in Silverlight. The component I choose is very simple. It retrieves a list of resources from the server, let's call them widgets, and allows the user to set their active / inactive state.

Visual Layout

To be clear, the focus of my experimentation was not to create the best looking UI, but I did want to see if using the standard settings you could create something presentable. One of the new features that Microsoft added as part of Visual Studio 2010 is a graphical XAML (Extensible Application Markup Language) editor. XAML files allow the developer / designer to layout components (it can also be done in code). Microsoft produces another editor named Expression Blend which targets the designers. I decided to stick with the VS2010 editor for this quick project.

My layout was fairly basic. It used a simple Grid layout that included a DataGrid to hold the records to be displayed and manipulated. The layout concepts should be easily picked-up by developers accustomed to other UI layout libraries (e.g., Java Swing etc.). The DataGrid can be configured to automatically create columns for each public property of the object bound to it. This is a great way to quickly get the data into a UI. After initially using this approach to make sure the binding was working, I defined switched to explicitly defining the columns and setup three named active, name, and title.

Retrieving and Displaying the Data

The constructor for the code behind class of MainPage was defined as follows:

public MainPage()
  {
    InitializeComponent();
      // Setup the Cell Editing delegate
      this.gridWidgets.CellEditEnded += 
         new EventHandler(gridWidgets_CellEditEnded);

      // Request the widget List data
      this.requestWidgetList();
  }

The first instruction registers an event handler to handle when the user changes the state of the active value of a record. The second instruction calls the requestWidgetList() method which starts the process of requesting the data from the server. As this was a simple HTTP GET request, I was able to use the WebClient .NET class. You simply create an instance of the client, register a delegate to read the response, and pass an instance of the Url class to the client to initiate the request. The event handler for the read complete event receives the data, deserializes it from JSON using the built in .NET class and populates the DataGrid through its ItemsSource property.The two methods are shown below.

private void requestWidgetList()
  {
    WebClient client = new WebClient();
    Uri address = new Uri(getApplicationUrl() + "/widgets;

    client.OpenReadCompleted += client_OpenReadCompleted;
    client.OpenReadAsync(address);
  }

  void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
  {
    DataContractJsonSerializer serializer =
      new DataContractJsonSerializer(typeof(WidgetSet));
    this.widgetSet = (WidgetSet)serializer.ReadObject(e.Result);
    this.gridWidgets.ItemsSource = widgetSet.widgets;
  } 
 
As you may notice, the deserializer was initialized with the type of data expected in the results. This is one area where working with the built-in .NET serialization classes could be time consuming if the JSON you're working with has a complex structure and is still in development. There is an open source library named Json.NET started by James Newton-King that aims to make working with JSON in .NET much easier. I haven't tried using the library yet, but plan to shortly.

Another thing to notice about the above code, is the call to the getApplicationUrl. This method obtains the URL to our application's base REST API context. In our application the REST API host may not be the same as the host the Silverlight component is downloaded from, Therefore the properties provided by the Silverlight environment could not be used and I needed a different way to obtain this information. For the sake of this simple example, I decided to pass this information into the Silverlight component as initialization parameters. This isn't the way you would want to go for a production application as it can be easily hacked, but for my purposes I thought it acceptable.

Updating the Data

The update process starts with the event handler registered in the MainPage constructor for DataGrid changes. It first checks to verify that the user is committing a change as opposed to canceling one. It then starts the process of sending the POST to the REST API to update the data. Unlike the GET request used to initially retrieve the data, sending a POST cannot be done using the WebClient .NET class. It requires the use of the WebRequest .Net class. This class is more flexible but adds an additional asynchronous step in the request process.

Testing and Experimentation

After I got the component working using VisualStudio's built-in test server, I deployed the Silverlight application to my JEE server as an embedded object in an HTML/JSP page. The Silverlight application is packaged up as a XAP file. This is essentially a ZIP file containing the compiled C# code, supporting libraries, and any static resources that the developer wanted to include. After starting our application, I brought up the new component and things worked as expected. Deciding to go a step further, I then installed Moonlight 3 Preview on Ubuntu 0904 64-bit and decided to give it a try. As the DaatGrid control was introduced in Silverlight 3, I needed Moonlight 3 to try out my component. I was pleasantly surprised that it worked as expected. The run time included a warning banner indicating that it was a preview release and it seemed a bit more sluggish than running in Windows, but all-in-all I was really impressed. Nice work Moonlight team!

Conclusions

Overall, I felt that the experience of creating a Silverlight component to interact with a JEE provided REST service went pretty smooth. Using the Json.Net library should hopefully make any similar work easier. And finally, the Moonlight team appears to be doing a great job at implementing the Silverlight environment. I'm curious now to see how working with the project would be in MonoDevelop ...