Accessing a REST Based Database Backend From an Android* App

Objective

The objective of this article is to show a method for accessing a REST based database backend from an Android* app using MongoDB* and Spring IO*.

Table of Contents

  1. Introduction
  2. Tools Used
    1. Environment Setup
  3. Creating the Database
  4. Accessing the Database
    1. Setting up the Android Project & Permissions
    2. Parsing the JSON Response
    3. Manipulating the Database
  5. Summary
  1. Introduction

    As smartphone and tablet devices continue to grow in capabilities and popularity they are becoming a natural part of the everyday computing devices that we carry with us, know how to use, and rely on. This continues to provide opportunities for developers to innovate in software apps to take advantage of the unique portable platforms that mobile devices offer. Businesses are deploying tablet devices within their venues to enhance the customer experience and provide greater revenue opportunity. These devices have wireless connections that are capable of communicating to a backend server. A restaurant is an interesting example where tablet devices are being deployed to each table allowing the customer to browse the menu, order when they are ready, and pay their bill when they are finished. Having a centralized backend server that each tablet can communicate with allows for new opportunities in restaurant management, analytics, dynamic menus, and improved service. This article discusses a method for accessing a REST based database backend from an Android app. In particular, the first section of the article will discuss the tools used, environment setup, and how to create the restaurant database. The second section of the article will discuss accessing the database from an Android app.

  2. Tools Used

    When creating a proof of concept, having a flexible solution that allows you to get a server up and running quickly is desirable. The Spring IO platform is an open source solution that uses an Apache* Tomcat server and works with a variety of databases. Spring provides a framework that makes it easy to get an Android client and a Linux* server communicating over a REST interface. Components used for the server side consist of Ubuntu* Linux 14 for the operating system, MongoDB for the database, and the Spring IO platform for the REST service. The components used for the client side consist of Android Studio for the development IDE, the Spring REST Template API’s for talking to the server, the Jackson library for parsing the JSON response, and AVD for Android device emulation. Please see the links below to learn more about these components.

    http://www.ubuntu.com/

    http://www.mongodb.org/

    http://spring.io/

    http://spring.io/understanding/REST

    http://tomcat.apache.org/

    https://developer.android.com/sdk/installing/studio.html

    http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

    http://wiki.fasterxml.com/JacksonHome

    Environment Setup

    To get the environment setup for the server and client sides, please follow the steps below to install Linux, packages, and Android Studio.

    Install Ubuntu Linux 14 and connect to a local network.

    http://www.ubuntu.com/download

    Install packages from the terminal.

    MongoDB

    				sudo apt-get update
    
    				sudo apt-get install –y mongodb-org
    
    		git
    
    				sudo apt-get install git
    
    		gradle
    
    				sudo apt-get install gradle
    
    		curl
    
    				sudo apt-get install curl
    
    		java
    
    				sudo add-apt-repository ppa:webupd8team/java
    				sudo apt-get update
    				sudo apt-get install oracle-java8-installer
    		

    Install Android Studio

    https://developer.android.com/sdk/index.html

  3. Creating the Database

    The Spring starter project provides a nice starting point for creating a persistent backend with MongoDB that uses a http JSON interface for accessing the database.  It is easy to create a restaurant database that contains menu items and prices.  In addition, queries can be defined in a few lines of code.  See the steps below for creating the database, creating the queries, and running the service.

    Get the Spring starter project.

                git clone https://github.com/spring-guides/gs-accessing-mongodb-data-rest.git

    Change into the initial source directory.

                cd gs-accessing-mongodb-data-rest/initial/src/main/java/hello

    Create the Restaurant Object (Restaurant.java).

    		
    		import org.springframework.data.annotation.Id;
    		
    		public class Restaurant {
    
    			@Id private String id;
    
    			private String menuCategoryName;
    
    			private String menuItemName;
    
    			private String menuItemPrice;
    
    			private Boolean isSpecial;
    
    			private String specialmenuItemPrice;
    
    
    			public String getmenuCategoryName() {
    
    				  return menuCategoryName;		
    			
    			}
    
    			public void setmenuCategoryName(String menuCategoryName) {
    
    				  this.menuCategoryName = menuCategoryName;	  
    			
    			}
    
    			public String getmenuItemName() {
    
    				  return menuItemName;
    			
    			}
    
    			public void setmenuItemName(String menuItemName) {
    
    				  this.menuItemName = menuItemName;
    			
    			}
    
    			public String getmenuItemPrice() {
    
    				  return menuItemPrice;
    			
    			}
    
    			public void setmenuItemPrice(String menuItemPrice) {
    
    				  this.menuItemPrice = menuItemPrice;
    			
    			}
    
    			public Boolean getisSpecial(){
    
    				  return isSpecial;
    			
    			}
    
    			public void setisSpecial(Boolean isSpecial){
    
    				  this.isSpecial = isSpecial;
    			
    			}
    
    			public String getspecialmenuItemPrice(){
    
    				  return specialmenuItemPrice;
    			
    			}
    
    			public void setspecialmenuItemPrice(String specialmenuItemPrice){
    
    				  this.specialmenuItemPrice = specialmenuItemPrice;   
    			
    			}
    		
    		}  		
    		

    Create the Restaurant Database Repository with Queries (RestaurantRepository.java).

    The path of the database root on the server will be http://localhost:8080/menu.  Two queries are defined in the interface below. findByMenuItemName allows searches by menuItemName. findByMenuCategoryName allows searches by menuCategoryName.

    		
    		import java.util.List;
    		
    		import org.springframework.data.mongodb.repository.MongoRepository;
    
    		import org.springframework.data.repository.query.Param;
    
    		import org.springframework.data.rest.core.annotation.RepositoryRestResource;
    
     
    		@RepositoryRestResource(collectionResourceRel = "menu", path = "menu")
    
    		public interface RestaurantRepository extends MongoRepository {
    
    			List findByMenuItemName(@Param("name") String name);
    
    			List findByMenuCategoryName(@Param("name") String name);
    
    		}		
    		

    Create the Application class (Application.java).

    The application class shown below is the main entry point into the service and includes configuration for using Spring IO and MongoDB in the service.

    		
    		import org.springframework.boot.SpringApplication;
    
    		import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    
    		import org.springframework.context.annotation.Configuration;
    
    		import org.springframework.context.annotation.Import;
    
    		import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
    
    		import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
    
    		 
    		@Configuration
    
    		@EnableMongoRepositories
    
    		@Import(RepositoryRestMvcConfiguration.class)
    
    		@EnableAutoConfiguration
    
    		public class Application {		 
    
    			   public static void main(String[] args) {
    
    					  SpringApplication.run(Application.class, args);
    
    			   }
    		
    		}		
    		

    Change into the initial directory.

                    cd gs-accessing-data-mongodb/initial/

    Build It with Gradle.

                    ./gradlew build

    Run the server.

                    java –jar build/libs/<project_name>.jar

    Access the database.

                    curl http://localhost:8080/menu

    View the JSON response.

    In this example, the database contains a Tacos menu item:

    		
    		{
    
    			"_links" : {
    
    			"self" : {
    
    			"href" : "http://localhost:8080/menu{?page,size,sort}",
    
    			"templated" : true
    
    				},
    
    			"search" : {
    
    			"href" : "http://localhost:8080/menu/search"
    
    				}
    
    			},
    
    			"_embedded" : {
    
    			"menu" : [ {
    
    			"menuCategoryName" : "Mexican",
    
    			"menuItemName" : "Tacos",
    
    			"menuItemPrice" : "$15",
    
    			"isSpecial" : false,
    
    			"specialmenuItemPrice" : "$7.50",
    
    			"_links" : {
    
    				"self" : {
    
    					"href" : "http://localhost:8080/menu/5488c2ee44ae7e3fab758edd"
    
    					}
    
    				}
    
    			} ]
    
    		},
    
    			"page" : {
    
    			"size" : 20,
    
    			"totalElements" : 1,
    
    			"totalPages" : 1,
    
    			"number" : 0
    
    			}
    
    		}		
    		
  4. Accessing the Database

    4.1. Setting up the Android project permissions & dependencies

    Launch Android Studio and create a new project. Once the new project is created it is necessary to add the internet permission to the manifest, Spring Rest Template dependency, and Jackson JSON parsing dependency as shown below.

    Add the Internet Permission to the manifest (AndroidManifest.xml).

                 <uses-permission android:name="android.permission.INTERNET">

    Add the RestTemplate and Jackson library dependencies (build.gradle).

    apply plugin: 'com.android.application'.

    		
    		android {
    
    			compileSdkVersion 21
    
    			buildToolsVersion "21.1.1"
    
     
    			defaultConfig {
    
    				applicationId "com.example.test.myapplication"
    
    				minSdkVersion 7
    
    				targetSdkVersion 21
    
    				versionCode 1
    
    				versionName "1.0"
    
    			}
    
    			buildTypes {
    
    				release {
    
    					minifyEnabled false
    
    					proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    
    				}
    
    			}
    
    			packagingOptions {
    
    				exclude 'META-INF/ASL2.0'
    
    				exclude 'META-INF/LICENSE'
    
    				exclude 'META-INF/license.txt'
    
    				exclude 'META-INF/NOTICE'
    
    				exclude 'META-INF/notice.txt'
    
    			}
    
    		}
    		
    		dependencies {
    
    			compile 'com.android.support:appcompat-v7:+'
    
    			compile fileTree(dir: 'libs', include: ['*.jar'])
    
    			compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'
    
    			compile 'com.fasterxml.jackson.core:jackson-databind:2.3.2'
    
    		}
    		

    4.2. Parsing the JSON response

    The app needs a way to understand the JSON response and be able to parse it.  An approach is to create Java objects that will represent the response.  The Jackson library is a convenient library that can be used to parse the JSON response and use the Java objects.  To use this library, Jackson annotations are added to the Java objects.  The Java objects can be manually created, but there is a handy tool out there that will assist with creating them for a given JSON response at http://www.jsonschema2pojo.org/. The Menu Class for this example is shown below with the Jackson annotations.

    		
    		package com.example.test.myapplication;
    
    		import com.fasterxml.jackson.annotation.JsonAnyGetter;
    
    		import com.fasterxml.jackson.annotation.JsonAnySetter;
    
    		import com.fasterxml.jackson.annotation.JsonIgnore;
    
    		import com.fasterxml.jackson.annotation.JsonInclude;
    
    		import com.fasterxml.jackson.annotation.JsonProperty;
    
    		import com.fasterxml.jackson.annotation.JsonPropertyOrder;
    
    		 
    		import java.util.HashMap;
    
    		import java.util.Map;
    
    			@JsonInclude(JsonInclude.Include.NON_NULL)
    
    			@JsonPropertyOrder({
    
    				"menuCategoryName",
    
    				"menuItemName",
    
    				"menuItemPrice",
    
    				"isSpecial",
    
    				"specialmenuItemPrice",
    
    				"_links"
    
    			})
    
    		public class Menu {
    
    			@JsonProperty("menuCategoryName")
    
    			private String menuCategoryName;
    
    			@JsonProperty("menuItemName")
    
    			private String menuItemName;
    
    			@JsonProperty("menuItemPrice")
    
    			private String menuItemPrice;
    
    			@JsonProperty("isSpecial")
    
    			private Boolean isSpecial;
    
    			@JsonProperty("specialmenuItemPrice")
    
    			private String specialmenuItemPrice;
    
    			@JsonProperty("_links")
    
    			private Links_ Links;
    
    			@JsonIgnore
    
    			private Map additionalProperties = new HashMap();
    	
    			
    			@JsonProperty("menuCategoryName")
    
    			public String getMenuCategoryName() {
    
    				return menuCategoryName;
    
    			}
    
     
    			@JsonProperty("menuCategoryName")
    
    			public void setMenuCategoryName(String menuCategoryName) { this.menuCategoryName = menuCategoryName; }
    
     
    			@JsonProperty("menuItemName")
    
    			public String getMenuItemName() {
    
    			return menuItemName;
    
    			}
    
     
    			@JsonProperty("menuItemName")
    
    			public void setMenuItemName(String menuItemName) {
    
    				this.menuItemName = menuItemName;
    
    			}
    
     
    			@JsonProperty("menuItemPrice")
    
    			public String getMenuItemPrice() {
    
    				return menuItemPrice;
    
    			}
    
     
    			@JsonProperty("menuItemPrice")
    
    			public void setMenuItemPrice(String menuItemPrice) {
    
    				this.menuItemPrice = menuItemPrice;
    
    			}
    
     
    			@JsonProperty("isSpecial")
    
    			public Boolean getIsSpecial() {
    
    				return isSpecial;
    
    			}
    
     
    			@JsonProperty("isSpecial")
    
    			public void setIsSpecial(Boolean isSpecial) {
    
    				this.isSpecial = isSpecial;
    
    			}
    
     
    			@JsonProperty("specialmenuItemPrice")
    
    			public String getSpecialmenuItemPrice() {
    
    				return specialmenuItemPrice;
    
    			}
    
     
    			@JsonProperty("specialmenuItemPrice")
    
    			public void setSpecialmenuItemPrice(String specialmenuItemPrice) { this.specialmenuItemPrice = specialmenuItemPrice; }
    
     
    			@JsonProperty("_links")
    
    			public Links_ getLinks() {
    
    				return Links;
    
    			}
    
     
    			@JsonProperty("_links")
    
    			public void setLinks(Links_ Links) {
    
    				this.Links = Links;
    
    			}
    
     
    			@JsonAnyGetter
    
    			public Map getAdditionalProperties() {
    
    				return this.additionalProperties;
    
    			}
    
    
    			@JsonAnySetter
    
    			public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); }	 
    
    		}	
    		

    4.3. Manipulating the database

    The database is accessed through a simple REST based http interface for doing primitive operations such as POST, PUT, GET, and DELETE.  The RestTemplate provides a nice API for performing these operations in an AsyncTask allowing the app to stay responsive.  The code snippets below show an example of how to access and manipulate the restaurant database.

    Creating a RestTemplate instance and server path.

                 private RestTemplate rest = new RestTemplate();

                 private String url = "http://192.168.1.110:8080/menu/";

    Enabling the Jackson library JSON parsing.

    RestTemplate rest = new RestTemplate();

    rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

    Creating a Menu Item instance:

    		
    		Menu myMenuItem = new Menu();
    
                 myMenuItem.setMenuCategoryName("Mexican");
    
                 myMenuItem.setMenuItemName("Tacos");
    
                 myMenuItem.setMenuItemPrice("$15");
    
                 myMenuItem.setIsSpecial(false);
    
                 myMenuItem.setSpecialmenuItemPrice("$7.50");		
    		

    Adding a new menu item to the database (POST)

    Adding a new menu item is a POST operation that passes a new menu item to the task.

    		
    		new Http_POST_Task().execute(myMenuItem);
    		
    		private class Http_POST_Task extends AsyncTask {
    
    			@Override
    
    			protected Void doInBackground(Menu... menuItem) {
    
    				try{
    
    				   rest.postForObject(url,menuItem[0],Restaurant.class);
    
    				}
    
    				catch (Exception e) {
    
    					Log.e("MainActivity", e.getMessage(), e);
    
    				}
    
    				return null;
    
    			}
    
    		}	
    		

    Deleting a menu item from the database (DELETE).

    Deleting a menu item is a DELETE operation that passes the menu item to the task for deleting.

    		
    		new Http_DELETE_Task().execute(myMenuItem);
    		
    		private class Http_DELETE_Task extends AsyncTask {
    
    			@Override
    
    			protected Void doInBackground(Menu... menuItem) {
    
    				try {
    
    					//DELETE
    
    					String urlStr = menuItem[0].getLinks().getSelf().getHref();
    
    					rest.delete(new URI(urlStr));
    
    				}
    
    				catch (Exception e) {
    
    					Log.e("MainActivity", e.getMessage(), e);
    
    				}
    	 
    				return null;
    
    			}
    
    		}
    		
    Searching for a menu item in the database (GET) Searching for a menu item performs the findByMenuItemName query to get the specified menu item:
    		try {
    
    			myMenuItem = new Http_findByMenuItemName_Task().execute("Tacos").get();
    
    			} catch (InterruptedException e) {
    
    				e.printStackTrace();
    
    			} catch (ExecutionException e) {
    
    				e.printStackTrace();
    
    			}
    
    		private class Http_findByMenuItemName_Task extends AsyncTask {
    
    			@Override
    
    			protected Menu doInBackground(String... menuItemName) {
    
    				try	{
    
    					String queryURL = url+"search/findByMenuItemName?name="+menuItemName[0];
    
    					Restaurant restaurant = rest.getForObject(queryURL, Restaurant.class);
    
    					return restaurant.getEmbedded().getMenu().get(0);
    
    				}
    
    				catch (Exception e) {
    
    					Log.e("MainActivity", e.getMessage(), e);
    
    				}
    
    				return null;
    
    			}
    
    		}	
    		

    Updating an existing menu item in the database (GET) (PUT).

    Updating an existing menu item performs a GET query operation to get the existing menu item:

    		
    		try {
    
    			myMenuItem = new Http_findByMenuItemName_Task().execute("Tacos").get();
    
    			} catch (InterruptedException e) {
    
    				e.printStackTrace();
    
    			} catch (ExecutionException e) {
    
    				e.printStackTrace();
    
    			}		
    		

    The existing menu item is modified and then a PUT operation is performed.

    		
    		myMenuItem.setMenuCategoryName("Chinese");
    
    		myMenuItem.setMenuItemName("Crab Puffs");
    
    		myMenuItem.setMenuItemPrice("$7");
    
    		myMenuItem.setIsSpecial(true);
    
    		myMenuItem.setSpecialmenuItemPrice("$5");
    
    		new Http_PUT_Task().execute(myMenuItem);
    
    	private class Http_PUT_Task extends AsyncTask<Menu,Void,Void> {
    
            @Override
    
            protected Void doInBackground(Menu... menuItem) {
    
                try {
    
    				String urlStr = menuItem[0].getLinks().getSelf().getHref();
    
    				rest.put(new URI(urlStr),menuItem[0]);
    
                }
    
                catch (Exception e) {
    
                    Log.e("MainActivity", e.getMessage(), e);
    
                }
    
                return null;
    
            }
    
        }	
    	

Summary

This article showed a method for accessing a REST based database backend from an Android app. The tools used and set up of the environment was first discussed.  Creating an example restaurant database with queries using MongoDB and Spring IO was shown.  The article concluded showing how to use the Spring IO framework in an Android app to parse the JSON response & manipulate the database.

++This sample source code is released under the Intel Sample Source License.

About the Author

Mike Rylee is a Software Engineer with Intel Corporation.  He currently works on app enabling for Android.

For more complete information about compiler optimizations, see our Optimization Notice.