DevIntersection talk: web apps with Mobile Services
12 April 2013
Yavor is a PM at Snowflake working on developer experience. Previously at Docker, Auth0, Hulu, and Microsoft Azure.
12 April 2013
31 March 2013
What was going to be a simple link I wanted to share (via Aatish) got me thinking about the legacy of “problematic” monuments across the Balkans. Regardless of what they symbolize, most of these have fallen into disrepair due to the fall of the regimes that erected them in the first place.
The original post here shared a series of “spomenik” monuments built throughout former Yugoslavia. Here is a great essay by John Bailey that puts these in context.
In today’s post we continue our Android blog series for Mobile Services. Here are the other posts in the series.
Today we will talk about the query model in the Android client. In our C# client we were lucky to be able to lean on LINQ, but after some research we found that there is no out-of-the-box equivalent in the Android platform. I’m glad to stand corrected here: please let me know in the comments if we missed something.
Given that, we decided to implement our own fluent query API that supports the same richness that you get with LINQ, so it deserves a thorough writeup. We’ll assume we’re working with our same reference type we used in our last tutorial, but we’ve added a field or two to make things more interesting to query against:
~~~ java 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;
@com.google.gson.annotations.SerializedName("manufactureDate")
private Date mManufactureDate;
@com.google.gson.annotations.SerializedName("canTalk")
private Boolean mCanTalk;
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;
}
18 March 2013
Announcing the new HTML client support in Mobile Services, which enables you to build PhoneGap/Apache Cordova applications. More information on ScottGu’s blog. Get started here.
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;