The last couple of months I've been working on my bachelor project to finish my bachelor computer science. Together with Tom Verhoeff, Jos Kraaijeveld, Jochem Toolenaar and Oana Nitu, I participated in the Imagine Cup 2011. We formed team O!ife and our project was called the City Cloud. The City Cloud is a cloud computing platform that allows different kinds of data generated by the city, its inhabitants, companies and its government to be easily accessed by developers to create new innovative technologies and solutions. You can find more about the City Cloud on the O!ife blog.
This post is one in a series on how we built the City Cloud and everything around it. The focus of these posts will be on the technical aspects of the City Cloud. It will also cover some problems we encountered during development and the solutions we used to tackle them. At this moment I have no idea how many parts will follow. We've came across lots of different problems and used lots of technologies, so I will write another part whenever I have the time and when I think the topic is interesting enough for other developers. The first part will cover the overall architecture of the system to establish a background for other posts.
When we started the City Cloud project we thought of it as a developer platform for a city. The main goal should be to offer the correct tools for developers to build next generation ubiquitous applications: it should be easy to expose new datasets through the system and the development of applications using these datasets should not require large investments in both terms of infrastructure and programming skills.
In the design phase we divided the system up into three parts: the cloud framework, the mobile platform and the website/webapplication. The framework was the heart of the system and was designed to run in the Azure cloud. Its responsibility was to present the data that is part of the system in an easy and consistent way and offering an all-in-one solution for data and app storage. The mobile platform and the website/webapplication functioned as two different portals to the data and the apps. The website should give general information on cities and should show the datasets and applications available. It should also provide developers with documentation and best practices on how to make use of the platform's capabilities in the best possible way. The mobile framework should be the main portal to the end user in a city. It should give an user specific information on data and apps based on his current location. With more and more smartphones sold every day, smartphones offered a great opportunity to be the number one entry point to the City Cloud.
The framework should expose data in an easy way. To achieve this we decided to go with an OData webservice running in an Azure webrole. Besides being a Microsoft technology which counts for the Imagine Cup, OData offers an excellent way to expose datasets and besides that offers great possibilities to perform transformations and filtering on the returned data. Another advantage is the great tools available to develop OData webservices and to consume them on almost all major platforms. To get data into the City Cloud framework we invented "connectors". To expose a new dataset through the framework all a developer would need to do is build a connector that allows the City Cloud to retrieve data from their data source. This connector should implement some interface, provide the system with some description of the data structures and it should all magically come to life.
Website and webapplication
To give developers and users an overview of the data and applications already in the system we built the website including a Silverlight webapplication. The webapplication was meant to be used as an explorer for the webservice. In this way everybody could take a quick look into the system to browse data. It also offered the possibility to plot these datasets on a map.
Developers could use the website to submit new applications and new connectors to the system. Because of the extensibility model we felt the need to building a validation step to verify the working of the newly submitted parts in the framework. To validate new submissions we made use of a core feature of the azure platform: a worker role. In Windows Azure a worker role is meant to be used for background processing or other long running tasks. In the cloud framework we used a worker role to validate a submission and to make the required changes to the framework to add a new connector or building block.
At the end of the design phase the overall system architecture looked a lot like a high level Model-View-Controller architecture. The website and the mobile platform functioned as the views, while the framework holds the current state of the system and functioned as the model. The worker role was used to change the state of the framework and can thus be seen as the controller. The following image shows the high level architecture in a graphical way:
I hope this gives a good overview of the system we built the last couple of months. Unfortunately no code yet, but I will save that for the next part.
Today I was working on some kind of WCF Data Service, when suddenly while I was testing my data service this error came up:
When I see this kind of errors, I'm always wondering if there is a way that my code can give me some more information on this error. Sure it can! All you need to do is add the following attribute to your service class:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
I compiled my projects again and ran it. This time I was given some more information on the error.
The additional information the exception gave me, immediately revealed the problem. I changed the constructor of my 'ExampleContext' from an empty constructor to a constructor that required one argument and since WCF Data Service still wants to call my empty constructor it throws an exception because it can't find the empty constructor.
I was wondering why this constraint wasn't enforced at compile time instead of runtime. The WCF people could have defined the DataService class as follows,
public class DataService<T> : IRequestHandler, IDataService where T : new()
which enforces every T to have an empty constructor, but they defined it as
public class DataService<T> : IRequestHandler, IDataService
without the empty constructor requirement. Why would they have done that? Of course this could be an issue with the DataService class, but as Scott Hanselman said at the Dav Days 2011: "Don't blame Microsoft for your bad design." Why would you enforce every T to have an empty constructor? It is just removing flexibility. It was more likely that I did something wrong, so I googled on "dataservice context needs empty constructor". The second hit took my attention, because it talked about an "IDataContextProvider in a constructor", so I clicked on it.
The blog post talked about the usage of Inversion of Control in a webservice and the code in the blog post showed a method called "CreateDataSource()" that was overriden from its base class "DataService" and returned the type T. This was a great solution because know I could call my custom constructor myself. While writing the code to override that method, another thought came up in my head. Of course removing the empty constructor an adding a custom one leads to problems for data services, because it doesn't know about all parameters of the custom constructor and their constraints.