Our application stores track informations about tracks an user has recorded with a GPS tracking device. For simplification we assume that the tracking data exists in a JSON format. This document is stored in the MongoDB with the additional information about the user who uploaded the track and an additional attribute about the position where the track starts.
With that track information stored in the MongoDB we start a search, that includes all tracks with startpositions within a certain radius. These Tracks are shown on a map.
The MongoDB part
If you have not installed MongoDB yet, download the latest version and install and start it. Now we have to start the interactive mongo shell. In the console you type following commands shown in Listing 1 to use the track collection and create a mongo spatial index.
use tracks;
db.track.ensureIndex( { start : "2d" } );
Listing 1: The command to creaet a MongoDB spatial index.
Now you can use the MongoDB spaitial feature. For example you can execute the command in Listing 2 to find the tracks with a nearby search to a given point.
1db.track.find( { start : { $near : [11.531439781188965,48.156700134277344] } } ).limit(2)
Listing 2: Find the two nearst tracks to the given point with the latitude and longitude.
Or you can execute the command in Listing 3 to find the tracks with a nearby search to a given point with a maximum distance. In the example we search in a distance of 1 kilometer. Therefore we have to divide the value 1 by 111 to get a maximum distance of 1 kilometer. For 1 mile we have to divide the value by 69.
1db.track.find( { start : { $near : [11.531439781188965,48.156700134277344] , $maxDistance : 0.009009009009009 } } ).limit(2);
Listing 3: Find the two nearest tracks to a given point with a maximum distance of 1 kilometer.
JSON Document and matching Java types
Lets assume the track information is a JSON document and has the structure shown in listing 4.
github:37aa01a6e243ce1f8274
Listing 4: JSON document structure
The corresponding Java object is shown in listing 5.
github:2501876b70be724f9bfb
Listing 5: Show the JSON document corresponding Java object
The serializable interface is not necessarily required in this example but maybe you want to use another frontend technology like wicket. Then at least you have to add the interface to your Java object.
The next listing 6 shows the Java object position that is used in the Java object track.
github:970ff2a53b0a9f114aa1
Listing 6: The position that is used in the track.
In this short example the user is not a Java object it’s only a attribute in the track that has a unique identifier.
Now we are ready to set up a Spring configuration to use MongoDB.
The Spring REST Web Service
In the first part we introduced the objects we want to store in the MongoDB. Now we need a service to do that for us. Lets have a look at the configuration and implementation of a REST Web service for this example.
The Listing 7 shows the configuration that is necessary in the web.xml to get Spring and and our Rest Service going.
github:196c65a9c3dd6ed29830
Listing 7: Shows the configuration of Spring and a REST Web service in the web.xml
With that configuration every request that calls an url under the path of /services delegetas to spring. For the servlet mapping with the name services a corresponding file with the nameservices-servlet.xml must be created. In that file nothing has to be configured. The interesting part is the applicationContext.xml file that is placed in the the folder src/main/resources/com/comsysto/labs/mobile/tracks/.
Listing 8 show the confiuguration of the applicationContext.xml. This is the base Spring configuration file in this example.
github:79b172a5c1edc4784846
Listing 8: Shows the configuration of the applicationContext.xml
Now lets come to the part where everything glues together. Therefore we have a look in our TrackService class shown in Listing 9 in the package org.comsysto.labs.web, where the services are placed which are autodetected by the component scan.
github:8701dd549eadd62d5ac7
Listing 9: The implementation of the TrackService.
The context component scan scans for all objects with the @Controller annotation and that is the target of our DispatcherServlet mapped in the web.xml under the path /services. The@RequestMapping(“/track”) maps the whole service under an additional sub-path /track. The annotation at the method getAll @RequestMapping(value = “/get”) maps the Method again. This means to call the getAll Method we have to use the path /services/track/get/.
With the attriubte method = RequestMethod.GET we define a Method that is only executed via a get request. The attribute produces = “application/json” defines that the result of the method is JSON. The result is automatically converted from a Java object to JSON by Spring. Therefore shown in listing 10 the Jar file Jackson must be present on the classpath.
github:9bc40566385c95d2cca4
Listing 10: Shows the Maven dependency for Jackson
The other methods are really straight forward and hopefully need not furhter documentation.
The UI
So now that we have a nice REST-Service we need some kind of UI. As we wanted to try some tools and frameworks we haven’t used yet, we decided to build a browser based app for mobile devices. So for this prototype we used:
- JQuery Mobile
- JQuery
- Google Maps API
- flot (to draw some charts)
- Tempo (for some templating)
You may have guessed the app we are building is basically a clone of one of the many sites likeGPSies or bikemap.net where you can share your gps tracks.
As our time was limited we started with four basic features:
- Upload tracks
- View tracks near your current location on a map
- View details of a track
- View the list of tracks you have uploaded
Each of the features (+ one main menu) requires an own page in the app, so we start with a JQuery Mobile multipage:
github:dbb69b2d94b081acde1c
Basic JQuery Mobile Mulitpage for the App (source)
In the partial source code of the index.html you can easily see, that we have two pages, identified by data-role="page"-Attribute and each contains a header (data-role="header") and adiv for the content (data-role="content"). On our main page with the id="home" we have just a list of links to the other pages. To link to a page, you just need a basic link where the href is a #followed by the id of the page (see lines 7 and 12). If you want to have a special animation for the transition you can simply add a data-transition-Attribute.
So now we have the basic html with some links and pages, but now we have to call the rest-service an get the stuff we want to display on the pages.To prepare the content of a page JQuery Mobile offers some events you can listen to. For our use case the page transition events (pagebeforeshow, pageshow, pagehide) and the page creation events (pagecreate and pageinit) are the most important. You should consider carefully what you do on each of the events (we have not done this carefully, so our code might not be perfect :-)).
For our page where we display the tracks near you on a map this looks basically like this:
github:ceea82800379f9c1eea5
If the page is first initialized the pageinit event ist triggered by JQueryMobile, if this happens we prepare our map and make sure it has the right size for the device. If the page is shown to the user (Event: pageshow) we finally make sure we get the current location of the user (if the browser supports this) and load the tracks to show on the map. To call our rest-service we simply use the well known $.getJSON():
github:59af1fc910652641232a
The other parts of the app are build the same way, so simply get the code from GitHub and have a look around.
JQuery Mobile is a basic and easy to use framework to create a webapp focused on mobile devices. Other frameworks like Sencha Touch may offer some morefunctionality. But I guess next time we should simply use a responsive design approach.