= AWS DynamoDB Component
:doctitle: AWS DynamoDB
:shortname: aws2-ddb
:artifactid: camel-aws2-ddb
:description: Store and retrieve data from AWS DynamoDB.
:since: 3.1
:supportlevel: Stable
:tabs-sync-option:
:component-header: Only producer is supported
//Manually maintained attributes
:group: AWS
:camel-spring-boot-name: aws2-ddb

*Since Camel {since}*

*{component-header}*

The AWS2 DynamoDB component supports storing and retrieving data from/to
https://aws.amazon.com/dynamodb[Amazon's DynamoDB] service.

Prerequisites

You must have a valid Amazon Web Services developer account, and be
signed up to use Amazon DynamoDB. More information is available at
https://aws.amazon.com/dynamodb[Amazon DynamoDB].


== URI Format

------------------------------
aws2-ddb://domainName[?options]
------------------------------

You can append query options to the URI in the following format:

`?options=value&option2=value&...`


// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
include::partial$component-endpoint-headers.adoc[]
// component options: END

Required DDB component options

You have to provide the amazonDDBClient in the
Registry or your accessKey and secretKey to access
the https://aws.amazon.com/dynamodb[Amazon's DynamoDB].

== Usage

=== Static credentials, Default Credential Provider and Profile Credentials Provider

You have the possibility of avoiding the usage of explicit static credentials by specifying the useDefaultCredentialsProvider option and set it to true.

The order of evaluation for Default Credentials Provider is the following:

 - Java system properties - `aws.accessKeyId` and `aws.secretKey`.
 - Environment variables - `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
 - Web Identity Token from AWS STS.
 - The shared credentials and config files.
 - Amazon ECS container credentials - loaded from the Amazon ECS if the environment variable `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` is set.
 - Amazon EC2 Instance profile credentials. 
 
You have also the possibility of using Profile Credentials Provider, by specifying the useProfileCredentialsProvider option to true and profileCredentialsName to the profile name.

Only one of static, default and profile credentials could be used at the same time.

For more information about this you can look at https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html[AWS credentials documentation]

=== Advanced AmazonDynamoDB configuration

If you need more control over the `AmazonDynamoDB` instance
configuration you can create your own instance and refer to it from the
URI:

[source,java]
----------------------------------------------------
public class MyRouteBuilder extends RouteBuilder {

    private String accessKey = "myaccessKey";
    private String secretKey = "secretKey";

    @Override
    public void configure() throws Exception {

        DynamoDbClient client = DynamoDbClient.builder()
        .region(Region.AP_SOUTHEAST_2)
        .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)))
        .build();

        getCamelContext().getRegistry().bind("client", client);

    	from("direct:start")
        .to("aws2-ddb://domainName?amazonDDBClient=#client");
    }
}
----------------------------------------------------

The `#client` refers to a `DynamoDbClient` in the
Registry.

=== Supported producer operations

- BatchGetItems
- BatchWriteItems
- BatchExecuteStatement
- DeleteItem
- DeleteTable
- DescribeTable
- ExecuteStatement
- GetItem
- PutItem
- Query
- Scan
- TransactGetItems
- TransactWriteItems
- UpdateItem
- UpdateTable

== Dependencies

Maven users will need to add the following dependency to their pom.xml.

*pom.xml*

[source,xml]
---------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-aws2-ddb</artifactId>
    <version>${camel-version}</version>
</dependency>
---------------------------------------

where `$\{camel-version}` must be replaced by the actual version of Camel.

== Examples

=== Producer Examples

- PutItem: this operation will create an entry into DynamoDB

[source,java]
--------------------------------------------------------------------------------
Map<String, AttributeValue> attributeMap = new HashMap<>();
attributeMap.put("partitionKey", AttributeValue.builder().s("3000").build());
attributeMap.put("id", AttributeValue.builder().s("1001").build());
attributeMap.put("barcode", AttributeValue.builder().s("9002811220001").build());

from("direct:start")
  .setHeader(Ddb2Constants.OPERATION,  constant(Ddb2Operations.PutItem))
  .setHeader(Ddb2Constants.CONSISTENT_READ, constant("true"))
  .setHeader(Ddb2Constants.RETURN_VALUES, constant("ALL_OLD"))
  .setHeader(Ddb2Constants.ITEM, constant(attributeMap))
  .setHeader(Ddb2Constants.ATTRIBUTE_NAMES, constant(attributeMap.keySet()))
  .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client");
--------------------------------------------------------------------------------

- UpdateItem: this operation will update an entry into DynamoDB

[source,java]
--------------------------------------------------------------------------------
Map<String, AttributeValueUpdate> attributeMap = new HashMap<>();
attributeMap.put("partitionKey", AttributeValueUpdate.builder().value(AttributeValue.builder().s("3000").build()).build());
attributeMap.put("sortKey",  AttributeValueUpdate.builder().value(AttributeValue.builder().s("1001").build()).build());
attributeMap.put("borcode",  AttributeValueUpdate.builder().value(AttributeValue.builder().s("900281122").build()).build());

