Use empty strings with AWS Amplify API and DynamoDB - amazon-web-services

I started to use AWS Amplify for a web app.
I configured AppSync GraphQL using a DynamoDB datasource as suggested by the Getting Started tutorial.
One of my values is an empty string and I get this error when trying to do an insert
"One or more parameter values were invalid: An AttributeValue may not contain an empty string (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 0000000SOMETHING0000000)"
It seems it can be solved by passing the option convertEmptyValues: true to the DynamoDB client. Do you know how I can pass a such option using AppSync ?

I have not found such an option in the Amplify codebase. I hope it will be added.
In the meantime, I pass my emptiable strings this way:
{
id: id,
title: title,
description: description || null
}

Related

CREATE_FAILED ; <name> ; AWS::AppSync::Resolver ; The specified key does not exist. (Service: Amazon S3; Status Code: 404; Error Code: NoSuchKey;

I'm trying to run amplify push after creating a resolver. The initial error is:
CREATE_FAILED ; BatchAddTodosResolver ; AWS::AppSync::Resolver ; The specified key does not exist. (Service: Amazon S3; Status Code: 404; Error Code: NoSuchKey;
This is followed by these errors:
UPDATE_FAILED ; CustomResourcesjson ; AWS::CloudFormation::Stack ; Embedded stack arn:aws:cloudformation:eu-west-2::stack/amplify--dev-153155--1BXI79QFMXX10-CustomResourcesjson-8BPZCI05LJ2U/cdd9bb90-1729-11ed-8fd7-06e957346298 was not successfully updated. Currently in UPDATE_ROLLBACK_IN_PROGRESS with reason: The following resource(s) failed to create: [BatchAddTodosResolver].
UPDATE_FAILED ; CustomResourcesjson ; AWS::CloudFormation::Stack
I've done the following (following this tutorial):
Create Amplify app with amplify init and amplify add api; amplify add auth;
Create mutation in schema.graphql:
input CreateTodoInput {
id: ID
title: String!
description: String
completed: Boolean
}
type Mutation {
batchAddTodos(todos: [CreateTodoInput]): [Todo]
}
amplify update api
Add this code to amplify/api/<your-api-name>/stacks/CustomResources.json
Create amplify/backend/api/<your-api-name>/resolvers/Mutation.batchAddTodos.req.vtl (as per the example and amplify/backend/api/<your-api-name>/resolvers/Mutation.batchAddTodos.res.vtl (as per the example below the req.vtl example)
Update the references to the DynamoDB table in the req.vtl
amplify push
There was an item in the instructions that I could not follow:
Note: You need to run amplify add api without the batchAddTodos mutation first and then add it via amplify update api.
I assumed that amplify update api was wrong, since we'd already set up the API and the article provided no further instructions to indicate why we would want to run amplify update api. I think the author meant that the we would add the changes by running amplify push - but perhaps this is where I've gone wrong and am getting the
I've got this working. I tried repeating the steps and noticed that if I don't update the schema.graphql correctly then the error above results. Perhaps I had not named the mutation correctly, or possibly forgotten to save my schema.graphql file before running amplify push?

Changing logical ID of AppSync resolver result in error upon deploy (CDK)

When I change a resolver ID as follows:
From:
new appsync.Resolver(scope, "SuperResolver",.....
To:
new appsync.Resolver(scope, "MegaResolver",.....
i.e from "SuperResolver" to "MegaResolver" and then I run cdk deploy, I get the following error:
Only one resolver is allowed per field. (Service: AWSAppSync; Status Code: 400; Error Code: BadRequestException; Request
ID: fd68b0ff-38a5-4149-a797-138baf6a836c; Proxy: null
It appears that instead of replacing the ID of the existing resolver (or deleting the construct with the old ID and creating a new one with the new ID), AppSync tries to attach a new resolver to the GQL field.
But the error is rather bogus, so my assumption may be incorrect.
Did anyone experience such a problem?
Any help would be much appreciated :)
It's because CloudFormation firstly creates new resources before it deletes old ones. In this case you have to delete resolver in one deploy and add new one in the next.

AWS CDK - Getting InvalidRouteTableId.Malformed when creating Route Table

I am getting the below exception when trying to create a Route Table through AWS CDK library. I went through the naming standards and am making sure to follow it. From the exception message, it seems to be removing the "-" from the id I provided. Please let me know what could be the issue
CDK statement for creating the Route Table. I am passing the vpc id as required:
aws_cdk.aws_ec2.CfnRouteTable(self,id="rtb-0ad2be93946c6be65",vpc_id=vpc.vpc_id)
Exception:
Invalid id: "rtb0ad2be93946c6be65" (Service: AmazonEC2; Status Code: 400; Error Code: InvalidRouteTableId.Malformed; Request ID: 342b6743-b0e3-4ceb-b86d-3ae9564f7923; Pr
oxy: null)
The issue turned out nothing to do with the way I was creating the route table. But rather what I was doing to create the Route later for that route table. I had to pass the route table using ".ref" rather than ".logical_id"
I am using the below code for creating the table and route now and its working fine:
route_table = aws_cdk.aws_ec2.CfnRouteTable(self,id="rtb-0ad2be93946c6be65",vpc_id=vpc.vpc_id)
target_route = aws_ec2.CfnRoute(self,id="someroutename",route_table_id=route_table.ref,gateway_id=vpn_gateway.ref,destination_cidr_block="10.0.0.0/22")
But, I do think CDK can do better with error handling

AWS DynamoDB Requested resource not found

I am trying to connect my app to DynamoDB. I have set everything up the way Amazon recommends. But i still keep getting the same error over and over again:
7-21 11:02:29.856 10027-10081/com.amazonaws.cognito.sync.demo E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.amazonaws.cognito.sync.demo, PID: 10027
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:304)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException: Requested resource not found (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: GIONOKT7E3AMTC4PO19CPLON93VV4KQNSO5AEMVJF66Q9ASUAAJG)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:710)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:385)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:196)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:2930)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.java:930)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper$SaveObjectHandler.doUpdateItem(DynamoDBMapper.java:1173)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper$2.executeLowLevelRequest(DynamoDBMapper.java:873)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper$SaveObjectHandler.execute(DynamoDBMapper.java:1056)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.save(DynamoDBMapper.java:904)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.save(DynamoDBMapper.java:688)
at com.amazonaws.cognito.sync.Utils.FriendsSyncManager.initalize_credentialprovider(FriendsSyncManager.java:43)
at com.amazonaws.cognito.sync.ValU.FriendListActivity$SyncFriends.doInBackground(FriendListActivity.java:168)
at com.amazonaws.cognito.sync.ValU.FriendListActivity$SyncFriends.doInBackground(FriendListActivity.java:160)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
 
         
What could be the solution?   
Okey it seems you need to add:
ddbClient.setRegion(Region.getRegion(Regions.EU_WEST_1));
// Add correct Region. In my case its EU_WEST_1
after the following line:
AmazonDynamoDBClient ddbClient = new AmazonDynamoDBClient(credentialsProvider);
Now it works. The table was successfully created.
Have a nice day and thanks!
It seems that the table you are trying to connect to doesn't exist. Verify the table name in your code agains the name of the table you created.
Please note that table name is case sensative.
You need to check a few things:
Check your credentials in your code:
private static String awsSecretKey = "your_secret_key"; //get it in AWS web UI
private static String awsAccessKey = "your_access_key"; //get it in AWS web UI
Check your Region code and set correct value:
client.setRegion(Region.getRegion(Regions.US_EAST_1));
You can get this value from your AWS Web Console. Details
Check does you have already created DynamoDB table & indexes under your Region.
If no, check your code
#DynamoDBTable(tableName = "Event")
public class Event implements Serializable {
public static final String CITY_INDEX = "City-Index";
public static final String AWAY_TEAM_INDEX = "AwayTeam-Index";
And create manualy from AWS Console or somehow else your table (Event in my case) and indexes (City-Index, AwayTeam-Index in my case). Please note - table and index name in case sensative.
Good sample - https://github.com/aws-samples/lambda-java8-dynamodb
From the docs it's either you don't have a Table with that name or it is in CREATING status.
I would double check to verify that the table does in fact exist, in the correct region, and you're using an access key that can reach it.
Or you might select the wrong region.
Along with #Yuliia Ashomok's answer
AWS C++ SDK 1.7.25
Aws::Client::ClientConfiguration clientConfig;
clientConfig.region = Aws::Region::US_WEST_2;
If using Spring boot, you can configure the region via application properties:
in src/main/resources/application.yaml
cloud:
aws:
region:
static: eu-west-1
As this problem is some what platform agnostic. For anyone coming at the same problem from .NET/C# ...
You can instantiate your client with the Endpoint in the constructor:
AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials, Amazon.RegionEndpoint.USEast1 );
I would have assumed that this would have been brought in from you AWS Profile but seems not although you could do something like this, where profile is imported from your SharedCredentialsFile:
new AmazonDynamoDBClient(credentials, profile.Region );
If you are sure that you have already created the table in DynamoDB but still getting this error. That means you may chances that your region is not correct. Just look at the top right corner of your AWS portal, with your profile dropdown. One another dropdown will give you the option to select your region. And now follow the process again with the right region.
Hope this works. This works for me.

