Update: August 21, 2012
Since this blog post was initially released in June, StackMob has made some significant changes to their development
environment. In particular, rather than relying on a local runner within the
stackmob gem, they now ship a Python
web server. This blog post has been updated to reflect these changes. Most of the content is the same; the only sections
that have changed are “Connecting Sencha to StackMob” and “Deploying to Production”. We have also updated the
sample project in GitHub.
Some Cool Tools
StackMob is a rapidly improving option for building an entire REST API in minutes. It allows you to define your data model and expose CRUD actions all through a simple UI. For those of you with “real world” problems, and “non CRUD actions” they provide a really simple way to develop custom endpoints with our good friend, Mr. Java. This week, they released OAuth 2 and shiny new access control features which remove the last few hurdles to using StackMob for grown up projects.
If we combine these tools we should be able to build pretty powerful applications in very little time. This isn’t easy to do out-of-the-box, so we are going to write a series of blog posts describing how to use these tools together.
Let’s start off simple, and build a silly little app that we can run in development mode (on our local machine) and in production mode (hosted by StackMob). This process will show how to get started with Sencha Touch 2 and StackMob without getting too deep into the complicated features necessary to build something truly useful (we will do this in future posts).
Let’s Build an App!
We are going to build a mobile web application that stores a list of meats. Users can load this app and browse through a list of meats that other users have created. They can even add some new ones if they want. Very silly. Very simple.
Let’s start by building a Sencha Touch application to show the list of Meats in the system and add new ones. The best
(and fastest) way to get started writing your Sencha Touch application is to download and install Sencha’s great
Sencha SDK Tools and Sencha Touch.
You’ll also need to set the environment variable
SENCHA_SDK_TOOLS_2_0_0_BETA3 to be the SDK’s installation directory
Once you’ve done that, starting a new project is very easy, just use the
sencha command to generate a new app:
This will generate a skeleton Sencha Touch app called
StackMobDemo, located in the
StackMobDemo directory in your
home directory. Feel free to rename the app or generate it in another location by varying these parameters. If you’d
like to see the result, launch a web server from within the directory you just created by running
and point your browser to http://localhost:8000. Now we’re all ready to write some code. This tutorial covers the Sencha Touch code at a fairly high level; if you’re completely unfamiliar with Sencha Touch, we highly recommend checking out the Sencha Touch Learning Center and the Sencha Touch 2 API Docs.
The Data Model
The data model of our app is very simple: we have a list of meats, and each meat has an ID and a name. Defining such
a simple model in Sencha Touch is also quite simple; we create the model in
~/StackMobDemo/app/model/Meat.js like so:
1 2 3 4 5 6 7 8 9 10 11
This should be pretty straight-forward. We extend the base model class to have two fields (
our ID will be stored in the
meat_id field, we tell Sencha Touch to handle it specially (in particular, we want the
IDs to be generated in the server –
persist: false tells Sencha Touch not to send up automatically-generated IDs
when creating new records).
Now that we have a meat model, we need a data store for meats. Create the store in
1 2 3 4 5 6 7 8 9 10 11 12 13
Our data store needs to know a few key pieces of information. Obviously, it needs to know what kind of data it will
be storing (our newly-created
Meat model). We tell it to fetch data automatically, and we tell it to sort the meats
alphabetically by their name field. Finally, we define the store’s proxy. In Sencha Touch, proxies are responsible for
reading and writing data to and from external sources. In this case, we want our proxy to be for a RESTful web service,
and we point that proxy at
meats.json. This is going to be our dummy data source that we use temporarily, before we
get the StackMob components set up. Let’s make that file now, and place it at
1 2 3 4 5 6 7 8 9 10
Now we have a model, a store to keep the model instances in, and a dummy set of data with three meats in it. Awesome. What would be more awesome, though, would be to actually see something happen in the browser. Let’s play with some views next.
First let’s create a list view in
1 2 3 4 5 6 7 8 9 10 11 12
Again, nothing too complex here. We extend the default
Ext.List class, we tell the list which store to use (Sencha
Touch is smart enough to figure out that by
'Meats' we are really referring to
StackMobDemo.store.Meats), and we
itemTpl to create a template for the individual list items (here, each row will simply contain a single string:
the name of the meat). The other two options (
title) will come into play later, but spoiler alert,
used to reference the list, and
title will be the title displayed for the list.
The last little bit of plumbing that we need to do is to actually plug all of these classes together and display the
list in the app. To do this, we need to do two things. First, let’s replace the
view that was automatically generated with some code to display the list (just a simple navigation view with one child
view – our list):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
And finally, in
~/StackMobDemo/app.js, we need to make sure that we require all the classes that we have just
defined. For brevity, we’ve snipped most of the code out in the snippet below to highlight the specific lines we need
to add, but you should keep the rest of the code. It’s important.
1 2 3 4 5 6 7 8 9 10
There. That should be everything we need to display our list of meats. Refresh that browser window and drink it in.
Add Some Interactivity
Lists are pretty cool, but static lists are boring. Let’s augment our list to let the user add a meat. To begin, we’ll
add a button next to the title. Open
~/StackMobDemo/app/view/Main.js back up, and add a button to the navigation bar.
Now it should look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
That will give us a slick “+” button. To make the button actually do something, we need to put the “C” in MVC and add
a controller to our application. Let’s define
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
Controllers in Sencha Touch can look a bit intimidating at first. There are four main things going on here:
refscreate getters for you that return the components matching the supplied Component Query. Here, we are defining two
reffinds any component whose ID is “addButton” (note that this is the ID that we supplied when we created our add button). Now if we call
this.getAddButton()in the controller, we will get a programmatic handle to our add button. Similarly, the
refmatches any component whose ID is “meatList”, and we can get it by calling
controlis how we can add event handlers to components that we defined above in
refs. Here, we are telling the controller that any time our
addButtoncomponent firs the
tapevent, it should call the
onAddButtonTap. This is the method that we attached to the
addButton’s tap event. It opens a simple prompt, asking the user to input a new meat. When the prompt is submitted, we call
onSubmitMeat. This is the method that handles the prompt submission. If the prompt was not cancelled, it creates a new meat instance, then uses our
refsthat we defined to get the meat list, and finally adds the meat to the meat list’s store and syncs the store.
Once we’ve wrapped our heads around all that, all we have to do is register this controller with our application. Go
~/StackMobDemo/app.js and add the controller alongside the model, view, and store:
1 2 3 4 5 6 7 8 9 10 11
If we refresh our browsers now, we should see that we have a “+” button which, when tapped, opens a prompt. When the
user inputs a new meat and submits the prompt, the new meat gets added to our list. Excellent. Well, almost excellent.
to POST and getting 501’s. This makes a lot of sense: we told our data store to treat the local file
meats.json as if
it were a RESTful service, so when we add a new meat, Sencha Touch is POSTing to a JSON file. This doesn’t really…
work. What we really want is not a static file for our data source, but rather a server. “But,” you say, “aren’t
servers so hard?” Not with StackMob.
We’re going to use StackMob to get a simple API running in just a few minutes. Get yourself psyched up for how awesome this is. When you’re ready, read on.
Create a free StackMob account. During your registration, you are prompted to select a name for your first
StackMob application. Consider calling it
meatapp (application names don’t need to be unique). When you login you should be taken to the
getting started page. Let’s hold off on looking
through these docs yet (though I recommend you read them, the docs are great). We’re going to jump right into defining the
meat of our API (cheap pun intended).
Creating A Schema
Let’s define our API endpoints and data model. This is the absurdly cool part of StackMob.
From StackMob’s docs, click on Manage Schemas on the left hand side
under Build. StackMob creates a user schema for you by default, we’re going to ignore this for this blog and create our
own schema called
- Click the
Create New Schemabutton in the top right.
- Name the schema
meatand add a
- We want to allow create and read in an “Open” way, so that we can ignore user auth in this simple post
- We are not supporting Update and Delete, so select “Not Allowed” for those options.
- Click Save Schema and you’re done! The configuration should match the image below.
That’s it, you’ve just created an endpoint for creating and retrieving different kinds of meat. Take a moment to reflect upon how easy that really was.
Connecting Sencha to StackMob
The StackMob Python Web Server
Now we want to make our Sencha Touch app connect to our shiny, new StackMob API. StackMob has a Backbone.js based SDK which we could probably shoehorn into our Sencha Touch app, but it would be messy. Instead, we’d like to use Sencha’s data services to talk to StackMob’s REST API directly.
There is one hiccup with connecting to StackMob locally. StackMob hosts your API in the magical cloud, which means an AJAX request to their server from a page hosted at localhost would violate browser’s same origin policy. They don’t currently support CORS so that’s not an option.
The StackMob Python Web Server is a proxy server that solves this problem. It proxies requests from your localhost to StackMob’s servers.
Follow the instructions in Step 2 of the Getting Started wizard to get the local server running.
First, download the web server.
Next, move the Python script to the root of your Sencha Touch application.
1 2 3 4 5 6 7 8
Now if you execute
python stackmobserver.py, the proxy will be running on localhost:4567.
This server will serve your Sencha Touch app, as well as proxy API requests to StackMob once we configure it with your
public key and point the app at our API endpoints. Let’s do that next.
Point Sencha at StackMob
Now we are going to modify our proxy to connect to StackMob via the the proxy url. Out of the box, Sencha Touch provides a proxy for communicating with RESTful services. This is the proxy we set up. Unfortunately, StackMob expects requests to be prepared slightly differently than the way the stock Sencha Touch REST proxy prepares them. To get Sencha Touch and StackMob to communicate gracefully in every situation requires enough modification to Sencha Touch that the topic deserves its own blog post, which will be coming in the near future. In the meantime, it is fairly trivial to get the limited functionality in our app to work. So let’s do that.
We want most of the functionality of Sencha Touch’s REST proxy, but with a few tweaks. So we create a subclass in
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
StackMob requires a few headers to be added to the request, and it does not support paging and limits as request params
(it wants them to be headers as well). Luckily, we don’t need any of that for our app, so we can just turn them off.
We will go through actually reimplementing them in a future post. Note that, in the
X-StackMob-User-Agent header, the
bit after the slash should match the name of your StackMob application. Ours is called
stackmobdemo, but yours might
not be. Be sure to set the
X-StackMob-API-Key header to be your development public key. Again, you can find this in the
Manage App Info section of the StackMob Dashboard.
To use the proxy, we simply swap out the old one in our
~/StackMobDemo/app/store/Meats.js for this new one (don’t forget
to also require the class). It should now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
That’s it. Refreshing the app in your browser, you should now be able to add meats that get persisted to the server. Add a meat. Refresh the app, it should still be in the list. If you open StackMob’s Object Datastore Browser, you should be able to find your meat there as well.
Deploying to Production
Now that we have everything running in development mode, let’s get it running in production. This means two things: publishing your API to a production URL and having StackMob host your HTML5 app. The hosting is necessary in production for the same reason the Local HTML Runner was necessary in development: to appease the browser’s same origin policies.
The first step is to deploy our API to production. This is quick and painless, but will require a credit card. We will be selecting an absolutely FREE plan, but you need a credit card on file to create the account (presumably in case you go over your free API call limits and such).
To deploy your API, click on Deploy your App under Deploy. Select
Deploy API and continue. You’ll be prompted to select a plan. I recommend selecting the free one for now.
After you enter your credit card information, you will be able to continue your deployment.
When prompted, I created a new snapshot called “Test Production Deploy” and created API Version 1. All that’s left is adding a description and clicking deploy. If you’d like more info on this process, check out their docs on deploying.
Next we want to deploy our HTML5 app. To do this, we need to tie our StackMob account to a github repo holding our Sencha Touch application source (yes, you have to use github for HTML5 deployment to work). You can follow the excellent instructions StackMob offers by clicking on Manage HTML5 under Build.
Once you are connected to github, return to the HTML5 settings page and click the checkbox to enable HTML5 serving and API proxying in development.
Now you should be able to see your app in development mode, hosted by StackMob. Click on the link called
dev link in
the Enable/Disable section (from the image above).
Once you’ve confirmed that the deployment works in dev mode, enable production deployment by returning to the html settings page and select “Enable HTML5 in production” as shown below.
After you do this, and before you actually deploy, we’ll have to make one change to our Sencha Touch code and commit that change. In production mode, the server expects the client to send up the correct API version. In our case, this means we have to change “0” to “1” in our proxy. We also need to swap out our development public key for the production public key (which can also be found in the Manage App Info section of the StackMob Dashboard.). The new proxy should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Note that the only changes were setting
version=1 instead of
version=0, and changing the development public key
to the production public key.
Add, commit and push this change to github. StackMob should automatically pick up the change, and if you reload your development url (the one hosted by StackMob, not the one at localhost), the API requests to StackMob should fail with a response body describing that development keys can only be used with version 0. This is expected. It is quite unfortunate that you have to break your development app in version control if you want to deploy to production, but it is an irritation we’ll deal with for now (hopefully StackMob smooths this out soon).
Return to the Deploy your App page. This time, the
Deploy HTML option
should be enabled. Select it and click Deploy. The page will indicate it is deploying, but not autorefresh when it is
done. Wait a moment for all the bits to fly from one cloud to another, and then revist the
html settings page. Under the Enable/Disable section, there
should now be a link to your production app called
prod link. If you click this, you should see your app running
in production. Cool!
Making Something Meaningful
Hopefully this exercise has been interesting and has you itching to use these tools together for a real project. If you want a fully working version of the Sencha Touch app, clone our github repo. What we’ve done here is a good start, but it doesn’t cover everything you’ll need to create a real application that can authenticate users and take full advantage of the features StackMob offers. Keep a close eye on the Palomino Labs blog and our github page for more developments. We plan to release an open source Sencha Touch user extension for connecting to StackMob shortly. This will help you use StackMob in your Sencha Touch app without worrying about headers and tokens and the like.