Reputation: 2019
so i have this lambda function which simply takes in a username as input, and goes to dynamoDB and grabs me the corresponding user in that table with all its attributes and logs it out. It works just fine, when i test in lambda. But, when i call the GET method through the sdk it doesn't work, and i dont understand why?
here is that function in lambda.
AWS.config.update(dynamoDBConfiguration);
var dynamodb = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event, context, callback)
{
console.log('entered exports handler');
console.log(JSON.stringify(event, null, ' '));
var userTableName = "usersTable";
var params = {
TableName : userTableName,
Key: {
"username": event.username
}
// AttributesToGet: [
// 'STRING_VALUE',
// /* more items */
// ],
};
dynamodb.get(params, function(err, data)
{ if (err) {
console.log(err);
callback(err);
} else {
console.log('great success: %j',data);
callback(null, data);
}
});
};
Now im trying to test this function in API getway so i can later deploy the sdk, but im having huge trouble figuring this out and hope you guys can help me out of what im missing!
Here is my GET method in my api
My method response
followed by my output model
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"username": {"type":"string"}
},
"title": "Output"
}
And here is the output i get when i test in Lambda (so works fine).
{
"Item": {
"experience": "0",
"displayName": "Archer",
"profileImageRef": "default",
"folders": {
"My Cards": {
"cards": {},
"name": "My Cards"
}
},
"birthdate": "1/1/1990",
"lastName": "Farooqui",
"username": "Archer",
"email": "[email protected]",
"firstName": "Qamar"
}
}
In android, here is my sdk i generated to put into my android studio.
MyUserClient sdk
@com.amazonaws.mobileconnectors.apigateway.annotation.Service(endpoint = "https://ow2zhiry2b.execute-api.us-west-2.amazonaws.com/awsTest")
public interface MyUserClient {
/**
* A generic invoker to invoke any API Gateway endpoint.
* @param request
* @return ApiResponse
*/
com.amazonaws.mobileconnectors.apigateway.ApiResponse execute(com.amazonaws.mobileconnectors.apigateway.ApiRequest request);
/**
*
*
* @param username
* @return Output
*/
@com.amazonaws.mobileconnectors.apigateway.annotation.Operation(path = "/", method = "GET")
Output rootGet(
@com.amazonaws.mobileconnectors.apigateway.annotation.Parameter(name = "username", location = "query")
String username);
}
Here is my out output class that was generated as well from the sdk
public class Output {
@com.google.gson.annotations.SerializedName("username")
private String username = null;
/**
* Gets username
*
* @return username
**/
public String getUsername() {
return username;
}
/**
* Sets the value of username.
*
* @param username the new value
*/
public void setUsername(String username) {
this.username = username;
}
}
And finally, i try to implement the GEt method in an async task, but it keeps crashing on a log statement.
class gateWayAsyncTask extends AsyncTask<Void, Void, Void>
{
private String userName;
public gateWayAsyncTask(String userName)
{
this.userName = userName;
}
@Override
protected Void doInBackground(Void... params)
{
creatingUser = clientFactory.build(com.awsTest.clientsdk.MyUserClient.class);
userName = creatingUser.rootGet("Archer").getUsername();
return null;
//clientFactory, and creatingUser variables are assigned in the parent class of this Async task don't worry.
}
@Override
public void onPostExecute(Void var)
{
Log.d("gateway","gateway succeded!");
Log.d("gateway",userName);
Toast.makeText(getBaseContext(),userName,Toast.LENGTH_LONG).show();
}
}
And here is my stackTrace
12-27 12:42:48.929 29019-29019/com.daprlabs.aaron.swipedeck2 E/UncaughtException: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:313)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:281)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
12-27 12:42:49.169 29019-29019/com.daprlabs.aaron.swipedeck2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.daprlabs.aaron.swipedeck2, PID: 29019
java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:313)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:281)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
12-27 12:43:14.387 29295-29295/com.daprlabs.aaron.swipedeck2 D/gateway: gateway succeded!
12-27 12:43:14.388 29295-29295/com.daprlabs.aaron.swipedeck2 E/UncaughtException: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:313)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:281)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
12-27 12:43:14.604 29295-29295/com.daprlabs.aaron.swipedeck2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.daprlabs.aaron.swipedeck2, PID: 29295
java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:313)
at com.daprlabs.aaron.zivitApp.Cognito.LogInZivit$gateWayAsyncTask.onPostExecute(LogInZivit.java:281)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access$500(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
UPDATE
So when i looked at cloud watch. It does show that my lambda function is being called and executed. But, i am not getting a return value. So something is wrong with my method response and/or integration response, but i am not sure what.
Upvotes: 1
Views: 2839
Reputation: 2019
So i solved the problem. Thanks to : @MikeD at AWS
If anyone wants to go from ANDROID -> API GATEWAY -> LAMBDA FUNCTION (end point,return a value) -> API GATEWAY -> ANDROID.
So heres a simple calculator lambda function:
console.log('Loading the Calc function');
exports.handler = function(event, context) {
console.log('Received event:', JSON.stringify(event, null, 2));
if (event.a === undefined || event.b === undefined || event.op === undefined) {
context.fail("400 Invalid Input");
}
var res = {};
res.a = Number(event.a);
res.b = Number(event.b);
res.op = event.op;
if (isNaN(event.a) || isNaN(event.b)) {
context.fail("400 Invalid Operand");
}
switch(event.op)
{
case "+":
case "add":
res.c = res.a + res.b;
console.log('WORKED FROM ANDROID!');
break;
case "-":
case "sub":
res.c = res.a - res.b;
break;
case "*":
case "mul":
res.c = res.a * res.b;
break;
case "/":
case "div":
res.c = res.b===0 ? NaN : Number(event.a) / Number(event.b);
break;
default:
context.fail("400 Invalid Operator");
break;
}
context.succeed(res);
};
Note that the variable name that i returned was res
. Which contains 3 numbers a,b, and c.
Now if you're going back from Lambda -> API gateway -> Android. In your integration response, in body mapping templates, in application/json I have the following template:
#set($allParams = $input.params())
{
"c" : $input.json('$.c')
}
Next, in your method response. Make sure you create a model (you can create models for your methods on the left side pane if you click on "models") for your method response and set it. Here is my output model:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"c": {"type":"string"}
},
"title": "Output"
}
I put this model in method response (repeating). AND notice how i have both c
in my model (in method response) AND in my body mapping template in my integration response. You can put: "c": {"type":"number"}
if you wanted.
Then when you deploy your api. It should work (if you're error was coming from the path: Lambda -> Api gateway -> Android).
Upvotes: 1
Reputation: 3745
It looks like your template in the integration response is empty and the Lambda output does not match your output model. On the integration response page, under Body Mapping Templates, select application/json on the left hand side. On the right hand side, enter a template body like this:
{ "username": $input.json('$.username') }
Also, try testing your API Gateway GET method via the test execute on the API Gateway console. If you're still having trouble, post the "Logs" output from the test invoke.
Upvotes: 1