Tuesday 9 February 2016

Google Cloud ApiEndPoints and their Initial Denials

Once I thought of :
-> Creating an appengine project
-> Creating backend api for the same project (Part of Google Cloud EndPoints)
-> Integrating Cloud Endpoints with an Android App.

and then one day finally after a long struggle streak I was able to create both.
Well I was not here to make a fuss about it, instead I am here to let you know about a minor issue (Really. Can't say) and few more implementation tips down the road.

Assumptions :
A GAE python project ready to do render some html and ready endpoints to serve.
Reader must have played a little with Google App Engine with Python .


This blog post informs about three things :

1. Issue with Backend api : It would have been little cumbersome if followed conventional process instead of endpoints proto datastore library .
It's implementation alone could be a very big blog post. That's why I will not write about it. Please do it on your own.

2. Create discovery document and client libraries (specifically java lib for Android) to directly interact with app engine backend.

3. Respective android app's build.gradle changes while adding end point lib to an android app.

4. Points to remember before testing with local and live environment


Backend Api Issue

In app.yaml (configuration file which tells what (files) is responsible for whatever appears)
I added entries for both type of handlers
a. wsgi-compliant application : handler that make this project acts as a simple web application
b. endpoints handler : handler that contains the code for api end points

handlers:

# Endpoints handler
- url: /_ah/spi/.*
  script: myModule.endpointApp

# All Request Handler
- url: /.*
  script: myOtherModule.App


Above is the correct order so as to get both handler working simultaneously but if you had the changed the order of declaration, you would have lost endpoints.
Nothing would have appeared there.

Note of Caution : Above thing may or may not be correct for all as I don't see any logic in that or didn't found any post that could tell this thing but yes it did solved my problem.


Create discovery document and client libraries

While generating client libraries, you should be in the root of project to create Google discovery document

1. Generating Google Discovery Document using command :
$ endpointscfg.py get_discovery_doc your_module.YourServiceClass
implies
$ endpointscfg.py get_discovery_doc fileNameOfApiDeclaration.NameOfClassDecoratedWith@endpoints.api
or
$ endpointscfg.py get_discovery_doc --format rpc MyModule.MyApi

example : 
$ endpointscfg.py get_discovery_doc MyModule.MyApi


2. Generate client library bundle using command :
$ endpointscfg.py get_client_lib java -bs desired_client_bundle your_module.YourServiceClass
implies
$ endpointscfg.py get_client_lib java -bs desired_client_bundle fileNameOfApiDeclaration.NameOfClassDecoratedWith@endpoints.api

Following line didn't worked out
$ endpointscfg.py get_client_lib java -bs desired_client_bundle MyModule.MyApi

And then found following in some blog
$ endpointscfg.py get_client_lib java --hostname localhost:8080 MyModule.MyApi
which was modified to following
$ endpointscfg.py get_client_lib java MyModule.MyApi  
     
        // Last one worked out successfully

Note : $ endpointscfg.py means this tool to generate client lib is in your path. So you can run it directly from terminal else you will need to navigate to the directory where it is present.


In Android Side, don't go with the obsolete documentation on how to integrate client library with the project (means don't go adding multiple libraries and then also updating gradle and hence ending up with errors in count of hundreds)

Just get the source file from the extracted source code files from java client lib and add as source in your project

Respective build.gradle changes while adding end point lib to an android app

1. Initially add following repositories :

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
    }
}

apply plugin: 'com.android.application'

repositories {
    mavenCentral()
    mavenLocal()
}


2. Enable multidex

defaultConfig {
.......
        multiDexEnabled true
    }


3. Add the following dependencies :

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.android.support:multidex:1.0.0'
    compile ([group: 'com.google.api-client', name: 'google-api-client-android', version: '1.21.0'])
}


Testing from simulator/phone :

Url's to access api endpoint explorer on machine's localhost

1. Android Emulator : http://10.0.2.2:8080/_ah/api/
2. Genymotion : http://10.0.3.2:8080/_ah/api/
3. Physical Device : http://<your_machine_ip>:8080/_ah/api/

Note : Localhost or 127.0.0.1 refers to the emulated device itself, not the host the emulator is running on.

Once you are done uploading api endpoints code to Google api console, you can update url to

4. http://<project_id>.appspot.com/_ah/api/  (Project Id : post registration of your project on api console)


References : Cloud Api End Points

I know you have issues, please write down in the comments.