Map<String, AttributeValue> keyMap = new HashMap<>();
keyMap.put("partitionKey", AttributeValue.builder().s("3000").build());
keyMap.put("sortKey", AttributeValue.builder().s("1001").build());

from("direct:start")
  .setHeader(Ddb2Constants.OPERATION,  constant(Ddb2Operations.UpdateItem))
  .setHeader(Ddb2Constants.UPDATE_VALUES,  constant(attributeMap))
  .setHeader(Ddb2Constants.KEY,  constant(keyMap))
  .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client");
--------------------------------------------------------------------------------

- GetItem: this operation will retrieve an entry from DynamoDB

[source,java]
--------------------------------------------------------------------------------
from("direct:get")
  .process(exchange -> {
      final Map<String, AttributeValue> keyMap = new HashMap<>();
      keyMap.put("table-key", AttributeValue.builder().s("1").build());

      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.GetItem);
      exchange.getIn().setHeader(Ddb2Constants.ATTRIBUTE_NAMES, constant(List.of("table-key", "message")));
      exchange.getIn().setHeader(Ddb2Constants.KEY, keyMap);
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName);
--------------------------------------------------------------------------------

- DeleteItem: this operation will delete an entry from DynamoDB

[source,java]
--------------------------------------------------------------------------------
from("direct:delete")
  .process(exchange -> {
      final Map<String, AttributeValue> keyMap = new HashMap<>();
      keyMap.put("table-key", AttributeValue.builder().s("1").build());

      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.DeleteItem);
      exchange.getIn().setHeader(Ddb2Constants.KEY, keyMap);
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName);
--------------------------------------------------------------------------------


- ExecuteStatement (PartiQL): this operation runs a PartiQL statement against DynamoDB

[source,java]
--------------------------------------------------------------------------------
from("direct:partiql")
  .process(exchange -> {
      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.ExecuteStatement);
      exchange.getIn().setHeader(Ddb2Constants.STATEMENT,
          "SELECT * FROM \"MyTable\" WHERE \"key\" = ?");
      exchange.getIn().setHeader(Ddb2Constants.STATEMENT_PARAMETERS,
          List.of(AttributeValue.builder().s("myKeyValue").build()));
      exchange.getIn().setHeader(Ddb2Constants.CONSISTENT_READ, true);
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName);
--------------------------------------------------------------------------------

- BatchExecuteStatement (PartiQL batch): this operation runs multiple PartiQL statements in a batch

[source,java]
--------------------------------------------------------------------------------
from("direct:batchPartiql")
  .process(exchange -> {
      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.BatchExecuteStatement);
      exchange.getIn().setHeader(Ddb2Constants.BATCH_STATEMENTS, List.of(
          BatchStatementRequest.builder()
              .statement("INSERT INTO \"MyTable\" VALUE {'key': 'k1', 'data': 'v1'}")
              .build(),
          BatchStatementRequest.builder()
              .statement("INSERT INTO \"MyTable\" VALUE {'key': 'k2', 'data': 'v2'}")
              .build()));
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName);
--------------------------------------------------------------------------------

- TransactWriteItems: this operation performs a transactional write across one or more tables

[source,java]
--------------------------------------------------------------------------------
Map<String, AttributeValue> item = new HashMap<>();
item.put("key", AttributeValue.builder().s("txKey").build());
item.put("data", AttributeValue.builder().s("txValue").build());

from("direct:transactWrite")
  .process(exchange -> {
      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.TransactWriteItems);
      exchange.getIn().setHeader(Ddb2Constants.TRANSACT_WRITE_ITEMS, List.of(
          TransactWriteItem.builder()
              .put(Put.builder().tableName("MyTable").item(item).build())
              .build()));
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName);
--------------------------------------------------------------------------------

- TransactGetItems: this operation performs a transactional read across one or more tables

[source,java]
--------------------------------------------------------------------------------
Map<String, AttributeValue> key = new HashMap<>();
key.put("key", AttributeValue.builder().s("txKey").build());

from("direct:transactGet")
  .process(exchange -> {
      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.TransactGetItems);
      exchange.getIn().setHeader(Ddb2Constants.TRANSACT_GET_ITEMS, List.of(
          TransactGetItem.builder()
              .get(Get.builder().tableName("MyTable").key(key).build())
              .build()));
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName);
--------------------------------------------------------------------------------

- BatchWriteItems: this operation puts or deletes multiple items in one or more tables in a single batch

[source,java]
--------------------------------------------------------------------------------
Map<String, AttributeValue> item1 = new HashMap<>();
item1.put("key", AttributeValue.builder().s("bk1").build());
item1.put("data", AttributeValue.builder().s("bv1").build());

Map<String, List<WriteRequest>> requestItems = new HashMap<>();
requestItems.put("MyTable", List.of(
    WriteRequest.builder()
        .putRequest(PutRequest.builder().item(item1).build())
        .build()));

from("direct:batchWrite")
  .process(exchange -> {
      exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.BatchWriteItems);
      exchange.getIn().setHeader(Ddb2Constants.BATCH_WRITE_ITEMS, requestItems);
  })
  .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName);
--------------------------------------------------------------------------------


include::spring-boot:partial$starter.adoc[]
