Mobile Services featured on TechCrunch!
05 March 2013
Yavor is a PM at Snowflake working on developer experience. Previously at Docker, Auth0, Hulu, and Microsoft Azure.
05 March 2013
04 March 2013
Welcome to part two of my blog series about the new Mobile Services Android client SDK. Here are the other posts in the series:
Today let’s focus on customizing object serialization using the gson library, which the Android client library uses under the covers to serialize objects to JSON data. In the previous episode of this series we named our Java object in lowercase, so all the properties would get serialized that way on the wire:
public class droid {
public Integer id;
public String name;
public Float weight;
public Integer numberOfLegs;
public Integer numberOfWheels;
}
For all of you seasoned Java developers out there, this immediately sticks out as bad programming style: we’re not capitalizing things correctly and also we’re not using getters and setters. This next class uses gson’s serialization attributes to produce the exact same wire representation as above.
public class Droid {
@com.google.gson.annotations.SerializedName("id")
private Integer mId;
@com.google.gson.annotations.SerializedName("name")
private String mName;
@com.google.gson.annotations.SerializedName("weight")
private Float mWeight;
@com.google.gson.annotations.SerializedName("numberOfLegs")
private Integer mNumberOfLegs;
@com.google.gson.annotations.SerializedName("numberOfWheels")
private Integer mNumberOfWheels;
public Integer getId() { return mId; }
public final void setId(Integer id) { mId = id; }
public String getName() { return mName; }
public final void setName(String name) { mName = name; }
public Float getWeight() { return mWeight; }
public final void setWeight(Float weight) { mWeight = weight; }
public Integer getNumberOfLegs () { return mNumberOfLegs; }
public final void setNumberOfLegs(Integer numberOfLegs) {
mNumberOfLegs = numberOfLegs;
}
public Integer getNumberOfWheels() { return mNumberOfWheels; }
public final void setNumberOfWheels(Integer numberOfWheels) {
mNumberOfWheels = numberOfWheels;
}
}
There is another catch here… our type name is Droid (uppercase), but maybe we want our table name to be lowercase. It’s just a matter of which getTable overload we use.
// Assumes table name is "Droid"
MobileServiceTable table = client.getTable(Droid.class);
// Allows you to use table named "droid" - use this one!
MobileServiceTable table = client.getTable("droid", Droid.class);
This was a relatively simple serialization trick. To do more we need to whip out the big gun: GsonBuilder. To successfully talk to your mobile service, the client needs to do some customizations of its own, so we we need to get a pre-cofigured instance from the the MobileServiceClient.createMobileServiceGsonBuilder() static method. We can then add our own modifications and pass the instance back to the client. The below code does a lot in just a few lines:
client.setGsonBuilder(
MobileServiceClient
.createMobileServiceGsonBuilder()
.setFieldNamingStrategy(new FieldNamingStrategy() {
public String translateName(Field field) {
String name = field.getName();
return Character.toLowerCase(name.charAt(1))
+ name.substring(2);
}
})
.setPrettyPrinting());
Of course we need to add the above code before the calls to any of the methods on the client.
To really put the cherry on the cake, let’s tackle a very challenging problem: complex types. So far all of our properties have neatly serialized to JSON primitives. Imagine we want to add the following property on our Droid object:
private ArrayList<String> mCatchphrases;
public ArrayList<String> getCatchphrases() {
if(mCatchphrases == null){
mCatchphrases = new ArrayList<String>();
}
return mCatchphrases;
}
private final void setCatchphrases(ArrayList<String> catchphrases){
mCatchphrases = catchphrases;
}
Having objects and arrays as properties is a rather advanced feature mostly because we now have to a make a call about how those are represented on the server. Mobile Services doesn’t support that out-of-the-box and you would get an error similar to this one:
{
"code":400,
"error":"Error: The value of property 'catchphrases' is of type 'object' which is not a supported type."
}
Let’s roll our own custom solution. On serialization we will store the JSON-serialized representation of our complex properties inside JSON strings. On the server, we will simply store the strings inside a string column. On deserialization, we will parse those strings as JSON and deserialize them back into typed objects. A tall order!
Our strategy here is to register a custom serializer for ArrayList<T> types. Here is an implementation I put together:
~~~ java import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collection;
To celebrate the Mobile Services Android launch, I’ve decided to put together a blog series over the next week to highlight some of the cool new features in our Android SDK. Here is the list of subjects I plan to cover:
Today, let’s focus on the data access aspect of the client, which lets us work with server entities in a typed or untyped way. Let’s start with a simple class that we want to store in a server-side table. We’re naming our class and properties to resemble the serialized JSON, we will cover how to customize the mapping between the properties and the serialized representation in a later post.
public class droid {
public int id;
public String name;
public Float weight;
public Integer numberOfLegs;
public Integer numberOfWheels;
}
Note that a phantom menace lurks here: the class needs to contain a property called Id, ID, or id which will be populated by the server when it stores the entity.
To store instances of the class inside Mobile Services, we first need to create our Mobile Service in the Azure portal and then create a table called droid. Capitalization is important here. We then use the URL and application key provided in the portal to instantiate the MobileServiceClient.
MobileServiceClient client = new MobileServiceClient(
"https://droid.azure-mobile.net/",
"RrBQdeuaScZCIUsDSNnHPUyKowDDdW89",
this);
The third parameter we pass here is the Activity or Service where the client is instantiated. We use that reference to grab the application context, which we use to store the installation ID for this application and also to display our authentication UI dialog.
Now we need to get a reference to the table object so we can insert data into it. Let’s look at the different overloads of the getTable method.
public class MobileServiceClient {
public MobileServiceJsonTable getTable(String name);
public <E> MobileServiceTable<E> getTable(String name, Class<E> clazz);
public <E> MobileServiceTable<E> getTable(Class<E> clazz);
}
The first overload is for working with our untyped JSON-based programming model, we will discuss that in a second. The second overload lets you work with a table if its name is different from the type name. The last overload assumes the class name and the table name are the same; this is the simplest one and that’s what we’ll use here.
MobileServiceTable<droid> table = client.getTable(droid.class);
We can then instantiate a new instance of the droid class and insert it into our server-side table.
~~~ java droid r2d2 = new droid(); r2d2.name = “R2D2”; r2d2.numberOfLegs = 0; r2d2.numberOfWheels = 2; r2d2.weight = 432.21f;
26 December 2012
Snow Fall: The Avalanche at Tunnel Creek
An amazing interactive article covering the avalanche that happened in the Stevens Pass area just the day before we last went skiing there.
21 December 2012
Update: Corrected the server script code snippet.
Update 2:The example below will unfortunately no longer work due to Twitter API changes… I need to update it. In the mean time, our official documentation shows a very similar scenario, so check that out.
As Scott announced earlier today, Mobile Services is celebrating the holiday season by bringing you some cool new features, including the ability to execute scheduled jobs (or “cron jobs”).
"Windows Azure Mobile Services now supports the ability to easily schedule background jobs (aka CRON jobs) that execute on a pre-set timer interval, and which can run independently of a device accessing the service (ensuring that you don’t block or slow-down any requests from your users). This job scheduler functionality allows you to perform a variety of useful scenarios without having to create or manage a separate VM."
Some of the scenarios you can enable with it include:
Here I want to give a more detailed demonstration of the feature and celebrate another winter tradition: skiing. Let’s walk through a simple scenario where we will use a scheduled job to aggregate and analyze tweets related to ski conditions near Seattle. The source code is available here.
Let’s assume we already have a mobile service called skibuddy. We can navigate to the new Scheduler tab in the Windows Azure portal to create a scheduled job.
Let’s go ahead and create a job called getUpdates. We will use the default interval of 15 minutes that is already selected in the dialog.
Once the job is created we will now see it in the summary view. You will note that the job starts off as disabled, so let’s click the job name to add our script.
On the job details page, we see information about our job and also we also have an opportunity to change the schedule. For now let’s leave everything as-is and navigate over to the Script tab.
Here we see the script editor window that has been pre-populated with a default empty script.
Let’s replace the default script with the following one.
~~~ javascript var updatesTable = tables.getTable(‘updates’); var request = require(‘request’);
28 November 2012
I had a great time in Milan, covering how to write lightweight apps on Azure. We showed how to write a mobile game using Azure Mobile Services and how to write a more involved Node.js app using Azure Websites.
Here are links to the demos I showed:
Hope you find this useful!