Apache Camel with AWS DynamoDB (aws-ddb) URI parameters

I'm trying to route messages from AWS SQS to AWS Dynamo DB using Apache Camel using the following route definition:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="aws-sqs://my_queue?accessKey=${aKey}&secretKey=RAW(${sKey})&maxMessagesPerPoll=10&deleteAfterRead=true"/>
<unmarshal>
<camel:json library="Jackson"/>
</unmarshal>
<to uri="aws-ddb:my_table?accessKey=${aKey}&secretKey=RAW(${sKey})&readCapacity=15&writeCapacity=100&operation=PutItem"/>
</route>
</camelContext>
But on execution Camel complains that the Dynamo Db URI is missing some required parameters:
org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: aws-ddb://table?amazonDDBClient=%23ddbClient&amazonDdbEndpoint=ap-southeast-2&readCapacity=10&writeCapacity=10 due to: Status Code: 400, AWS Service: AmazonDynamoDB, AWS Request ID: KHA79STK78SHC2BG2R8HLPF7RJVV4KQNSO5AEMVJF66Q9ASUAAJG, AWS Error Code: ValidationException, AWS Error Message: 2 validation errors detected: Value null at 'keySchema.hashKeyElement.attributeName' failed to satisfy constraint: Member must not be null; Value null at 'keySchema.hashKeyElement.attributeType' failed to satisfy constraint: Member must not be null
The fun part is, these 2 parameters are not described anywhere in Camel DDB doc. I spent some time browsing the Camel source and found 2 undocumented URI parameters: keyAttributeName & keyAttributeType, which worked perfectly for me. (I hope this find of mine helps someone as well).
Now even more fun is that these should not be requested for inserting items into Dynamo DB, but I can no longer reproduce this error when I remove the 2 undocumented params from the URI.
So my questions are:
Why did AWS request hash key data for PutItem requests?
Why can't I reproduce this behaviour any longer?
I could not find any hints either in Camel or AWS documentation, googling only uncovers a handful of irrelevant results.
Could it be that you didn't specify the region your Dynamo DB table belongs too?
I had the same problem and found that my data was stored in the US East region instead of the region I had my table in.
And to answer your two questions then it would be:
Because the table didn't exist, Camel AWS tries to create it for you as can be seen in the DdbEndpoint class. Personally I don't like this side effect but it is there :/
This means that those attributes suddenly got required.
You cannot reproduce it after the first try because now it is created :)
Delete the table and you will be able to reproduce it.
So my solution was to specify my own AmazonDynamoDBClient with the region set and then put it in the registry so it could be found from the route with the parameter: amazonDDBClient
Hope it helps!