JayData.org

Using JayData in Titanium to access remote OData service

Author: Robert Bonay July 12th, 2012

, , , , , ,


UPDATE: this blogpost has been updated to use the latest version of JayData (1.1.1). The example project has been moved to a separate GitHub repo: https://github.com/jaydata/titanium-odata-client. Feel free to fork it and improve the app with your ideas.

As we are determined to unify the data management in HTML5 and JavaScript, we try to support as many platforms as we can. After developing hybrid PhoneGap applications using JayData, we decided to make a try to make a proof-of-concept with Appcelerator Titanium.

It was clear that supporting local data storage access to Titanium developer will take a while for us, so we focus on how to manage remote cloud data in Titanium apps using JayData, hence we decided to put together an OData client application, which queries the online Netflix movie data service. We have already published a similar Netflix browser example to Sencha Touch 2.

The example application

Our example Titanium project will use JayData to access the public Netflix movie database with a single query. JayData is a provider-based library, developers can manage CRUD data in local storages (WebSQL/SQLite, IndexedDB) and on the cloud (Facebook, OData, YQL) with the same syntax. At the moment we tested JayData in Titanium environment only with OData provider.

The user interface will be very simple, we will render two tabs:

  1. Master view – lists the last 50 movies
  2. Detail view – displays the selected movie from the list

As I’m not an expert of Titanium, so I won’t be able to show a masterpiece application here, but I will demonstrate how can you use JayData for data management in cross-platform scenario. You will see that the source-code of data management is the same for Android and iOS.

netflix_browser_masterview  netflix_browser_detailview

Putting the app together

First of all, you will need the latest JayData library. You can fork and build the latest (non-stable) version for yourself from the JayData Github repo, or download the released version from the JayData CodePlex project page.

No matter how you get JayData, you will have a jaydata.js and a jaydataproviders subfolder. As we will use only the OData provider, we can save same space by deleting all the files in the jaydataproviders folder, except the oDataProvider.js, which contains the necessary dependency (data.js). Before you include JayData to the Resources folder of your Titanium Studio project, make sure you have saved the files in UTF-8 format.

Now we can create a new Titanium Mobile Project in Titanium Studio by following the project creation wizard.

create-titanium-mobile-project-1 create-titanium-mobile-project-2

The Netflix OData service metadata can be analyzed here: http://odata.netflix.com/v2/Catalog/$metadata. As you can see, this metadata describes the published entities (Title, Person, BoxArt, etc.) and the relationships.

Without JayData we would build a querystring, use a XMLHttpRequest in web applications or Ti.Network.HTTPClient in Titanium to query query the service URL, process the result and map the object properties to the frontend. JayData does the first three labour-intensive tasks for us and helps the UI mapping with navigable object references. JayData is shipped with JaySvcUtil, which generates the client-side metadata of online OData services as a context definition. Currently JaySvcUtil can be used only on Windows platform (any contribution is welcome, guys), but you find the generated netflix.js.

After you have this context (and JayData) loaded to your project, you are able to use JavaScript Language Query (JSLQ) syntax to access Netflix data.

Building the frontend

As I mentioned, we will have the master and the detail views as two element of a TabGroup control.

After the application starts, Titanium gets the matching ApplicationWindow.js, depending on the platform of the current device/emulator. This ApplicationWindow class initiates the TabGroup containing our two views.

To overcome the differences of iOS and Android, our current implementation we will reference JayData differently.

iOS:

  1. We can use require() to load JayData library and the Netflix context definition in the ApplicatonWindow class
  2. Let’s tell JayData to use the Titanium-specific HTTPClient to issue requests by injecting the Ti.Network.HTTPRequest
  3. According to the Titanium SDK API Reference, HTTPClient class doesn’t implement the getAllResponseHeaders() method on iOS platform, so we have to monkey patch it here.

Android:

  1. I wasn’t able to use require by overcoming the issues of global scope and window object, so I use Ti.include() to load JayData library and the Netflix context in each views as a workaround. Please keep me posted if you find any better, working solution Smile

The ApplicationWindow defines an event listener, which is attached to the click event of the movie list and fires an event in the detail view by passing the ID of the selected movie.This also switches to the detail view.

Master view

We will write here a JSLQ query to retrieve the list of movies, create a TableView and add a TableViewSection for each movie.

Notice that we hadn’t made any manual AJAX call, we haven’t build query string and we haven’t parse any response, because JayData has solved all of these tasks for us.

Detail view

We can arrive to the detail view by choosing a movie on the master view.

Here we will build a little bit more complex JSLQ statement to retrieve the selected movie. The query consists of two major parts:

  1. filter: we ask for the movie with specific value
  2. include: we join the movie (Title entity) with the cast to retrieve the actors as well. Feel free to extend this list with more entities, for example to show the awards.

Our Titanium app now queries the Netflix service using JayData

I assume that everybody reading this blogpost understands Titanium better then me, so I omitted the Titanium UI building. To get a working copy of the source-code, import my example project from GitHub to your Titanium workspace. I tested the iOS platform on OSX and the Android platform on Linux.

Possible improvements

  1. The user interface 🙂
  2. You can use the map() function to apply a projection on the movies to retrieve only a subset of the fields in order to reduce network traffic – You can check out the possibilities in JSLQ 101.
  3. You can improve you master view with custom ordering (for example by movie release year), search and pull-to-refresh features.

, , , , , ,