It’s about time I started talking about actually building the application, so I’m going to start looking at it from the other end, for a while. The goal is to build a desktop/mobile application that can load GPS data for bicycle rides, process it to determine the per-segment and overall power production of the rider, and display this information.
There are two pillars in the application, the client and services.
This is a high-level state diagram illustrating the paths through the application. Some comments:
- Every interaction in the application requires the user to be signed in, so this state is checked at every transition. Because it is implicit, it is not included here. When a transition is attempted and the user is found to be signed out, they are redirected to the Login view.
- The user can sign out, or return to the menu from any screen. Returning to the menu while editing persistent information effectively cancels the edit.
- The Login view does what it says — if the user is not logged in, this screen allows them to do so, or provides a link to the Registration page. When the credentials are submitted and the user is authenticated, they are redirected to the Menu.
- The Registration view allows the user to choose a username and password, and to enter some preliminary data, such as gender, body weight and whatever else might be useful for the application’s purposes. When the user is registered, the application restarts. At this stage, complex email validation schemes are out of scope.
- The main Menu provides access to the different features of the application. The user can load ride data, edit their profile, add or edit bicycles or view existing rides.
- The Ride Source Selection screen enables the rider to choose the source of the data they’d like to process. Once the data has been processed, the user is redirected to the Ride View (below). The three source options are:
- GPX File — a GPX file will be uploaded and processed by the application.
- GPX URL — a GPX file will be downloaded from a URL and processed.
- Strava Ride — a GPX file representing a ride will be downloaded from Strava and reprocessed.
- The Ride List provides a list of rides that have already been processed selecting a ride directs the user to the ride view.
- The Ride View displays speed, power and other metrics from the ride (layout yet to be determined), along with a map of the ride.
- The User Information view provides access to the user’s details, some of which will have been entered in the registration phase.
- The Bike List is a list of bikes that the rider may use. When a ride is processed, it is important to know some details about the bike, particularly the type (road or mountain bike) and weight. This view provides the ability to add and edit bikes.
- The Bike Information view provides access to information for a single bike.
The Bike Information, User Information, GPX URL, and Strava Ride features have yet to be implemented. Everything else is in a workable, if not exactly presentable, state — but you’ll have to take my word for that right now!
The Server Side
Services are provided by a Servlet running on a Tomcat instance on a Linode. The data store is PostgreSQL database with the PostGIS and pgRouting extensions. REST capability and JSON serialization/deserialization are provided by an existing library that I designed for previous project. Java has a standard REST application development framework (JAX-RS), which does essentially the same job as my own framework. But time is of the essence, and learning a new framework, while worthwhile, would have taken too much time.
REST is an oft-touted, but poorly understood (at least by me, initially) paradigm for building Web-accessible APIs. Essentially, it consists of nouns (resources) and HTTP verbs, such as PUT, POST, DELETE and GET. Nouns are realized as URLs, in the form,
In this instance, “property” is an attribute of the “thing” identified by “id,” which can be mutated by PUTting a value, or retrieved by GETting it.
Like many things in programming it is easy to claim to have implemented a REST API, and yet to have a hybrid system where the resource dictionary is polluted with verbs. For example, one might implement the login API using the intuitive URL,
and POST the user’s credentials to it. This is not RESTful, because “login” is a verb, not a noun. This URL is not a resource. A more RESTful way would be to POST the user’s credentials to the sessions list, which would have the effect of creating a new session and returning a unique token:
The user could then retrieve (GET) the session resource using a token returned by the PUT action:
Since one of REST’s objectives is to be stateless, the use of session variables and cookies to preserve the user’s application state is deprecated — this information should be stored on the client and passed explicitly through resource requests.
But why do it this way? As with most constrained APIs, the ultimate goals are simplicity, maintainability and scalability. More generally, communication between tiers in an application (or a society) is easier when the the lingua franca is standardized.
The next post will feature a discussion of the processing system.