

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menelepon Layanan AWS dari AWS SDK for Java 2.x
<a name="work-with-services"></a>

Bagian ini memberikan tutorial singkat dan panduan tentang cara bekerja dengan pilih Layanan AWS. Untuk kumpulan contoh lengkap, lihat [bagian Contoh Kode](java_code_examples.md).

**Topics**
+ [CloudWatch](examples-cloudwatch.md)
+ [AWS layanan basis data](examples-databases.md)
+ [DynamoDB](examples-dynamodb.md)
+ [Amazon EC2](examples-ec2.md)
+ [IAM](examples-iam.md)
+ [Kinesis](examples-kinesis.md)
+ [Lambda](examples-lambda.md)
+ [Amazon S3](examples-s3.md)
+ [Amazon SNS](examples-simple-notification-service.md)
+ [Amazon SQS](examples-sqs.md)
+ [Amazon Transcribe](examples-transcribe.md)

# Bekerja dengan CloudWatch
<a name="examples-cloudwatch"></a>

Bagian ini memberikan contoh pemrograman [Amazon CloudWatch](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) dengan menggunakan AWS SDK untuk Java 2.x.

 Amazon CloudWatch memantau sumber daya Amazon Web Services (AWS) Anda dan aplikasi yang Anda jalankan AWS secara real time. Anda dapat menggunakan CloudWatch untuk mengumpulkan dan melacak metrik, yang merupakan variabel yang dapat Anda ukur untuk sumber daya dan aplikasi Anda. CloudWatch alarm mengirim pemberitahuan atau secara otomatis membuat perubahan pada sumber daya yang Anda pantau berdasarkan aturan yang Anda tetapkan.

Contoh berikut hanya mencakup kode yang diperlukan untuk mendemonstrasikan setiap teknik. [Kode contoh lengkap tersedia di GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Dari sana, Anda dapat mengunduh satu file sumber atau mengkloning repositori secara lokal untuk mendapatkan semua contoh untuk dibangun dan dijalankan.

**Topics**
+ [Dapatkan metrik dari CloudWatch](examples-cloudwatch-get-metrics.md)
+ [Publikasikan data metrik kustom ke CloudWatch](examples-cloudwatch-publish-custom-metrics.md)
+ [Bekerja dengan CloudWatch alarm](examples-cloudwatch-create-alarms.md)
+ [Gunakan CloudWatch Acara Amazon](examples-cloudwatch-send-events.md)

# Dapatkan metrik dari CloudWatch
<a name="examples-cloudwatch-get-metrics"></a>

## Metrik daftar
<a name="listing-metrics"></a>

Untuk membuat daftar CloudWatch metrik, buat [ListMetricsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsRequest.html)dan panggil `listMetrics` metode CloudWatchClient ini. Anda dapat menggunakan `ListMetricsRequest` untuk memfilter metrik yang dikembalikan berdasarkan namespace, nama metrik, atau dimensi.

**catatan**  
Daftar metrik dan dimensi yang diposting oleh AWS layanan dapat ditemukan dalam [Referensi Amazon CloudWatch Metrik dan Dimensi](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) di Amazon CloudWatch Panduan Pengguna.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest;
import software.amazon.awssdk.services.cloudwatch.model.ListMetricsResponse;
import software.amazon.awssdk.services.cloudwatch.model.Metric;
```

 **Kode** 

```
    public static void listMets( CloudWatchClient cw, String namespace) {

        boolean done = false;
        String nextToken = null;

        try {
            while(!done) {

                ListMetricsResponse response;

                if (nextToken == null) {
                   ListMetricsRequest request = ListMetricsRequest.builder()
                        .namespace(namespace)
                        .build();

                 response = cw.listMetrics(request);
                } else {
                  ListMetricsRequest request = ListMetricsRequest.builder()
                        .namespace(namespace)
                        .nextToken(nextToken)
                        .build();

                response = cw.listMetrics(request);
            }

            for (Metric metric : response.metrics()) {
                System.out.printf(
                        "Retrieved metric %s", metric.metricName());
                System.out.println();
            }

            if(response.nextToken() == null) {
                done = true;
            } else {
                nextToken = response.nextToken();
            }
        }

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Metrik dikembalikan dalam a [ListMetricsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsResponse.html)dengan memanggil `getMetrics` metodenya.

Hasilnya mungkin *paged.* Untuk mengambil kumpulan hasil berikutnya, panggil `nextToken` objek respons dan gunakan nilai token untuk membangun objek permintaan baru. Kemudian panggil `listMetrics` metode lagi dengan permintaan baru.

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [ListMetrics](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_ListMetrics.html)di Referensi Amazon CloudWatch API

# Publikasikan data metrik kustom ke CloudWatch
<a name="examples-cloudwatch-publish-custom-metrics"></a>

Sejumlah AWS layanan mempublikasikan [metrik mereka sendiri](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) di ruang nama yang dimulai dengan "`AWS`" Anda juga dapat mempublikasikan data metrik khusus menggunakan namespace Anda sendiri (asalkan tidak dimulai dengan "“). `AWS`

## Publikasikan data metrik kustom
<a name="cwid1"></a>

Untuk mempublikasikan data metrik Anda sendiri, panggil `putMetricData` metode ini dengan file [PutMetricDataRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricDataRequest.html). CloudWatchClient `PutMetricDataRequest`Harus menyertakan namespace khusus yang akan digunakan untuk data, dan informasi tentang titik data itu sendiri dalam suatu [MetricDatum](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/MetricDatum.html)objek.

**catatan**  
Anda tidak dapat menentukan namespace yang dimulai dengan "”`AWS`. Ruang nama yang dimulai dengan "`AWS`" dicadangkan untuk digunakan oleh Amazon Web Services produk.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.Dimension;
import software.amazon.awssdk.services.cloudwatch.model.MetricDatum;
import software.amazon.awssdk.services.cloudwatch.model.StandardUnit;
import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataRequest;
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
```

 **Kode** 

```
    public static void putMetData(CloudWatchClient cw, Double dataPoint ) {

        try {
            Dimension dimension = Dimension.builder()
                    .name("UNIQUE_PAGES")
                    .value("URLS")
                    .build();

            // Set an Instant object
            String time = ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_INSTANT );
            Instant instant = Instant.parse(time);

            MetricDatum datum = MetricDatum.builder()
                .metricName("PAGES_VISITED")
                .unit(StandardUnit.NONE)
                .value(dataPoint)
                .timestamp(instant)
                .dimensions(dimension).build();

            PutMetricDataRequest request = PutMetricDataRequest.builder()
                .namespace("SITE/TRAFFIC")
                .metricData(datum).build();

            cw.putMetricData(request);

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        System.out.printf("Successfully put data point %f", dataPoint);
     }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Gunakan Amazon CloudWatch Metrik](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/working_with_metrics.html) di Panduan Amazon CloudWatch Pengguna.
+  [AWS Ruang nama](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) di Amazon CloudWatch Panduan Pengguna.
+  [PutMetricData](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricData.html)di Referensi Amazon CloudWatch API.

# Bekerja dengan CloudWatch alarm
<a name="examples-cloudwatch-create-alarms"></a>

## Membuat alarm
<a name="create-an-alarm"></a>

Untuk membuat alarm berdasarkan CloudWatch metrik, panggil `putMetricAlarm` metode dengan [PutMetricAlarmRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricAlarmRequest.html)diisi dengan kondisi alarm. CloudWatchClient

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.Dimension;
import software.amazon.awssdk.services.cloudwatch.model.PutMetricAlarmRequest;
import software.amazon.awssdk.services.cloudwatch.model.ComparisonOperator;
import software.amazon.awssdk.services.cloudwatch.model.Statistic;
import software.amazon.awssdk.services.cloudwatch.model.StandardUnit;
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
```

 **Kode** 

```
    public static void putMetricAlarm(CloudWatchClient cw, String alarmName, String instanceId) {

        try {
            Dimension dimension = Dimension.builder()
                .name("InstanceId")
                .value(instanceId).build();

            PutMetricAlarmRequest request = PutMetricAlarmRequest.builder()
                .alarmName(alarmName)
                .comparisonOperator(
                        ComparisonOperator.GREATER_THAN_THRESHOLD)
                .evaluationPeriods(1)
                .metricName("CPUUtilization")
                .namespace("AWS/EC2")
                .period(60)
                .statistic(Statistic.AVERAGE)
                .threshold(70.0)
                .actionsEnabled(false)
                .alarmDescription(
                        "Alarm when server CPU utilization exceeds 70%")
                .unit(StandardUnit.SECONDS)
                .dimensions(dimension)
                .build();

            cw.putMetricAlarm(request);
            System.out.printf(
                    "Successfully created alarm with name %s", alarmName);

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java) di GitHub.

## Daftar alarm
<a name="list-alarms"></a>

Untuk membuat daftar CloudWatch alarm yang telah Anda buat, panggil `describeAlarms` metode ini dengan [DescribeAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsRequest.html)yang dapat Anda gunakan untuk mengatur opsi untuk hasilnya. CloudWatchClient

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsRequest;
import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsResponse;
import software.amazon.awssdk.services.cloudwatch.model.MetricAlarm;
```

 **Kode** 

```
    public static void desCWAlarms( CloudWatchClient cw) {

        try {

            boolean done = false;
            String newToken = null;

            while(!done) {
                DescribeAlarmsResponse response;

                if (newToken == null) {
                    DescribeAlarmsRequest request = DescribeAlarmsRequest.builder().build();
                    response = cw.describeAlarms(request);
                } else {
                    DescribeAlarmsRequest request = DescribeAlarmsRequest.builder()
                        .nextToken(newToken)
                        .build();
                    response = cw.describeAlarms(request);
                }

                for(MetricAlarm alarm : response.metricAlarms()) {
                    System.out.printf("\n Retrieved alarm %s", alarm.alarmName());
                }

                if(response.nextToken() == null) {
                    done = true;
                } else {
                    newToken = response.nextToken();
                }
            }

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        System.out.printf("Done");
    }
```

Daftar alarm dapat diperoleh dengan memanggil `MetricAlarms` [DescribeAlarmsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsResponse.html)yang dikembalikan oleh`describeAlarms`.

Hasilnya mungkin *paged.* Untuk mengambil kumpulan hasil berikutnya, panggil `nextToken` objek respons dan gunakan nilai token untuk membangun objek permintaan baru. Kemudian panggil `describeAlarms` metode lagi dengan permintaan baru.

**catatan**  
Anda juga dapat mengambil alarm untuk metrik tertentu dengan menggunakan metode ini CloudWatchClient. `describeAlarmsForMetric` Penggunaannya mirip dengan`describeAlarms`.

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java) di GitHub.

## Menghapus alarm
<a name="delete-alarms"></a>

Untuk menghapus CloudWatch alarm, panggil `deleteAlarms` metode dengan [DeleteAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DeleteAlarmsRequest.html)berisi satu atau beberapa nama alarm yang ingin Anda hapus. CloudWatchClient

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsRequest;
```

 **Kode** 

```
    public static void deleteCWAlarm(CloudWatchClient cw, String alarmName) {

        try {
            DeleteAlarmsRequest request = DeleteAlarmsRequest.builder()
                    .alarmNames(alarmName)
                    .build();

            cw.deleteAlarms(request);
            System.out.printf("Successfully deleted alarm %s", alarmName);

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Menggunakan Amazon CloudWatch alarm](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) di Amazon CloudWatch Panduan Pengguna
+  [PutMetricAlarm](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricAlarm.html)di Referensi Amazon CloudWatch API
+  [DescribeAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)di Referensi Amazon CloudWatch API
+  [DeleteAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DeleteAlarms.html)di Referensi Amazon CloudWatch API

# Gunakan CloudWatch Acara Amazon
<a name="examples-cloudwatch-send-events"></a>

 CloudWatch Acara memberikan aliran peristiwa sistem yang mendekati real-time yang menggambarkan perubahan AWS sumber daya ke Amazon EC2 instance, Lambda fungsi, Kinesis aliran, Amazon ECS tugas, mesin Step Functions status, Amazon SNS topik, Amazon SQS antrian, atau target bawaan. Anda dapat mencocokkan acara dan meruteknya ke satu atau beberapa fungsi atau aliran target dengan menggunakan aturan sederhana.

Amazon EventBridge adalah [evolusi](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cwe-now-eb.html) dari CloudWatch Peristiwa. Kedua layanan menggunakan API yang sama, sehingga Anda dapat terus menggunakan [klien CloudWatch Acara](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/CloudWatchClient.html) yang disediakan oleh SDK atau bermigrasi ke fungsionalitas SDK untuk [EventBridge klien](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/eventbridge/EventBridgeClient.html) Java untuk CloudWatch Acara. CloudWatch [Dokumentasi Panduan Pengguna](https://docs.aws.amazon.com/eventbridge/latest/userguide/index.html) Acara dan [referensi API](https://docs.aws.amazon.com/eventbridge/latest/APIReference/index.html) sekarang tersedia melalui situs EventBridge dokumentasi.

## Tambahkan acara
<a name="add-events"></a>

Untuk menambahkan CloudWatch peristiwa khusus, panggil `CloudWatchEventsClient’s` `putEvents` metode dengan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutEventsRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutEventsRequest.html)objek yang berisi satu atau beberapa [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutEventsRequestEntry.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutEventsRequestEntry.html)objek yang memberikan detail tentang setiap peristiwa. Anda dapat menentukan beberapa parameter untuk entri seperti sumber dan jenis acara, sumber daya yang terkait dengan acara, dan sebagainya.

**catatan**  
Anda dapat menentukan maksimum 10 acara per panggilan ke`putEvents`.

 **Impor** 

```
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient;
import software.amazon.awssdk.services.cloudwatchevents.model.PutEventsRequest;
import software.amazon.awssdk.services.cloudwatchevents.model.PutEventsRequestEntry;
```

 **Kode** 

```
    public static void putCWEvents(CloudWatchEventsClient cwe, String resourceArn ) {

        try {

            final String EVENT_DETAILS =
                "{ \"key1\": \"value1\", \"key2\": \"value2\" }";

            PutEventsRequestEntry requestEntry = PutEventsRequestEntry.builder()
                    .detail(EVENT_DETAILS)
                    .detailType("sampleSubmitted")
                    .resources(resourceArn)
                    .source("aws-sdk-java-cloudwatch-example")
                    .build();

            PutEventsRequest request = PutEventsRequest.builder()
                    .entries(requestEntry)
                    .build();

            cwe.putEvents(request);
            System.out.println("Successfully put CloudWatch event");

        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutEvents.java) di GitHub.

## Tambahkan aturan
<a name="add-rules"></a>

Untuk membuat atau memperbarui aturan, panggil `CloudWatchEventsClient’s` `putRule` metode [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutRuleRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutRuleRequest.html)dengan nama aturan dan parameter opsional seperti [pola acara](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html), IAM peran untuk dikaitkan dengan aturan, dan [ekspresi penjadwalan](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html) yang menjelaskan seberapa sering aturan dijalankan.

 **Impor** 

```
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient;
import software.amazon.awssdk.services.cloudwatchevents.model.PutRuleRequest;
import software.amazon.awssdk.services.cloudwatchevents.model.PutRuleResponse;
import software.amazon.awssdk.services.cloudwatchevents.model.RuleState;
```

 **Kode** 

```
    public static void putCWRule(CloudWatchEventsClient cwe, String ruleName, String roleArn) {

        try {
            PutRuleRequest request = PutRuleRequest.builder()
                .name(ruleName)
                .roleArn(roleArn)
                .scheduleExpression("rate(5 minutes)")
                .state(RuleState.ENABLED)
                .build();

            PutRuleResponse response = cwe.putRule(request);
            System.out.printf(
                    "Successfully created CloudWatch events rule %s with arn %s",
                    roleArn, response.ruleArn());
        } catch (
            CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutRule.java) di GitHub.

## Menambahkan target
<a name="add-targets"></a>

Target adalah sumber daya yang dipanggil ketika suatu aturan dipicu. Contoh target termasuk Amazon EC2 instance, Lambda fungsi, Kinesis aliran, Amazon ECS tugas, mesin Step Functions status, dan target bawaan.

Untuk menambahkan target ke aturan, panggil `CloudWatchEventsClient’s` `putTargets` metode dengan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutTargetsRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatchevents/model/PutTargetsRequest.html)berisi aturan untuk diperbarui dan daftar target untuk ditambahkan ke aturan.

 **Impor** 

```
import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException;
import software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient;
import software.amazon.awssdk.services.cloudwatchevents.model.PutTargetsRequest;
import software.amazon.awssdk.services.cloudwatchevents.model.PutTargetsResponse;
import software.amazon.awssdk.services.cloudwatchevents.model.Target;
```

 **Kode** 

```
    public static void putCWTargets(CloudWatchEventsClient cwe, String ruleName, String functionArn, String targetId ) {

        try {
            Target target = Target.builder()
                .arn(functionArn)
                .id(targetId)
                .build();

            PutTargetsRequest request = PutTargetsRequest.builder()
                .targets(target)
                .rule(ruleName)
                .build();

            PutTargetsResponse response = cwe.putTargets(request);
            System.out.printf(
                "Successfully created CloudWatch events target for rule %s",
                ruleName);
        } catch (CloudWatchException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutTargets.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Menambahkan Acara dengan PutEvents](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html) di Panduan EventBridge Pengguna Amazon
+  [Ekspresi Jadwal untuk Aturan](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html#eb-create-scheduled-rule-schedule) di Panduan EventBridge Pengguna Amazon
+  [Jenis Acara untuk CloudWatch Events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html) di Panduan EventBridge Pengguna Amazon
+  [Pola Acara](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html) di Panduan EventBridge Pengguna Amazon
+  [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)di Referensi EventBridge API Amazon
+  [PutTargets](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html)di Referensi EventBridge API Amazon
+  [PutRule](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html)di Referensi EventBridge API Amazon

# AWS layanan database dan AWS SDK for Java 2.x
<a name="examples-databases"></a>

AWS [menawarkan beberapa jenis database: relasional, key-value, in-memory, document, dan beberapa lainnya.](https://aws.amazon.com/products/databases/) Dukungan SDK for Java 2.x bervariasi tergantung sifat layanan database di. AWS

Beberapa layanan database, misalnya layanan [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/Welcome.html), memiliki APIs layanan web untuk mengelola AWS sumber daya (database) serta APIs layanan web untuk berinteraksi dengan data. [Dalam SDK for Java 2.x jenis layanan ini memiliki klien layanan khusus, misalnya Dynamo. DBClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)

Layanan database lainnya memiliki layanan web APIs yang berinteraksi dengan sumber daya, seperti [Amazon DocumentDB](https://docs.aws.amazon.com/documentdb/latest/developerguide/api-reference.html) API (untuk cluster, instance dan manajemen sumber daya), tetapi tidak memiliki API layanan web untuk bekerja dengan data. SDK for Java 2.x memiliki antarmuka yang [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html)sesuai untuk bekerja dengan sumber daya. Namun, Anda memerlukan API Java lain, seperti [MongoDB untuk Java untuk](https://www.mongodb.com/developer/languages/java/) bekerja dengan data.

Gunakan contoh di bawah ini untuk mempelajari cara Anda menggunakan klien layanan SDK for Java 2.x dengan berbagai jenis database.

## Contoh Amazon DynamoDB
<a name="examples-db-dynamodb"></a>


| Bekerja dengan data | Bekerja dengan database | 
| --- |--- |
| Klien layanan SDK: [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | Klien layanan SDK: [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | 
| Contoh: Aplikasi [React/Spring REST](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) menggunakan DynamoDB | Contoh: [CreateTable, ListTables, DeleteTable](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) | 
| Contoh: [Beberapa contoh DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) |  | 
|  | 
| --- |
| Klien layanan SDK: [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html) |  | 
| Contoh: Aplikasi [React/Spring REST](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) menggunakan DynamoDB |  | 
| Contoh: [Beberapa contoh DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) (nama dimulai dengan 'Enhanced”) |  | 

Lihat contoh [DynamoDB tambahan](examples-dynamodb.md) di bagian contoh kode terpandu dari panduan ini.

## Contoh-contoh Amazon RDS
<a name="examples-db-rds"></a>


|  Bekerja dengan data  |  Bekerja dengan database  | 
| --- | --- | 
| API non-SDK: JDBC, ragam SQL khusus database; kode Anda mengelola koneksi database atau kumpulan koneksi. | Klien layanan SDK: [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Contoh: Aplikasi [React/Spring REST](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_rds_item_tracker) menggunakan MySQL | Contoh: [Beberapa RdsClient contoh](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) | 

## Contoh Amazon Redshift
<a name="examples-db-redshift"></a>


|  Bekerja dengan data  |  Bekerja dengan database  | 
| --- | --- | 
| Klien layanan SDK: [RedshiftDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshiftdata/RedshiftDataClient.html) | Klien layanan SDK: [RedshiftClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshift/RedshiftClient.html) | 
| Contoh: [Beberapa RedshiftDataClient contoh](https://github.com/awsdocs/aws-doc-sdk-examples/blob/c682a07a1e6abce793e3c32ef3b9661fa723d0ff/javav2/example_code/redshift/src/main/java/com/example/scenario/RedshiftScenario.java) | Contoh: [Beberapa RedshiftClient contoh](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/redshift/src/main/java/com/example/redshift) | 
| Contoh: Aplikasi [React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/CreatingSpringRedshiftRest) REST menggunakan RedshiftDataClient |  | 

## Contoh Amazon Aurora Tanpa Server v2
<a name="examples-db-aurora-sv1"></a>


|  Bekerja dengan data  |  Bekerja dengan database  | 
| --- | --- | 
| Klien layanan SDK: [RdsDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rdsdata/RdsDataClient.html) | Klien layanan SDK: [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Contoh: Aplikasi [React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_Spring_RDS_Rest) REST menggunakan RdsDataClient | Contoh: [Beberapa RdsClient contoh](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) | 

## Contoh Amazon DocumentDB
<a name="examples-db-docdb"></a>


|  Bekerja dengan data  |  Bekerja dengan database  | 
| --- | --- | 
| Non-SDK API: pustaka Java khusus MongoDB (misalnya [MongoDB untuk Java](https://www.mongodb.com/developer/languages/java/)); kode Anda mengelola koneksi database atau kumpulan koneksi. | Klien layanan SDK: [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html) | 
| Contoh: Panduan [Pengembang DocumentDB (Mongo)](https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html#connect_programmatically-tls_enabled) (pilih tab 'Java') |  | 

# Bekerja dengan DynamoDB
<a name="examples-dynamodb"></a>

[DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) adalah layanan database NoSQL yang dikelola sepenuhnya yang memberikan kinerja yang cepat dan dapat diprediksi dengan skalabilitas yang mulus. Bagian ini menunjukkan cara bekerja dengan DynamoDB menggunakan 2.x. AWS SDK untuk Java 

## Pilih klien DynamoDB Anda
<a name="ddb-clients-overview"></a>

SDK menyediakan dua pendekatan utama untuk bekerja dengan DynamoDB:

Klien tingkat rendah () `DynamoDbClient`  
Menyediakan akses langsung ke operasi DynamoDB dengan kontrol penuh atas permintaan dan tanggapan. Gunakan klien ini ketika Anda membutuhkan kontrol halus atau bekerja dengan skema dinamis.

Klien yang disempurnakan (`DynamoDbEnhancedClient`)  
Menawarkan pemrograman berorientasi objek dengan pemetaan otomatis antara objek Java dan item DynamoDB. Juga menyediakan kemampuan berorientasi dokumen untuk bekerja dengan data seperti JSON yang tidak mengikuti skema tetap. Gunakan klien ini saat bekerja dengan model data yang terdefinisi dengan baik atau data tipe dokumen.

## Konfigurasikan klien DynamoDB
<a name="ddb-configuration-setup"></a>

Sebelum bekerja dengan DynamoDB, konfigurasikan klien Anda untuk kinerja dan keandalan yang optimal.

### Memahami perilaku coba lagi DynamoDB
<a name="ddb-retry-behavior"></a>

Klien DynamoDB menggunakan hitungan coba ulang maksimum default 8, yang lebih tinggi dari klien lain. Layanan AWS Jumlah percobaan ulang yang lebih tinggi ini membantu menangani sifat terdistribusi DynamoDB dan batasan kapasitas sementara. Untuk informasi lebih lanjut tentang strategi coba lagi, lihat[Konfigurasikan perilaku coba lagi di AWS SDK for Java 2.x](retry-strategy.md).

### Optimalkan kinerja dengan titik akhir berbasis akun
<a name="ddb-account-based-endpoints-v2"></a>

DynamoDB [AWS menawarkan endpoint berbasis akun](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.SDKOverview.html#Programming.SDKs.endpoints) yang meningkatkan kinerja dengan menggunakan ID akun AWS Anda untuk merampingkan perutean permintaan. 

Untuk menggunakan fitur ini, Anda memerlukan versi 2.28.4 atau yang lebih besar dari. AWS SDK for Java 2.x Anda dapat menemukan versi terbaru di repositori [pusat Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/bom/versions). Versi SDK yang didukung secara otomatis menggunakan titik akhir baru.

Untuk memilih keluar dari perutean berbasis akun, pilih salah satu opsi berikut:
+ Konfigurasikan klien `AccountIdEndpointMode` layanan DynamoDB dengan set ke. `DISABLED`
+ Tetapkan variabel lingkungan.
+ Mengatur properti sistem JVM.
+ Perbarui setelan file AWS konfigurasi bersama.

Contoh berikut menunjukkan cara menonaktifkan routing berbasis akun dengan mengkonfigurasi klien layanan DynamoDB:

```
DynamoDbClient.builder()
                 .accountIdEndpointMode(AccountIdEndpointMode.DISABLED)
                 .build();
```

Untuk informasi selengkapnya tentang opsi konfigurasi lainnya, lihat [Titik akhir berbasis akun](https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html) di Panduan Referensi Alat AWS SDKs dan Alat.

## Apa yang dibahas dalam topik ini
<a name="ddb-topics-overview"></a>

Bagian berikut menunjukkan cara bekerja dengan DynamoDB:
+ [Bekerja dengan tabel di DynamoDB](examples-dynamodb-tables.md)- Buat, jelaskan, perbarui, dan hapus tabel
+ [Bekerja dengan item di DynamoDB](examples-dynamodb-items.md)- Tambahkan, ambil, dan perbarui item individual
+ [Peta objek Java ke item DynamoDB dengan AWS SDK for Java 2.x](dynamodb-enhanced-client.md)- Gunakan pemetaan objek dan data berorientasi dokumen dengan Klien yang Ditingkatkan

Untuk contoh kode DynamoDB tambahan, lihat contoh kode [DynamoDB di Pustaka Contoh](java_dynamodb_code_examples.md) Kode. AWS 

# Bekerja dengan tabel di DynamoDB
<a name="examples-dynamodb-tables"></a>

Tabel adalah wadah untuk semua item dalam DynamoDB database. Sebelum Anda dapat menambah atau menghapus data dari DynamoDB, Anda harus membuat tabel.

Untuk setiap tabel, Anda harus mendefinisikan:
+ *Nama* tabel yang unik untuk akun dan Wilayah Anda.
+ *Kunci utama* yang setiap nilainya harus unik; tidak ada dua item dalam tabel Anda yang dapat memiliki nilai kunci primer yang sama.

  Kunci primer bisa *sederhana*, terdiri dari kunci partisi tunggal (HASH), atau *komposit*, yang terdiri dari partisi dan kunci sort (RANGE).

  Setiap nilai kunci memiliki *tipe data* terkait, disebutkan oleh kelas. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ScalarAttributeType.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ScalarAttributeType.html) Nilai kunci dapat berupa biner (B), numerik (N), atau string (S). Untuk informasi selengkapnya, lihat [Aturan Penamaan dan Jenis Data](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) di Panduan Amazon DynamoDB Pengembang.
+  *Throughput yang disediakan* adalah nilai yang menentukan jumlah unit kapasitas baca/tulis yang dicadangkan untuk tabel.
**catatan**  
 [Amazon DynamoDB Penetapan harga](https://aws.amazon.com/dynamodb/pricing/) didasarkan pada nilai throughput yang disediakan yang Anda tetapkan pada tabel Anda, jadi cadangkan hanya kapasitas sebanyak yang Anda pikir Anda perlukan untuk tabel Anda.

  Throughput yang disediakan untuk tabel dapat dimodifikasi kapan saja, sehingga Anda dapat menyesuaikan kapasitas saat kebutuhan Anda berubah.

## Membuat tabel
<a name="dynamodb-create-table"></a>

Gunakan `DynamoDbClient’s` `createTable` metode ini untuk membuat DynamoDB tabel baru. Anda perlu membangun atribut tabel dan skema tabel, yang keduanya digunakan untuk mengidentifikasi kunci utama tabel Anda. Anda juga harus menyediakan nilai throughput awal yang disediakan dan nama tabel.

**catatan**  
Jika tabel dengan nama yang Anda pilih sudah ada, a `[DynamoDbException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)` dilemparkan.

### Buat tabel dengan kunci primer sederhana
<a name="dynamodb-create-table-simple"></a>

Kode ini membuat tabel dengan satu atribut yang merupakan kunci utama sederhana tabel. contoh menggunakan `[AttributeDefinition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeDefinition.html)` dan `[KeySchemaElement](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/KeySchemaElement.html)` objek untuk. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CreateTableRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CreateTableRequest.html)

 **Impor** 

```
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

 **Kode** 

```
    public static String createTable(DynamoDbClient ddb, String tableName, String key) {

        DynamoDbWaiter dbWaiter = ddb.waiter();
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(AttributeDefinition.builder()
                        .attributeName(key)
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(KeySchemaElement.builder()
                        .attributeName(key)
                        .keyType(KeyType.HASH)
                        .build())
                .provisionedThroughput(ProvisionedThroughput.builder()
                        .readCapacityUnits(new Long(10))
                        .writeCapacityUnits(new Long(10))
                        .build())
                .tableName(tableName)
                .build();

        String newTable ="";
        try {
            CreateTableResponse response = ddb.createTable(request);
            DescribeTableRequest tableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();

            // Wait until the Amazon DynamoDB table is created
            WaiterResponse<DescribeTableResponse> waiterResponse =  dbWaiter.waitUntilTableExists(tableRequest);
            waiterResponse.matched().response().ifPresent(System.out::println);

            newTable = response.tableDescription().tableName();
            return newTable;

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
       return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java) di GitHub.

### Buat tabel dengan kunci primer komposit
<a name="dynamodb-create-table-composite"></a>

Contoh berikut membuat tabel dengan dua atribut. Kedua atribut digunakan untuk kunci primer komposit.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
```

 **Kode** 

```
    public static String createTableComKey(DynamoDbClient ddb, String tableName) {
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(
                        AttributeDefinition.builder()
                                .attributeName("Language")
                                .attributeType(ScalarAttributeType.S)
                                .build(),
                        AttributeDefinition.builder()
                                .attributeName("Greeting")
                                .attributeType(ScalarAttributeType.S)
                                .build())
                .keySchema(
                        KeySchemaElement.builder()
                                .attributeName("Language")
                                .keyType(KeyType.HASH)
                                .build(),
                        KeySchemaElement.builder()
                                .attributeName("Greeting")
                                .keyType(KeyType.RANGE)
                                .build())
                .provisionedThroughput(
                        ProvisionedThroughput.builder()
                                .readCapacityUnits(new Long(10))
                                .writeCapacityUnits(new Long(10)).build())
                .tableName(tableName)
                .build();

       String tableId = "";

       try {
            CreateTableResponse result = ddb.createTable(request);
            tableId = result.tableDescription().tableId();
            return tableId;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
       return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTableCompositeKey.java) di GitHub.

## Mencantumkan tabel
<a name="dynamodb-list-tables"></a>

Anda dapat membuat daftar tabel di Wilayah tertentu dengan memanggil `DynamoDbClient’s` `listTables` metode.

**catatan**  
Jika tabel bernama tidak ada untuk akun dan Wilayah Anda, a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)dilemparkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import java.util.List;
```

 **Kode** 

```
    public static void listAllTables(DynamoDbClient ddb){

        boolean moreTables = true;
        String lastName = null;

        while(moreTables) {
            try {
                ListTablesResponse response = null;
                if (lastName == null) {
                    ListTablesRequest request = ListTablesRequest.builder().build();
                    response = ddb.listTables(request);
                } else {
                    ListTablesRequest request = ListTablesRequest.builder()
                            .exclusiveStartTableName(lastName).build();
                    response = ddb.listTables(request);
                }

                List<String> tableNames = response.tableNames();

                if (tableNames.size() > 0) {
                    for (String curName : tableNames) {
                        System.out.format("* %s\n", curName);
                    }
                } else {
                    System.out.println("No tables found!");
                    System.exit(0);
                }

                lastName = response.lastEvaluatedTableName();
                if (lastName == null) {
                    moreTables = false;
                }
            } catch (DynamoDbException e) {
                System.err.println(e.getMessage());
                System.exit(1);
            }
        }
        System.out.println("\nDone!");
    }
```

Secara default, hingga 100 tabel dikembalikan per panggilan—gunakan `lastEvaluatedTableName` pada [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ListTablesResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ListTablesResponse.html)objek yang dikembalikan untuk mendapatkan tabel terakhir yang dievaluasi. Anda dapat menggunakan nilai ini untuk memulai daftar setelah nilai terakhir yang dikembalikan dari daftar sebelumnya.

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/ListTables.java) di GitHub.

## Jelaskan (dapatkan informasi tentang) tabel
<a name="dynamodb-describe-table"></a>

Gunakan `DynamoDbClient’s` `describeTable` metode ini untuk mendapatkan informasi tentang tabel.

**catatan**  
Jika tabel bernama tidak ada untuk akun dan Wilayah Anda, a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)dilemparkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughputDescription;
import software.amazon.awssdk.services.dynamodb.model.TableDescription;
import java.util.List;
```

 **Kode** 

```
    public static void describeDymamoDBTable(DynamoDbClient ddb,String tableName ) {

        DescribeTableRequest request = DescribeTableRequest.builder()
                .tableName(tableName)
                .build();

        try {
            TableDescription tableInfo =
                    ddb.describeTable(request).table();

            if (tableInfo != null) {
                System.out.format("Table name  : %s\n",
                        tableInfo.tableName());
                System.out.format("Table ARN   : %s\n",
                        tableInfo.tableArn());
                System.out.format("Status      : %s\n",
                        tableInfo.tableStatus());
                System.out.format("Item count  : %d\n",
                        tableInfo.itemCount().longValue());
                System.out.format("Size (bytes): %d\n",
                        tableInfo.tableSizeBytes().longValue());

                ProvisionedThroughputDescription throughputInfo =
                        tableInfo.provisionedThroughput();
                System.out.println("Throughput");
                System.out.format("  Read Capacity : %d\n",
                        throughputInfo.readCapacityUnits().longValue());
                System.out.format("  Write Capacity: %d\n",
                        throughputInfo.writeCapacityUnits().longValue());

                List<AttributeDefinition> attributes =
                        tableInfo.attributeDefinitions();
                System.out.println("Attributes");

                for (AttributeDefinition a : attributes) {
                    System.out.format("  %s (%s)\n",
                            a.attributeName(), a.attributeType());
                }
            }
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println("\nDone!");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DescribeTable.java) di GitHub.

## Ubah (perbarui) tabel
<a name="dynamodb-update-table"></a>

Anda dapat memodifikasi nilai throughput yang disediakan tabel kapan saja dengan memanggil metode. `DynamoDbClient’s` `updateTable`

**catatan**  
Jika tabel bernama tidak ada untuk akun dan Wilayah Anda, a [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)dilemparkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
```

 **Kode** 

```
    public static void updateDynamoDBTable(DynamoDbClient ddb,
                                           String tableName,
                                           Long readCapacity,
                                           Long writeCapacity) {

        System.out.format(
                "Updating %s with new provisioned throughput values\n",
                tableName);
        System.out.format("Read capacity : %d\n", readCapacity);
        System.out.format("Write capacity : %d\n", writeCapacity);

        ProvisionedThroughput tableThroughput = ProvisionedThroughput.builder()
                .readCapacityUnits(readCapacity)
                .writeCapacityUnits(writeCapacity)
                .build();

        UpdateTableRequest request = UpdateTableRequest.builder()
                .provisionedThroughput(tableThroughput)
                .tableName(tableName)
                .build();

        try {
            ddb.updateTable(request);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.out.println("Done!");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateTable.java) di GitHub.

## Menghapus tabel
<a name="dynamodb-delete-table"></a>

Untuk menghapus tabel, panggil `DynamoDbClient’s` `deleteTable` metode dan berikan nama tabel.

**catatan**  
Jika tabel bernama tidak ada untuk akun dan Wilayah Anda, a [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)dilemparkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
```

 **Kode** 

```
    public static void deleteDynamoDBTable(DynamoDbClient ddb, String tableName) {

        DeleteTableRequest request = DeleteTableRequest.builder()
                .tableName(tableName)
                .build();

        try {
            ddb.deleteTable(request);

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println(tableName +" was successfully deleted!");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteTable.java) di GitHub.

## Informasi lain
<a name="more-information"></a>
+  [Pedoman untuk Bekerja dengan Tabel](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html) di Panduan Amazon DynamoDB Pengembang
+  [Bekerja dengan Tabel DynamoDB di](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html) Panduan Amazon DynamoDB Pengembang

# Bekerja dengan item di DynamoDB
<a name="examples-dynamodb-items"></a>

Dalam DynamoDB, item adalah kumpulan *atribut*, yang masing-masing memiliki *nama* dan *nilai*. Nilai atribut dapat berupa skalar, set, atau jenis dokumen. Untuk informasi selengkapnya, lihat [Aturan Penamaan dan Jenis Data](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) di Panduan Amazon DynamoDB Pengembang.

## Ambil (dapatkan) item dari tabel
<a name="dynamodb-get-item"></a>

Panggil `getItem` metode ini dan berikan [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)objek dengan nama tabel dan nilai kunci primer dari item yang Anda inginkan. DynamoDbClient Ia mengembalikan [GetItemResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemResponse.html)objek dengan semua atribut untuk item itu. Anda dapat menentukan satu atau lebih [ekspresi proyeksi](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) dalam `GetItemRequest` untuk mengambil atribut tertentu.

Anda dapat menggunakan `item()` metode `GetItemResponse` objek yang dikembalikan untuk mengambil [Map](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) of key (String) dan value ([AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html)) pasangan yang terkait dengan item tersebut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
```

 **Kode** 

```
    public static void getDynamoDBItem(DynamoDbClient ddb,String tableName,String key,String keyVal ) {

        HashMap<String,AttributeValue> keyToGet = new HashMap<String,AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal).build());

        GetItemRequest request = GetItemRequest.builder()
                .key(keyToGet)
                .tableName(tableName)
                .build();

        try {
            Map<String,AttributeValue> returnedItem = ddb.getItem(request).item();

            if (returnedItem != null) {
                Set<String> keys = returnedItem.keySet();
                System.out.println("Amazon DynamoDB table attributes: \n");

                for (String key1 : keys) {
                    System.out.format("%s: %s\n", key1, returnedItem.get(key1).toString());
                }
            } else {
                System.out.format("No item found with the key %s!\n", key);
            }
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/GetItem.java) di GitHub.

## Ambil (dapatkan) item dari tabel menggunakan klien asinkron
<a name="id1ddb"></a>

Memanggil `getItem` metode DynamoDbAsyncClient dan meneruskannya [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)objek dengan nama tabel dan nilai kunci utama dari item yang Anda inginkan.

Anda dapat mengembalikan instance [Collection](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html) dengan semua atribut untuk item tersebut (lihat contoh berikut).

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
```

 **Kode** 

```
    public static void getItem(DynamoDbAsyncClient client, String tableName, String key,  String keyVal) {

        HashMap<String, AttributeValue> keyToGet =
                new HashMap<String, AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal).build());

        try {

            // Create a GetItemRequest instance
            GetItemRequest request = GetItemRequest.builder()
                    .key(keyToGet)
                    .tableName(tableName)
                    .build();

            // Invoke the DynamoDbAsyncClient object's getItem
            java.util.Collection<AttributeValue> returnedItem = client.getItem(request).join().item().values();

            // Convert Set to Map
            Map<String, AttributeValue> map = returnedItem.stream().collect(Collectors.toMap(AttributeValue::s, s->s));
            Set<String> keys = map.keySet();
            for (String sinKey : keys) {
                System.out.format("%s: %s\n", sinKey, map.get(sinKey).toString());
            }

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/DynamoDBAsyncGetItem.java) di GitHub.

## Tambahkan item baru ke tabel
<a name="dynamodb-add-item"></a>

Buat [Peta](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) pasangan kunci-nilai yang mewakili atribut item. Ini harus menyertakan nilai untuk bidang kunci utama tabel. Jika item yang diidentifikasi oleh kunci utama sudah ada, bidangnya *diperbarui* oleh permintaan.

**catatan**  
Jika tabel bernama tidak ada untuk akun dan wilayah Anda, a [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)dilemparkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import java.util.HashMap;
```

 **Kode** 

```
    public static void putItemInTable(DynamoDbClient ddb,
                                      String tableName,
                                      String key,
                                      String keyVal,
                                      String albumTitle,
                                      String albumTitleValue,
                                      String awards,
                                      String awardVal,
                                      String songTitle,
                                      String songTitleVal){

        HashMap<String,AttributeValue> itemValues = new HashMap<String,AttributeValue>();

        // Add all content to the table
        itemValues.put(key, AttributeValue.builder().s(keyVal).build());
        itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build());
        itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build());
        itemValues.put(awards, AttributeValue.builder().s(awardVal).build());

        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(itemValues)
                .build();

        try {
            ddb.putItem(request);
            System.out.println(tableName +" was successfully updated");

        } catch (ResourceNotFoundException e) {
            System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName);
            System.err.println("Be sure that it exists and that you've typed its name correctly!");
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/PutItem.java) di GitHub.

## Memperbarui item yang ada dalam tabel
<a name="dynamodb-update-item"></a>

Anda dapat memperbarui atribut untuk item yang sudah ada dalam tabel dengan menggunakan `updateItem` metode, memberikan nama tabel, nilai kunci primer, dan peta bidang yang akan diperbarui. DynamoDbClient

**catatan**  
Jika tabel bernama tidak ada untuk akun dan wilayah Anda, atau jika item yang diidentifikasi oleh kunci utama yang Anda lewati tidak ada, a akan [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)ditampilkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.AttributeAction;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import java.util.HashMap;
```

 **Kode** 

```
    public static void updateTableItem(DynamoDbClient ddb,
                                       String tableName,
                                       String key,
                                       String keyVal,
                                       String name,
                                       String updateVal){

        HashMap<String,AttributeValue> itemKey = new HashMap<String,AttributeValue>();

        itemKey.put(key, AttributeValue.builder().s(keyVal).build());

        HashMap<String,AttributeValueUpdate> updatedValues =
                new HashMap<String,AttributeValueUpdate>();

        // Update the column specified by name with updatedVal
        updatedValues.put(name, AttributeValueUpdate.builder()
                .value(AttributeValue.builder().s(updateVal).build())
                .action(AttributeAction.PUT)
                .build());

        UpdateItemRequest request = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(itemKey)
                .attributeUpdates(updatedValues)
                .build();

        try {
            ddb.updateItem(request);
        } catch (ResourceNotFoundException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.out.println("Done!");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateItem.java) di GitHub.

## Menghapus item yang ada dalam tabel
<a name="dynamodb-delete-item"></a>

Anda dapat menghapus item yang ada dalam tabel dengan menggunakan `deleteItem` metode dan memberikan nama tabel serta nilai kunci primer. DynamoDbClient

**catatan**  
Jika tabel bernama tidak ada untuk akun dan wilayah Anda, atau jika item yang diidentifikasi oleh kunci utama yang Anda lewati tidak ada, a akan [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)ditampilkan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import java.util.HashMap;
```

 **Kode** 

```
  public static void deleteDynamoDBItem(DynamoDbClient ddb, String tableName, String key, String keyVal) {

        HashMap<String,AttributeValue> keyToGet =
                new HashMap<String,AttributeValue>();

        keyToGet.put(key, AttributeValue.builder()
                .s(keyVal)
                .build());

        DeleteItemRequest deleteReq = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(keyToGet)
                .build();

        try {
            ddb.deleteItem(deleteReq);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteItem.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Pedoman untuk Bekerja dengan Item](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/best-practices.html) di Panduan Amazon DynamoDB Pengembang
+  [Bekerja dengan Item DynamoDB di](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/WorkingWithItems.html) Panduan Amazon DynamoDB Pengembang

# Peta objek Java ke item DynamoDB dengan AWS SDK for Java 2.x
<a name="dynamodb-enhanced-client"></a>

[DynamoDB Enhanced Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) API adalah library tingkat tinggi yang merupakan penerus kelas dalam SDK for `DynamoDBMapper` Java v1.x. Ini menawarkan cara mudah untuk memetakan kelas sisi klien ke tabel DynamoDB. Anda menentukan hubungan antara tabel dan kelas data yang sesuai dalam kode Anda. Setelah menentukan hubungan tersebut, Anda dapat melakukan berbagai operasi buat, baca, perbarui, atau hapus (CRUD) pada tabel atau item di DynamoDB.

DynamoDB Enhanced Client API juga menyertakan API [Dokumen yang Ditingkatkan](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) yang memungkinkan Anda bekerja dengan item tipe dokumen yang tidak mengikuti skema yang ditentukan. 

**Topics**
+ [Memulai menggunakan DynamoDB Enhanced Client API](ddb-en-client-getting-started.md)
+ [Pelajari dasar-dasar DynamoDB Enhanced Client API](ddb-en-client-use.md)
+ [Gunakan fitur pemetaan tingkat lanjut](ddb-en-client-adv-features.md)
+ [Bekerja dengan dokumen JSON dengan Enhanced Document API untuk DynamoDB](ddb-en-client-doc-api.md)
+ [Gunakan ekstensi untuk menyesuaikan operasi DynamoDB Enhanced Client](ddb-en-client-extensions.md)
+ [Gunakan DynamoDB Enhanced Client API secara asinkron](ddb-en-client-async.md)
+ [Anotasi kelas data](ddb-en-client-anno-index.md)

# Memulai menggunakan DynamoDB Enhanced Client API
<a name="ddb-en-client-getting-started"></a>

Tutorial berikut memperkenalkan Anda pada dasar-dasar yang Anda butuhkan untuk bekerja dengan DynamoDB Enhanced Client API.

## Tambahkan dependensi
<a name="ddb-en-client-gs-dep"></a>

Untuk mulai bekerja dengan DynamoDB Enhanced Client API di project Anda, tambahkan dependensi pada artefak Maven. `dynamodb-enhanced` Ini ditunjukkan dalam contoh berikut. 

------
#### [ Maven ]

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version><VERSION></version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb-enhanced</artifactId>
    </dependency>
  </dependencies>
  ...
</project>
```

Lakukan pencarian repositori pusat Maven untuk [versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) dan ganti *<VERSION>* dengan nilai ini.

------
#### [ Gradle ]

```
repositories {
    mavenCentral()
}
dependencies {
    implementation(platform("software.amazon.awssdk:bom:<VERSION>"))
    implementation("software.amazon.awssdk:dynamodb-enhanced")
    ...
}
```

Lakukan pencarian repositori pusat Maven untuk [versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) dan ganti *<VERSION>* dengan nilai ini.

------

# Menghasilkan `TableSchema` dari kelas data
<a name="ddb-en-client-gs-tableschema"></a>

A `[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)` memungkinkan klien yang disempurnakan untuk memetakan nilai atribut DynamoDB ke dan dari kelas sisi klien Anda. Dalam tutorial ini, Anda belajar tentang `TableSchema` s yang berasal dari kelas data statis dan dihasilkan dari kode dengan menggunakan pembangun.

## Gunakan kelas data beranotasi
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

SDK for Java 2.x menyertakan [serangkaian anotasi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html) yang dapat Anda gunakan dengan kelas data untuk menghasilkan `TableSchema` cepat untuk memetakan kelas Anda ke tabel.

Mulailah dengan membuat kelas data yang sesuai dengan [JavaBean spesifikasi](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf). Spesifikasi mensyaratkan bahwa kelas memiliki konstruktor publik tanpa argumen dan memiliki getter dan setter untuk setiap atribut di kelas. Sertakan anotasi tingkat kelas untuk menunjukkan bahwa kelas data adalah a. `DynamoDbBean` Juga, minimal, sertakan `DynamoDbPartitionKey` anotasi pada pengambil atau penyetel untuk atribut kunci utama. 

Anda dapat menerapkan [anotasi tingkat atribut](ddb-en-client-anno-index.md) ke getter atau setter, tetapi tidak keduanya.

**catatan**  
Istilah `property` ini biasanya digunakan untuk nilai yang dienkapsulasi dalam a. JavaBean Namun, panduan ini menggunakan istilah `attribute` sebagai gantinya, agar konsisten dengan terminologi yang digunakan oleh DynamoDB.

`Customer`Kelas berikut menunjukkan anotasi yang menghubungkan definisi kelas ke tabel DynamoDB.

### `Customer` kelas
<a name="ddb-en-client-gs-tableschema-anno-bean-cust"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbBean
public class Customer {

    private String id;
    private String name;
    private String email;
    private Instant regDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }

    public void setId(String id) { this.id = id; }

    public String getCustName() { return this.name; }

    public void setCustName(String name) { this.name = name; }

    @DynamoDbSortKey
    public String getEmail() { return this.email; }

    public void setEmail(String email) { this.email = email; }

    public Instant getRegistrationDate() { return this.regDate; }

    public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", email=" + email
                + ", regDate=" + regDate + "]";
    }
}
```

Setelah Anda membuat kelas data beranotasi, gunakan untuk membuat`TableSchema`, seperti yang ditunjukkan pada cuplikan berikut.

```
static final TableSchema<Customer> customerTableSchema = TableSchema.fromBean(Customer.class);
```

A `TableSchema` dirancang untuk menjadi statis dan tidak dapat diubah. Anda biasanya dapat membuat instance pada waktu pemuatan kelas.

Metode `TableSchema.fromBean()` pabrik statis mengintrospeksi kacang untuk menghasilkan pemetaan atribut kelas data (properti) ke dan dari atribut DynamoDB.

Untuk contoh bekerja dengan model data yang terdiri dari beberapa kelas data, lihat `Person` kelas di [Bekerja dengan atribut yang kacang, peta, daftar, dan set](ddb-en-client-adv-features-nested.md) bagian tersebut.

## Gunakan pembangun
<a name="ddb-en-client-gs-tableschema-builder"></a>

Anda dapat melewatkan biaya introspeksi kacang jika Anda menentukan skema tabel dalam kode. Jika Anda membuat kode skema, kelas Anda tidak perlu mengikuti standar JavaBean penamaan dan juga tidak perlu dianotasi. Contoh berikut menggunakan pembangun dan setara dengan contoh `Customer` kelas yang menggunakan anotasi.

```
static final TableSchema<Customer> customerTableSchema =
                TableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(Customer::getId)
                                .setter(Customer::setId)
                                .tags(StaticAttributeTags.primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("email")
                                .getter(Customer::getEmail)
                                .setter(Customer::setEmail)
                                .tags(StaticAttributeTags.primarySortKey()))
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getCustName)
                                .setter(Customer::setCustName))
                        .addAttribute(Instant.class, a -> a.name("registrationDate")
                                .getter(Customer::getRegistrationDate)
                                .setter(Customer::setRegistrationDate))
                        .build();
```

# Buat klien yang disempurnakan dan `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## Buat klien yang disempurnakan
<a name="ddb-en-client-getting-started-dynamodbTable-eclient"></a>

[DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)Kelas atau rekan asinkron, [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html), adalah titik masuk untuk bekerja dengan DynamoDB Enhanced Client API.

Klien yang disempurnakan membutuhkan standar `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)` untuk melakukan pekerjaan. API menawarkan dua cara untuk membuat `DynamoDbEnhancedClient` instance. Opsi pertama, yang ditunjukkan dalam cuplikan berikut, membuat standar `DynamoDbClient` dengan pengaturan default diambil dari pengaturan konfigurasi.

```
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();
```

Jika Anda ingin mengonfigurasi klien standar yang mendasarinya, Anda dapat menyediakannya ke metode pembangun klien yang disempurnakan seperti yang ditunjukkan pada cuplikan berikut.

```
// Configure an instance of the standard DynamoDbClient.
DynamoDbClient standardClient = DynamoDbClient.builder()
    .region(Region.US_EAST_1)
    .credentialsProvider(ProfileCredentialsProvider.create())
    .build();

// Use the configured standard client with the enhanced client.
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
    .dynamoDbClient(standardClient)
    .build();
```

## Buat sebuah `DynamoDbTable` instance
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

Pikirkan a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)sebagai representasi sisi klien dari tabel DynamoDB yang menggunakan fungsionalitas pemetaan yang disediakan oleh file. `TableSchema` `DynamoDbTable`Kelas menyediakan metode untuk operasi CRUD yang memungkinkan Anda berinteraksi dengan tabel DynamoDB tunggal.

`DynamoDbTable<T>`adalah kelas generik yang mengambil argumen tipe tunggal, apakah itu kelas khusus atau `EnhancedDocument` saat bekerja dengan item tipe dokumen. Jenis argumen ini menetapkan hubungan antara kelas yang Anda gunakan dan tabel DynamoDB tunggal.

Gunakan metode `table()` pabrik `DynamoDbEnhancedClient` untuk membuat `DynamoDbTable` instance seperti yang ditunjukkan pada cuplikan berikut.

```
static final DynamoDbTable<Customer> customerTable = 
        enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

`DynamoDbTable`contoh adalah kandidat untuk lajang karena mereka tidak dapat diubah dan dapat digunakan di seluruh aplikasi Anda.

Kode Anda sekarang memiliki representasi dalam memori dari tabel DynamoDB yang dapat bekerja dengan instance. `Customer` Tabel DynamoDB yang sebenarnya mungkin atau mungkin tidak ada. Jika tabel bernama `Customer` sudah ada, Anda dapat mulai melakukan operasi CRUD terhadapnya. Jika tidak ada, gunakan `DynamoDbTable` instance untuk membuat tabel seperti yang dibahas di bagian berikutnya.

# Buat tabel DynamoDB jika diperlukan
<a name="ddb-en-client-gs-ddbtable"></a>

Setelah Anda membuat `DynamoDbTable` instance, gunakan untuk melakukan pembuatan tabel *satu kali* di DynamoDB.

## Buat kode contoh tabel
<a name="ddb-en-client-gs-ddbtable-createex"></a>

Contoh berikut membuat tabel DynamoDB berdasarkan `Customer` kelas data. 

Contoh ini membuat tabel DynamoDB dengan `Customer` nama —identik dengan nama kelas—tetapi nama tabel bisa menjadi sesuatu yang lain. Apa pun nama Anda tabel, Anda harus menggunakan nama ini dalam aplikasi tambahan untuk bekerja dengan tabel. Berikan nama ini ke `table()` metode kapan pun Anda membuat `DynamoDbTable` objek lain agar dapat bekerja dengan tabel DynamoDB yang mendasarinya.

Parameter lambda Java`builder`,, diteruskan ke `createTable` metode memungkinkan Anda [menyesuaikan tabel](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html). Dalam contoh ini, [throughput yang disediakan dikonfigurasi](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual). Jika Anda ingin menggunakan pengaturan default saat membuat tabel, lewati pembangun seperti yang ditunjukkan pada cuplikan berikut.

```
customerTable.createTable();
```

Saat pengaturan default digunakan, nilai untuk throughput yang disediakan tidak disetel. Sebagai gantinya, mode penagihan untuk tabel diatur ke [sesuai permintaan](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand).

Contoh ini juga menggunakan `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)` sebelum mencoba untuk mencetak nama tabel yang diterima dalam respon. Pembuatan meja membutuhkan waktu. Oleh karena itu, menggunakan pelayan berarti Anda tidak perlu menulis logika yang melakukan polling layanan DynamoDB untuk melihat apakah tabel ada sebelum menggunakan tabel.

### Impor
<a name="ddb-en-client-gs-ddbtable-imports"></a>

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.core.internal.waiters.ResponseOrException;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

### Kode
<a name="ddb-en-client-gs-ddbtable-code"></a>

```
 public static void createCustomerTable(DynamoDbTable<Customer> customerTable, DynamoDbClient standardClient) {
     // Create the DynamoDB table using the 'customerTable' DynamoDbTable instance.
     customerTable.createTable(builder -> builder
             .provisionedThroughput(b -> b
                     .readCapacityUnits(10L)
                     .writeCapacityUnits(10L)
                     .build())
     );
     // The DynamoDbClient instance (named 'standardClient') passed to the builder for the DynamoDbWaiter is the same instance
     // that was passed to the builder of the DynamoDbEnhancedClient instance that we created previously.
     // By using the same instance, it ensures that the same Region that was configured on the standard DynamoDbClient 
     // instance is used for other service clients that accept a DynamoDbClient during construction.
     try (DynamoDbWaiter waiter = DynamoDbWaiter.builder().client(standardClient).build()) { // DynamoDbWaiter is Autocloseable
         ResponseOrException<DescribeTableResponse> response = waiter
                 .waitUntilTableExists(builder -> builder.tableName("Customer").build())
                 .matched();
         DescribeTableResponse tableDescription = response.response().orElseThrow(
                 () -> new RuntimeException("Customer table was not created."));
         // The actual error can be inspected in response.exception()
         logger.info("Customer table was created.");
     }
 }
```

**catatan**  
Nama atribut tabel DynamoDB dimulai dengan huruf kecil ketika tabel dihasilkan dari kelas data. Jika Anda ingin nama atribut tabel dimulai dengan huruf besar, gunakan [`@DynamoDbAttribute(NAME)`anotasi](ddb-en-client-adv-features-inex-attr.md) dan berikan nama yang Anda inginkan sebagai parameter.

# Lakukan operasi
<a name="ddb-en-client-gs-use"></a>

Setelah tabel dibuat, gunakan `DynamoDbTable` instance untuk melakukan operasi terhadap tabel DynamoDB. 

Dalam contoh berikut, singleton `DynamoDbTable<Customer>` dilewatkan sebagai parameter bersama dengan contoh [kelas `Customer` data](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) untuk menambahkan item baru ke tabel.

```
    public static void putItemExample(DynamoDbTable<Customer> customerTable, Customer customer){
        logger.info(customer.toString());
        customerTable.putItem(customer);
    }
```

## Objek `Customer`
<a name="perform_ops_create_customer_instatnce"></a>

```
        Customer customer = new Customer();
        customer.setId("1");
        customer.setCustName("Customer Name");
        customer.setEmail("customer@example.com");
        customer.setRegistrationDate(Instant.parse("2023-07-03T10:15:30.00Z"));
```

Sebelum mengirim `customer` objek ke layanan DynamoDB, catat output dari metode objek untuk membandingkannya dengan apa yang dikirim `toString()` klien yang disempurnakan.

```
Customer [id=1, name=Customer Name, email=customer@example.com, regDate=2023-07-03T10:15:30Z]
```

Pencatatan tingkat kabel menunjukkan muatan permintaan yang dihasilkan. Klien yang disempurnakan menghasilkan representasi tingkat rendah dari kelas data. `regDate`Atribut, yang merupakan `Instant` tipe di Java, direpresentasikan sebagai string DynamoDB.

```
{
  "TableName": "Customer",
  "Item": {
    "registrationDate": {
      "S": "2023-07-03T10:15:30Z"
    },
    "id": {
      "S": "1"
    },
    "custName": {
      "S": "Customer Name"
    },
    "email": {
      "S": "customer@example.com"
    }
  }
}
```

# Bekerja dengan tabel yang ada
<a name="ddb-en-client-gs-existingtable"></a>

Bagian sebelumnya menunjukkan cara membuat tabel DynamoDB dimulai dengan kelas data Java. Jika Anda sudah memiliki tabel yang ada dan ingin menggunakan fitur klien yang disempurnakan, Anda dapat membuat kelas data Java untuk bekerja dengan tabel. Anda perlu memeriksa tabel DynamoDB dan menambahkan anotasi yang diperlukan ke kelas data. 

Sebelum Anda bekerja dengan tabel yang ada, panggil `DynamoDbEnhanced.table()` metode. Ini dilakukan pada contoh sebelumnya dengan pernyataan berikut.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

Setelah `DynamoDbTable` instance dikembalikan, Anda dapat mulai bekerja segera dengan tabel yang mendasarinya. Anda tidak perlu membuat ulang tabel dengan memanggil `DynamoDbTable.createTable()` metode.

Contoh berikut menunjukkan ini dengan segera mengambil `Customer` contoh dari tabel DynamoDB.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
// The Customer table exists already and has an item with a primary key value of "1" and a sort key value of "customer@example.com".
customerTable.getItem(
        Key.builder().
                partitionValue("1").
                sortValue("customer@example.com").build());
```

**penting**  
Nama tabel yang digunakan dalam `table()` metode harus cocok dengan nama tabel DynamoDB yang ada.

# Pelajari dasar-dasar DynamoDB Enhanced Client API
<a name="ddb-en-client-use"></a>

[Topik ini membahas fitur dasar DynamoDB Enhanced Client API dan membandingkannya dengan API klien DynamoDB standar.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html)

Jika Anda baru mengenal DynamoDB Enhanced Client API, kami sarankan Anda melalui tutorial [pengantar](ddb-en-client-getting-started.md) untuk membiasakan diri dengan kelas fundamental.

## item DynamoDB di Java
<a name="ddb-en-client-use-usecase"></a>

Tabel DynamoDB menyimpan item. Bergantung pada kasus penggunaan Anda, item di sisi Java dapat berbentuk data atau struktur terstruktur statis yang dibuat secara dinamis. 

Jika kasus penggunaan Anda memanggil item dengan kumpulan atribut yang konsisten, gunakan [kelas beranotasi](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) atau gunakan [pembuat](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder) untuk menghasilkan tipe statis yang sesuai. `TableSchema` 

Atau, jika Anda perlu menyimpan item yang terdiri dari berbagai struktur, buat`DocumentTableSchema`. `DocumentTableSchema`adalah bagian dari [Enhanced Document API](ddb-en-client-doc-api.md) dan hanya memerlukan kunci primer yang diketik secara statis dan bekerja dengan `EnhancedDocument` instance untuk menyimpan elemen data. Enhanced Document API dibahas dalam [topik lain.](ddb-en-client-doc-api.md)

## Tipe atribut untuk kelas model data
<a name="ddb-en-client-use-types"></a>

Meskipun DynamoDB [mendukung sejumlah kecil tipe atribut](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) dibandingkan dengan sistem tipe kaya Java, DynamoDB Enhanced Client API menyediakan mekanisme untuk mengonversi anggota kelas Java ke dan dari tipe atribut DynamoDB.

Jenis atribut (properti) kelas data Java Anda harus berupa tipe objek, bukan primitif. Misalnya, selalu gunakan `Long` dan `Integer` objek tipe data, bukan `long` dan `int` primitif.

[Secara default, DynamoDB Enhanced Client API mendukung konverter atribut untuk sejumlah besar tipe, [seperti](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html) Integer, String[,](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html) dan Instant. [BigDecimal](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/BigDecimalAttributeConverter.html)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/InstantAsStringAttributeConverter.html) Daftar ini muncul di [kelas implementasi AttributeConverter antarmuka yang dikenal](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html). Daftar ini mencakup banyak jenis dan koleksi seperti peta, daftar, dan set.

Untuk menyimpan data untuk jenis atribut yang tidak didukung secara default atau tidak sesuai dengan JavaBean konvensi, Anda dapat menulis `AttributeConverter` implementasi khusus untuk melakukan konversi. Lihat bagian konversi atribut untuk [contoh](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example).

Untuk menyimpan data untuk tipe atribut yang kelasnya sesuai dengan spesifikasi kacang Java (atau [kelas data yang tidak dapat diubah](ddb-en-client-use-immut.md)), Anda dapat mengambil dua pendekatan. 
+ Jika Anda memiliki akses ke file sumber, Anda dapat membuat anotasi kelas dengan `@DynamoDbBean` (atau`@DynamoDbImmutable`). Bagian yang membahas atribut bersarang menunjukkan [contoh](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-anno) penggunaan kelas beranotasi.
+ Jika tidak memiliki akses ke file sumber dari kelas JavaBean data untuk atribut (atau Anda tidak ingin membubuhi keterangan file sumber kelas yang Anda memiliki akses ke), maka Anda dapat menggunakan pendekatan builder. Ini menciptakan skema tabel tanpa mendefinisikan kunci. Kemudian, Anda dapat menyusun skema tabel ini di dalam skema tabel lain untuk melakukan pemetaan. Bagian atribut bersarang memiliki [contoh](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-builder) yang menunjukkan penggunaan skema bersarang.

### Nilai nol
<a name="ddb-en-client-use-types-nulls"></a>

Saat Anda menggunakan `putItem` metode ini, klien yang disempurnakan tidak menyertakan atribut bernilai nol dari objek data yang dipetakan dalam permintaan ke DynamoDB.

Perilaku default SDK untuk `updateItem` permintaan menghapus atribut dari item di DynamoDB yang disetel ke null dalam objek yang Anda kirimkan dalam metode. `updateItem` Jika Anda bermaksud memperbarui beberapa nilai atribut dan menjaga yang lain tidak berubah, Anda memiliki dua opsi.
+ Ambil item (dengan menggunakan`getItem`) sebelum Anda membuat perubahan pada nilai. Dengan menggunakan pendekatan ini, SDK mengirimkan semua nilai yang diperbarui dan lama ke DynamoDB.
+ Gunakan salah satu `[IgnoreNullsMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html).SCALAR_ONLY` atau `IgnoreNullsMode.MAPS_ONLY` ketika Anda membuat permintaan untuk memperbarui item. Kedua mode mengabaikan properti bernilai nol dalam objek yang mewakili atribut skalar di DynamoDB. [Perbarui item yang berisi tipe kompleks](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-updates)Topik dalam panduan ini berisi informasi lebih lanjut tentang `IgnoreNullsMode` nilai-nilai dan cara bekerja dengan tipe yang kompleks.

Contoh berikut menunjukkan `ignoreNullsMode()` untuk `updateItem()` metode ini.

```
    public static void updateItemNullsExample() {
        Customer customer = new Customer();
        customer.setCustName("CustomerName");
        customer.setEmail("email");
        customer.setId("1");
        customer.setRegistrationDate(Instant.now());

        logger.info("Original customer: {}", customer);

        // Put item with values for all attributes.
        try {
            customerAsyncDynamoDbTable.putItem(customer).join();
        } catch (RuntimeException rte) {
            logger.error("A exception occurred during putItem: {}", rte.getCause().getMessage(), rte);
            return;
        }

        // Create a Customer instance with the same 'id' and 'email' values, but a different 'name' value.
        // Do not set the 'registrationDate' attribute.
        Customer customerForUpdate = new Customer();
        customerForUpdate.setCustName("NewName");
        customerForUpdate.setEmail("email");
        customerForUpdate.setId("1");

        // Update item without setting the 'registrationDate' property and set IgnoreNullsMode to SCALAR_ONLY.
        try {
            Customer updatedWithNullsIgnored = customerAsyncDynamoDbTable.updateItem(b -> b
                            .item(customerForUpdate)
                            .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY))
                    .join();
            logger.info("Customer updated with nulls ignored: {}", updatedWithNullsIgnored.toString());
        } catch (RuntimeException rte) {
            logger.error("An exception occurred during updateItem: {}", rte.getCause().getMessage(), rte);
            return;
        }

        // Update item without setting the registrationDate attribute and not setting ignoreNulls to true.
        try {
            Customer updatedWithNullsUsed = customerAsyncDynamoDbTable.updateItem(customerForUpdate)
                    .join();
            logger.info("Customer updated with nulls used: {}", updatedWithNullsUsed.toString());
        } catch (RuntimeException rte) {
            logger.error("An exception occurred during updateItem: {}", rte.getCause().getMessage(), rte);
        }
    }


// Logged lines. 
Original customer: Customer [id=1, name=CustomerName, email=email, regDate=2024-10-11T14:12:30.222858Z]
Customer updated with nulls ignored: Customer [id=1, name=NewName, email=email, regDate=2024-10-11T14:12:30.222858Z]
Customer updated with nulls used: Customer [id=1, name=NewName, email=email, regDate=null]
```

## Metode dasar DynamoDB Enhanced Client
<a name="ddb-en-client-use-basic-ops"></a>

Metode dasar peta klien yang disempurnakan ke operasi layanan DynamoDB yang dinamai menurut namanya. Contoh berikut menunjukkan variasi paling sederhana dari setiap metode. Anda dapat menyesuaikan setiap metode dengan meneruskan objek permintaan yang disempurnakan. Objek permintaan yang disempurnakan menawarkan sebagian besar fitur yang tersedia di klien DynamoDB standar. Mereka sepenuhnya didokumentasikan dalam Referensi AWS SDK for Java 2.x API.

Contoh menggunakan yang [`Customer` kelas](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) ditunjukkan sebelumnya.

```
// CreateTable
customerTable.createTable();

// GetItem
Customer customer = customerTable.getItem(Key.builder().partitionValue("a123").build());

// UpdateItem
Customer updatedCustomer = customerTable.updateItem(customer);

// PutItem
customerTable.putItem(customer);

// DeleteItem
Customer deletedCustomer = customerTable.deleteItem(Key.builder().partitionValue("a123").sortValue(456).build());

// Query
PageIterable<Customer> customers = customerTable.query(keyEqualTo(k -> k.partitionValue("a123")));

// Scan
PageIterable<Customer> customers = customerTable.scan();

// BatchGetItem
BatchGetResultPageIterable batchResults = 
    enhancedClient.batchGetItem(r -> r.addReadBatch(ReadBatch.builder(Customer.class)
                                      .mappedTableResource(customerTable)
                                      .addGetItem(key1)
                                      .addGetItem(key2)
                                      .addGetItem(key3)
                                      .build()));

// BatchWriteItem
batchResults = enhancedClient.batchWriteItem(r -> r.addWriteBatch(WriteBatch.builder(Customer.class)
                                                   .mappedTableResource(customerTable)
                                                   .addPutItem(customer)
                                                   .addDeleteItem(key1)
                                                   .addDeleteItem(key1)
                                                   .build()));

// TransactGetItems
transactResults = enhancedClient.transactGetItems(r -> r.addGetItem(customerTable, key1)
                                                        .addGetItem(customerTable, key2));

// TransactWriteItems
enhancedClient.transactWriteItems(r -> r.addConditionCheck(customerTable, 
                                                           i -> i.key(orderKey)
                                                                 .conditionExpression(conditionExpression))
                                        .addUpdateItem(customerTable, customer)
                                        .addDeleteItem(customerTable, key));
```

## Bandingkan DynamoDB Enhanced Client dengan klien DynamoDB standar
<a name="ddb-en-client-use-compare"></a>

Baik APIs klien DynamoDB [- standar [dan](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) ditingkatkan -](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html) memungkinkan Anda bekerja dengan tabel DynamoDB untuk melakukan operasi tingkat data CRUD (membuat, membaca, memperbarui, dan menghapus). Perbedaan antara klien APIs adalah bagaimana hal itu dicapai. Menggunakan klien standar, Anda bekerja secara langsung dengan atribut data tingkat rendah. API klien yang disempurnakan menggunakan kelas Java yang sudah dikenal dan memetakan ke API tingkat rendah di belakang layar.

Sementara kedua klien APIs mendukung operasi tingkat data, klien DynamoDB standar juga mendukung operasi tingkat sumber daya. Operasi tingkat sumber daya mengelola database, seperti membuat cadangan, daftar tabel, dan memperbarui tabel. API klien yang disempurnakan mendukung sejumlah operasi tingkat sumber daya tertentu seperti membuat, mendeskripsikan, dan menghapus tabel.

Untuk mengilustrasikan pendekatan berbeda yang digunakan oleh dua klien APIs, contoh kode berikut menunjukkan pembuatan `ProductCatalog` tabel yang sama menggunakan klien standar dan klien yang disempurnakan.

### Bandingkan: Buat tabel menggunakan klien DynamoDB standar
<a name="ddb-en-client-use-compare-cs1"></a>

```
DependencyFactory.dynamoDbClient().createTable(builder -> builder
        .tableName(TABLE_NAME)
        .attributeDefinitions(
                b -> b.attributeName("id").attributeType(ScalarAttributeType.N),
                b -> b.attributeName("title").attributeType(ScalarAttributeType.S),
                b -> b.attributeName("isbn").attributeType(ScalarAttributeType.S)
        )
        .keySchema(
                builder1 -> builder1.attributeName("id").keyType(KeyType.HASH),
                builder2 -> builder2.attributeName("title").keyType(KeyType.RANGE)
        )
        .globalSecondaryIndexes(builder3 -> builder3
                        .indexName("products_by_isbn")
                        .keySchema(builder2 -> builder2
                                .attributeName("isbn").keyType(KeyType.HASH))
                        .projection(builder2 -> builder2
                                .projectionType(ProjectionType.INCLUDE)
                                .nonKeyAttributes("price", "authors"))
                        .provisionedThroughput(builder4 -> builder4
                                .writeCapacityUnits(5L).readCapacityUnits(5L))
        )
        .provisionedThroughput(builder1 -> builder1
                .readCapacityUnits(5L).writeCapacityUnits(5L))
);
```

### Bandingkan: Buat tabel menggunakan DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs2"></a>

```
DynamoDbEnhancedClient enhancedClient = DependencyFactory.enhancedClient();
productCatalog = enhancedClient.table(TABLE_NAME, TableSchema.fromImmutableClass(ProductCatalog.class));
productCatalog.createTable(b -> b
        .provisionedThroughput(b1 -> b1.readCapacityUnits(5L).writeCapacityUnits(5L))
        .globalSecondaryIndices(b2 -> b2.indexName("products_by_isbn")
                .projection(b4 -> b4
                        .projectionType(ProjectionType.INCLUDE)
                        .nonKeyAttributes("price", "authors"))
                .provisionedThroughput(b3 -> b3.writeCapacityUnits(5L).readCapacityUnits(5L))
        )
);
```

Klien yang disempurnakan menggunakan kelas data beranotasi berikut. DynamoDB Enhanced Client memetakan tipe data Java ke tipe data DynamoDB untuk kode verbose yang lebih sedikit yang lebih mudah diikuti. `ProductCatalog`adalah contoh menggunakan kelas yang tidak dapat diubah dengan DynamoDB Enhanced Client. Penggunaan kelas Immutable untuk kelas data yang dipetakan [dibahas nanti dalam topik](ddb-en-client-use-immut.md) ini.

### `ProductCatalog` kelas
<a name="ddb-en-client-use-compare-cs3"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbIgnore;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.Set;

@DynamoDbImmutable(builder = ProductCatalog.Builder.class)
public class ProductCatalog implements Comparable<ProductCatalog> {
    private Integer id;
    private String title;
    private String isbn;
    private Set<String> authors;
    private BigDecimal price;


    private ProductCatalog(Builder builder){
        this.authors = builder.authors;
        this.id = builder.id;
        this.isbn = builder.isbn;
        this.price = builder.price;
        this.title = builder.title;
    }

    public static Builder builder(){ return new Builder(); }

    @DynamoDbPartitionKey
    public Integer id() { return id; }
    
    @DynamoDbSortKey
    public String title() { return title; }
    
    @DynamoDbSecondaryPartitionKey(indexNames = "products_by_isbn")
    public String isbn() { return isbn; }
    public Set<String> authors() { return authors; }
    public BigDecimal price() { return price; }


    public static final class Builder {
      private Integer id;
      private String title;
      private String isbn;
      private Set<String> authors;
      private BigDecimal price;
      private Builder(){}

      public Builder id(Integer id) { this.id = id; return this; }
      public Builder title(String title) { this.title = title; return this; }
      public Builder isbn(String ISBN) { this.isbn = ISBN; return this; }
      public Builder authors(Set<String> authors) { this.authors = authors; return this; }
      public Builder price(BigDecimal price) { this.price = price; return this; }
      public ProductCatalog build() { return new ProductCatalog(this); }
  }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("ProductCatalog{");
        sb.append("id=").append(id);
        sb.append(", title='").append(title).append('\'');
        sb.append(", isbn='").append(isbn).append('\'');
        sb.append(", authors=").append(authors);
        sb.append(", price=").append(price);
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ProductCatalog that = (ProductCatalog) o;
        return id.equals(that.id) && title.equals(that.title) && Objects.equals(isbn, that.isbn) && Objects.equals(authors, that.authors) && Objects.equals(price, that.price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, title, isbn, authors, price);
    }

    @Override
    @DynamoDbIgnore
    public int compareTo(ProductCatalog other) {
        if (this.id.compareTo(other.id) != 0){
            return this.id.compareTo(other.id);
        } else {
            return this.title.compareTo(other.title);
        }
    }
}
```

Dua contoh kode berikut dari penulisan batch menggambarkan verboseness dan kurangnya keamanan tipe saat menggunakan klien standar sebagai lawan dari klien yang ditingkatkan.

### Bandingkan: Batch write menggunakan klien DynamoDB standar
<a name="ddb-en-client-use-compare-cs4"></a>

```
    public static void batchWriteStandard(DynamoDbClient dynamoDbClient, String tableName) {

        Map<String, AttributeValue> catalogItem = Map.of(
                "authors", AttributeValue.builder().ss("a", "b").build(),
                "id", AttributeValue.builder().n("1").build(),
                "isbn", AttributeValue.builder().s("1-565-85698").build(),
                "title", AttributeValue.builder().s("Title 1").build(),
                "price", AttributeValue.builder().n("52.13").build());

        Map<String, AttributeValue> catalogItem2 = Map.of(
                "authors", AttributeValue.builder().ss("a", "b", "c").build(),
                "id", AttributeValue.builder().n("2").build(),
                "isbn", AttributeValue.builder().s("1-208-98073").build(),
                "title", AttributeValue.builder().s("Title 2").build(),
                "price", AttributeValue.builder().n("21.99").build());

        Map<String, AttributeValue> catalogItem3 = Map.of(
                "authors", AttributeValue.builder().ss("g", "k", "c").build(),
                "id", AttributeValue.builder().n("3").build(),
                "isbn", AttributeValue.builder().s("7-236-98618").build(),
                "title", AttributeValue.builder().s("Title 3").build(),
                "price", AttributeValue.builder().n("42.00").build());

        Set<WriteRequest> writeRequests = Set.of(
                WriteRequest.builder().putRequest(b -> b.item(catalogItem)).build(),
                WriteRequest.builder().putRequest(b -> b.item(catalogItem2)).build(),
                WriteRequest.builder().putRequest(b -> b.item(catalogItem3)).build());

        Map<String, Set<WriteRequest>> productCatalogItems = Map.of(
                "ProductCatalog", writeRequests);

        BatchWriteItemResponse response = dynamoDbClient.batchWriteItem(b -> b.requestItems(productCatalogItems));

        logger.info("Unprocessed items: " + response.unprocessedItems().size());
    }
```

### Bandingkan: Batch write menggunakan DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs5"></a>

```
    public static void batchWriteEnhanced(DynamoDbTable<ProductCatalog> productCatalog) {
        ProductCatalog prod = ProductCatalog.builder()
                .id(1)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(52.13))
                .title("Title 1")
                .build();
        ProductCatalog prod2 = ProductCatalog.builder()
                .id(2)
                .isbn("1-208-98073")
                .authors(new HashSet<>(Arrays.asList("a", "b", "c")))
                .price(BigDecimal.valueOf(21.99))
                .title("Title 2")
                .build();
        ProductCatalog prod3 = ProductCatalog.builder()
                .id(3)
                .isbn("7-236-98618")
                .authors(new HashSet<>(Arrays.asList("g", "k", "c")))
                .price(BigDecimal.valueOf(42.00))
                .title("Title 3")
                .build();

        BatchWriteResult batchWriteResult = DependencyFactory.enhancedClient()
                .batchWriteItem(b -> b.writeBatches(
                        WriteBatch.builder(ProductCatalog.class)
                                .mappedTableResource(productCatalog)
                                .addPutItem(prod).addPutItem(prod2).addPutItem(prod3)
                                .build()
                ));
        logger.info("Unprocessed items: " + batchWriteResult.unprocessedPutItemsForTable(productCatalog).size());
    }
```

# Bekerja dengan kelas data yang tidak dapat diubah
<a name="ddb-en-client-use-immut"></a>

Fitur pemetaan DynamoDB Enhanced Client API bekerja dengan kelas data yang tidak dapat diubah. Kelas yang tidak dapat diubah hanya memiliki getter dan memerlukan kelas pembangun yang digunakan SDK untuk membuat instance kelas. Alih-alih menggunakan `@DynamoDbBean` anotasi seperti yang ditunjukkan di [kelas Pelanggan, kelas](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) yang tidak dapat diubah menggunakan `@DynamoDbImmutable` anotasi, yang mengambil parameter yang menunjukkan kelas pembuat untuk digunakan.

Kelas berikut adalah versi yang tidak dapat diubah dari. `Customer`

```
package org.example.tests.model.immutable;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbImmutable(builder = CustomerImmutable.Builder.class)
public class CustomerImmutable {
    private final String id;
    private final String name;
    private final String email;
    private final Instant regDate;

    private CustomerImmutable(Builder b) {
        this.id = b.id;
        this.email = b.email;
        this.name = b.name;
        this.regDate = b.regDate;
    }

    // This method will be automatically discovered and used by the TableSchema.
    public static Builder builder() { return new Builder(); }

    @DynamoDbPartitionKey
    public String id() { return this.id; }

    @DynamoDbSortKey
    public String email() { return this.email; }

    @DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name")
    public String name() { return this.name; }

    @DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"})
    public Instant regDate() { return this.regDate; }

    public static final class Builder {
        private String id;
        private String email;
        private String name;
        private Instant regDate;

        // The private Builder constructor is visible to the enclosing CustomerImmutable class.
        private Builder() {}

        public Builder id(String id) { this.id = id; return this; }
        public Builder email(String email) { this.email = email; return this; }
        public Builder name(String name) { this.name = name; return this; }
        public Builder regDate(Instant regDate) { this.regDate = regDate; return this; }

        // This method will be automatically discovered and used by the TableSchema.
        public CustomerImmutable build() { return new CustomerImmutable(this); }
    }
}
```

Anda harus memenuhi persyaratan berikut ketika Anda membuat anotasi kelas data dengan. `@DynamoDbImmutable`

1. Setiap metode yang keduanya bukan penggantian `Object.class` dan belum dianotasi `@DynamoDbIgnore` harus menjadi pengambil untuk atribut tabel DynamoDB.

1. Setiap pengambil harus memiliki penyetel case-sensitive yang sesuai pada kelas builder.

1. Hanya satu dari kondisi konstruksi berikut yang harus dipenuhi.
   + Kelas builder harus memiliki konstruktor default publik.
   + Kelas data harus memiliki metode statis publik bernama `builder()` yang tidak mengambil parameter dan mengembalikan instance dari kelas builder. Opsi ini ditampilkan di kelas yang tidak dapat diubah`Customer`.

1.  Kelas builder harus memiliki metode publik bernama `build()` yang tidak mengambil parameter dan mengembalikan instance dari kelas yang tidak dapat diubah. 

Untuk membuat `TableSchema` untuk kelas abadi Anda, gunakan `fromImmutableClass()` metode pada `TableSchema` seperti yang ditunjukkan dalam cuplikan berikut.

```
static final TableSchema<CustomerImmutable> customerImmutableTableSchema = 
                         TableSchema.fromImmutableClass(CustomerImmutable.class);
```

Sama seperti Anda dapat membuat tabel DynamoDB dari kelas yang bisa berubah, Anda dapat membuatnya dari kelas yang tidak dapat diubah dengan panggilan satu kali ke dari seperti *yang ditunjukkan dalam* contoh `createTable()` cuplikan berikut`DynamoDbTable`.

```
static void createTableFromImmutable(DynamoDbEnhancedClient enhancedClient, String tableName, DynamoDbWaiter waiter){
    // First, create an in-memory representation of the table using the 'table()' method of the DynamoDb Enhanced Client.
    // 'table()' accepts a name for the table and a TableSchema instance that you created previously.
    DynamoDbTable<CustomerImmutable> customerDynamoDbTable = enhancedClient
            .table(tableName, TableSchema.fromImmutableClass(CustomerImmutable.class));
        
    // Second, call the 'createTable()' method on the DynamoDbTable instance.
    customerDynamoDbTable.createTable();
    waiter.waitUntilTableExists(b -> b.tableName(tableName));
}
```

## Gunakan perpustakaan pihak ketiga, seperti Lombok
<a name="ddb-en-client-use-immut-lombok"></a>

Perpustakaan pihak ketiga, seperti [Project Lombok](https://projectlombok.org/), membantu menghasilkan kode boilerplate yang terkait dengan objek yang tidak dapat diubah. DynamoDB Enhanced Client API bekerja dengan pustaka ini selama kelas data mengikuti konvensi yang dirinci di bagian ini. 

Contoh berikut menunjukkan `CustomerImmutable` kelas abadi dengan anotasi Lombok. Perhatikan bagaimana `onMethod` fitur Lombok menyalin anotasi DynamoDB berbasis atribut, seperti, ke kode yang dihasilkan. `@DynamoDbPartitionKey`

```
@Value
@Builder
@DynamoDbImmutable(builder = Customer.CustomerBuilder.class)
public class Customer {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;

    @Getter(onMethod_=@DynamoDbSortKey)
    private String email;

    @Getter(onMethod_=@DynamoDbSecondaryPartitionKey(indexNames = "customers_by_name"))
    private String name;

    @Getter(onMethod_=@DynamoDbSecondarySortKey(indexNames = {"customers_by_date", "customers_by_name"}))
    private Instant createdDate;
}
```

# Gunakan ekspresi dan kondisi
<a name="ddb-en-client-expressions"></a>

[Ekspresi dalam DynamoDB Enhanced Client API adalah representasi Java dari ekspresi DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html)

DynamoDB Enhanced Client API menggunakan tiga jenis ekspresi:

[Ekspresi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)  
`Expression`Kelas digunakan ketika Anda menentukan kondisi dan filter.

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)  
Jenis ekspresi ini merupakan [kondisi utama](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions) untuk operasi kueri.

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)  
Kelas ini membantu Anda menulis ekspresi [pembaruan DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) dan saat ini digunakan dalam kerangka ekstensi saat Anda memperbarui item.

## Anatomi ekspresi
<a name="ddb-en-client-expressions-compoonents"></a>

Ekspresi terdiri dari yang berikut:
+ Ekspresi string (wajib). String berisi ekspresi logika DynamoDB dengan nama placeholder untuk nama atribut dan nilai atribut.
+ Peta nilai ekspresi (biasanya diperlukan).
+ Peta nama ekspresi (opsional).

Gunakan pembangun untuk menghasilkan `Expression` objek yang mengambil bentuk umum berikut.

```
Expression expression = Expression.builder()
                            .expression(<String>)
                            .expressionNames(<Map>)
                            .expressionValues(<Map>)
                           .build()
```

`Expression`S biasanya membutuhkan peta nilai ekspresi. Peta memberikan nilai untuk placeholder dalam ekspresi string. Kunci peta terdiri dari nama placeholder yang didahului dengan titik dua (`:`) dan nilai peta adalah instance dari. [AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html) [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/AttributeValues.html)Kelas memiliki metode kenyamanan untuk menghasilkan `AttributeValue` instance dari literal. Atau, Anda dapat menggunakan `AttributeValue.Builder` untuk menghasilkan `AttributeValue` instance.

Cuplikan berikut menunjukkan peta dengan dua entri setelah baris komentar 2. String diteruskan ke `expression()` metode, ditampilkan setelah baris komentar 1, berisi placeholder yang DynamoDB menyelesaikan sebelum melakukan operasi. Cuplikan ini tidak berisi peta nama ekspresi, karena *harga* adalah nama atribut yang diizinkan.

```
    public static void scanAsync(DynamoDbAsyncTable productCatalog) {
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                .attributesToProject("id", "title", "authors", "price")
                .filterExpression(Expression.builder()
                        // 1. :min_value and :max_value are placeholders for the values provided by the map
                        .expression("price >= :min_value AND price <= :max_value")
                        // 2. Two values are needed for the expression and each is supplied as a map entry.
                        .expressionValues(
                                Map.of( ":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();
```

Jika nama atribut dalam tabel DynamoDB adalah kata cadangan, dimulai dengan angka, atau berisi spasi, peta nama ekspresi diperlukan untuk. `Expression`

Misalnya, jika nama atribut `1price` bukan `price` dalam contoh kode sebelumnya, contoh akan perlu dimodifikasi seperti yang ditunjukkan pada contoh berikut.

```
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .filterExpression(Expression.builder()
                        .expression("#price >= :min_value AND #price <= :max_value")
                        .expressionNames( Map.of("#price", "1price") )
                        .expressionValues(
                                Map.of(":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();
```

Sebuah placeholder untuk nama ekspresi dimulai dengan tanda pound ()`#`. Entri untuk peta nama ekspresi menggunakan placeholder sebagai kunci dan nama atribut sebagai nilai. Peta ditambahkan ke pembuat ekspresi dengan `expressionNames()` metode. DynamoDB menyelesaikan nama atribut sebelum melakukan operasi.

Nilai ekspresi tidak diperlukan jika fungsi digunakan dalam ekspresi string. Contoh fungsi ekspresi adalah`attribute_exists(<attribute_name>)`.

Contoh berikut membangun sebuah `Expression` yang menggunakan fungsi [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions). String ekspresi dalam contoh ini tidak menggunakan placeholder. Ekspresi ini dapat digunakan pada `putItem` operasi untuk memeriksa apakah item sudah ada dalam database dengan nilai `movie` atribut sama dengan `movie` atribut objek data.

```
Expression exp = Expression.builder().expression("attribute_not_exists (movie)").build();
```

Panduan Pengembang DynamoDB berisi informasi lengkap tentang ekspresi [tingkat rendah yang](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html) digunakan dengan DynamoDB.

## Ekspresi kondisi dan kondisional
<a name="ddb-en-client-expressions-cond"></a>

Ketika Anda menggunakan`putItem()`,`updateItem()`, dan `deleteItem()` metode, dan juga ketika Anda menggunakan transaksi dan operasi batch, Anda menggunakan `[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)` objek untuk menentukan kondisi yang DynamoDB harus memenuhi untuk melanjutkan operasi. Ekspresi ini diberi nama ekspresi kondisi. Sebagai contoh, lihat ekspresi kondisi yang digunakan dalam `addDeleteItem()` metode (setelah baris komentar 1) dari [contoh transaksi](ddb-en-client-use-multiop-trans.md#ddb-en-client-use-multiop-trans-writeitems-opcondition) yang ditunjukkan dalam panduan ini.

Ketika Anda bekerja dengan `query()` metode, suatu kondisi dinyatakan sebagai a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html). `QueryConditional`Kelas memiliki beberapa metode kenyamanan statis yang membantu Anda menulis kriteria yang menentukan item mana yang akan dibaca dari DynamoDB.

Sebagai contoh`QueryConditionals`, lihat contoh kode pertama dari [`Query`contoh metode](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-query-example) bagian panduan ini.

## Ekspresi Filter
<a name="ddb-en-client-expressions-filter"></a>

Ekspresi filter digunakan dalam operasi pemindaian dan kueri untuk memfilter item yang dikembalikan. 

Ekspresi filter diterapkan setelah semua data dibaca dari database, sehingga biaya baca sama seperti jika tidak ada filter. [Panduan *Pengembang Amazon DynamoDB* memiliki informasi lebih lanjut tentang penggunaan ekspresi filter untuk operasi kueri [dan](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression) pemindaian.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.FilterExpression)

Contoh berikut menunjukkan ekspresi filter ditambahkan ke permintaan scan. Kriteria membatasi barang yang dikembalikan ke barang dengan harga antara 8.00 dan 80,00 inklusif.

```
        Map<String, AttributeValue> expressionValues = Map.of(
                ":min_value", numberValue(8.00),
                ":max_value", numberValue(80.00));

        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                // 1. the 'attributesToProject()' method allows you to specify which values you want returned.
                .attributesToProject("id", "title", "authors", "price")
                // 2. Filter expression limits the items returned that match the provided criteria.
                .filterExpression(Expression.builder()
                        .expression("price >= :min_value AND price <= :max_value")
                        .expressionValues(expressionValues)
                        .build())
                .build();
```

## Ekspresi pembaruan
<a name="ddb-en-client-expressions-update"></a>

Metode DynamoDB Enhanced Client `updateItem()` menyediakan cara standar untuk memperbarui item di DynamoDB. [Namun, ketika Anda memerlukan lebih banyak fungsionalitas, [UpdateExpressions](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)berikan representasi type-safe dari sintaks ekspresi pembaruan DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) Misalnya, Anda dapat menggunakan `UpdateExpressions` untuk meningkatkan nilai tanpa terlebih dahulu membaca item dari DynamoDB, atau menambahkan anggota individu ke daftar. Ekspresi pembaruan saat ini tersedia di ekstensi khusus untuk `updateItem()` metode ini.

Untuk contoh yang menggunakan ekspresi pembaruan, lihat [contoh ekstensi kustom](ddb-en-client-extensions-custom.md) dalam panduan ini.

Informasi selengkapnya tentang ekspresi pembaruan tersedia di Panduan Pengembang [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).

# Bekerja dengan hasil paginasi: pemindaian dan kueri
<a name="ddb-en-client-use-multirecord"></a>

*Metode`scan`, `query` dan `batch` metode DynamoDB Enhanced Client API mengembalikan respons dengan satu halaman atau beberapa.* Sebuah halaman berisi satu atau lebih item. Kode Anda dapat memproses respons per halaman atau dapat memproses item individual.

Respons paginasi yang dikembalikan oleh `DynamoDbEnhancedClient` klien sinkron mengembalikan [PageIterable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PageIterable.html)objek, sedangkan respons yang dikembalikan oleh `DynamoDbEnhancedAsyncClient` asinkron mengembalikan objek. [PagePublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PagePublisher.html)

Bagian ini melihat pemrosesan hasil paginasi dan memberikan contoh yang menggunakan pemindaian dan kueri APIs.

## Memindai tabel
<a name="ddb-en-client-use-multirecord-scan"></a>

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer))Metode SDK sesuai dengan operasi [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) dengan nama yang sama. DynamoDB Enhanced Client API menawarkan opsi yang sama tetapi menggunakan model objek yang sudah dikenal dan menangani pagination untuk Anda.

Pertama, kita menjelajahi `PageIterable` antarmuka dengan melihat `scan` metode kelas pemetaan sinkron,. [DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)

### Gunakan API sinkron
<a name="ddb-en-client-use-multirecord-scan-sync"></a>

Contoh berikut menunjukkan `scan` metode yang menggunakan [ekspresi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html) untuk memfilter item yang dikembalikan. [ProductCatalog](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)Ini adalah objek model yang ditunjukkan sebelumnya.

Ekspresi pemfilteran yang ditampilkan setelah baris komentar 2 membatasi `ProductCatalog` item yang dikembalikan ke item dengan nilai harga antara 8,00 dan 80,00 secara inklusif.

Contoh ini juga mengecualikan `isbn` nilai dengan menggunakan `attributesToProject` metode yang ditampilkan setelah baris komentar 1.

Setelah komentar baris 3, `PageIterable` objek`pagedResults`,, dikembalikan oleh `scan` metode. `stream`Metode `PageIterable` mengembalikan [https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)objek, yang dapat Anda gunakan untuk memproses halaman. Dalam contoh ini, jumlah halaman dihitung dan dicatat.

Dimulai dengan baris komentar 4, contoh menunjukkan dua variasi mengakses `ProductCatalog` item. Versi setelah baris komentar 4a mengalir melalui setiap halaman dan mengurutkan dan mencatat item di setiap halaman. Versi setelah baris komentar 4b melewatkan iterasi halaman dan mengakses item secara langsung.

`PageIterable`Antarmuka menawarkan beberapa cara untuk memproses hasil karena dua antarmuka induknya— [https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html)dan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html). `Iterable`membawa`forEach`, `iterator` dan `spliterator` metode, dan `SdkIterable` membawa `stream` metode.

```
    public static void scanSync(DynamoDbTable<ProductCatalog> productCatalog) {

        Map<String, AttributeValue> expressionValues = Map.of(
                ":min_value", numberValue(8.00),
                ":max_value", numberValue(80.00));

        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                // 1. the 'attributesToProject()' method allows you to specify which values you want returned.
                .attributesToProject("id", "title", "authors", "price")
                // 2. Filter expression limits the items returned that match the provided criteria.
                .filterExpression(Expression.builder()
                        .expression("price >= :min_value AND price <= :max_value")
                        .expressionValues(expressionValues)
                        .build())
                .build();

        // 3. A PageIterable object is returned by the scan method.
        PageIterable<ProductCatalog> pagedResults = productCatalog.scan(request);
        logger.info("page count: {}", pagedResults.stream().count());

        // 4. Log the returned ProductCatalog items using two variations.
        // 4a. This version sorts and logs the items of each page.
        pagedResults.stream().forEach(p -> p.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                ));
        // 4b. This version sorts and logs all items for all pages.
        pagedResults.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                );
    }
```

### Gunakan API asinkron
<a name="ddb-en-client-use-multirecord-scan-async"></a>

`scan`Metode asinkron mengembalikan hasil sebagai objek. `PagePublisher` `PagePublisher`Antarmuka memiliki dua `subscribe` metode yang dapat Anda gunakan untuk memproses halaman respons. Salah satu `subscribe` metode berasal dari antarmuka `org.reactivestreams.Publisher` induk. Untuk memproses halaman menggunakan opsi pertama ini, berikan `[Subscriber](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Subscriber.html)` instance ke `subscribe` metode. Contoh pertama yang berikut menunjukkan penggunaan `subscribe` metode.

`subscribe`Metode kedua berasal dari [SdkPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)antarmuka. Versi ini `subscribe` menerima [https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html)bukan a`Subscriber`. Variasi `subscribe` metode ini ditunjukkan pada contoh kedua berikut.

Contoh berikut menunjukkan versi asinkron dari `scan` metode yang menggunakan ekspresi filter yang sama yang ditunjukkan pada contoh sebelumnya. 

Setelah baris komentar 3, `DynamoDbAsyncTable.scan` mengembalikan `PagePublisher` objek. Pada baris berikutnya, kode membuat instance `org.reactivestreams.Subscriber` antarmuka,`ProductCatalogSubscriber`, yang berlangganan baris `PagePublisher` setelah komentar 4.

`Subscriber`Objek mengumpulkan `ProductCatalog` item dari setiap halaman dalam `onNext` metode setelah baris komentar 8 dalam contoh `ProductCatalogSubscriber` kelas. Item disimpan dalam `List` variabel pribadi dan diakses dalam kode panggilan dengan `ProductCatalogSubscriber.getSubscribedItems()` metode. Ini disebut setelah baris komentar 5.

Setelah daftar diambil, kode mengurutkan semua `ProductCatalog` item berdasarkan harga dan mencatat setiap item.

[CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)Di `ProductCatalogSubscriber` kelas memblokir thread panggilan sampai semua item telah ditambahkan ke daftar sebelum melanjutkan setelah baris komentar 5. 

```
    public static void scanAsync(DynamoDbAsyncTable productCatalog) {
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                .attributesToProject("id", "title", "authors", "price")
                .filterExpression(Expression.builder()
                        // 1. :min_value and :max_value are placeholders for the values provided by the map
                        .expression("price >= :min_value AND price <= :max_value")
                        // 2. Two values are needed for the expression and each is supplied as a map entry.
                        .expressionValues(
                                Map.of( ":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();

        // 3. A PagePublisher object is returned by the scan method.
        PagePublisher<ProductCatalog> pagePublisher = productCatalog.scan(request);
        ProductCatalogSubscriber subscriber = new ProductCatalogSubscriber();
        // 4. Subscribe the ProductCatalogSubscriber to the PagePublisher.
        pagePublisher.subscribe(subscriber);
        // 5. Retrieve all collected ProductCatalog items accumulated by the subscriber.
        subscriber.getSubscribedItems().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(item ->
                        logger.info(item.toString()));
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
    }
```

```
    private static class ProductCatalogSubscriber implements Subscriber<Page<ProductCatalog>> {
        private CountDownLatch latch = new CountDownLatch(1);
        private Subscription subscription;
        private List<ProductCatalog> itemsFromAllPages = new ArrayList<>();

        @Override
        public void onSubscribe(Subscription sub) {
            subscription = sub;
            subscription.request(1L);
            try {
                latch.await(); // Called by main thread blocking it until latch is released.
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onNext(Page<ProductCatalog> productCatalogPage) {
            // 8. Collect all the ProductCatalog instances in the page, then ask the publisher for one more page.
            itemsFromAllPages.addAll(productCatalogPage.items());
            subscription.request(1L);
        }

        @Override
        public void onError(Throwable throwable) {
        }

        @Override
        public void onComplete() {
            latch.countDown(); // Call by subscription thread; latch releases.
        }

        List<ProductCatalog> getSubscribedItems() {
            return this.itemsFromAllPages;
        }
    }
```

Contoh cuplikan berikut menggunakan versi `PagePublisher.subscribe` metode yang menerima baris `Consumer` setelah komentar 6. Parameter lambda Java mengkonsumsi halaman, yang selanjutnya memproses setiap item. Dalam contoh ini, setiap halaman diproses dan item pada setiap halaman diurutkan dan kemudian dicatat.

```
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

`items`Metode `PagePublisher` membuka bungkus contoh model sehingga kode Anda dapat memproses item secara langsung. Pendekatan ini ditunjukkan dalam cuplikan berikut.

```
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

## Mengkueri Tabel
<a name="ddb-en-client-use-multirecord-query"></a>

Anda dapat menggunakan DynamoDB Enhanced Client untuk menanyakan tabel Anda dan mengambil beberapa item yang cocok dengan kriteria tertentu. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest))Metode ini menemukan item berdasarkan nilai kunci primer menggunakan `@DynamoDbPartitionKey` dan `@DynamoDbSortKey` anotasi opsional yang ditentukan pada kelas data Anda.

`query()`Metode ini memerlukan nilai kunci partisi dan secara opsional menerima kondisi kunci pengurutan untuk lebih menyempurnakan hasil. Seperti `scan` API, kueri mengembalikan a `PageIterable` untuk panggilan sinkron dan a `PagePublisher` untuk panggilan asinkron.

### `Query`contoh metode
<a name="ddb-en-client-use-multirecord-query-example"></a>

Contoh kode `query()` metode yang mengikuti menggunakan `MovieActor` kelas. Kelas data mendefinisikan kunci primer komposit yang terdiri dari **`movie`**atribut sebagai kunci partisi dan **`actor`**atribut sebagai kunci pengurutan. 

#### `MovieActor` kelas
<a name="ddb-en-client-use-movieactor-class"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.Objects;

@DynamoDbBean
public class MovieActor implements Comparable<MovieActor> {

    private String movieName;
    private String actorName;
    private String actingAward;
    private Integer actingYear;
    private String actingSchoolName;

    @DynamoDbPartitionKey
    @DynamoDbAttribute("movie")
    public String getMovieName() {
        return movieName;
    }

    public void setMovieName(String movieName) {
        this.movieName = movieName;
    }

    @DynamoDbSortKey
    @DynamoDbAttribute("actor")
    public String getActorName() {
        return actorName;
    }

    public void setActorName(String actorName) {
        this.actorName = actorName;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "acting_award_year")
    @DynamoDbAttribute("actingaward")
    public String getActingAward() {
        return actingAward;
    }

    public void setActingAward(String actingAward) {
        this.actingAward = actingAward;
    }

    @DynamoDbSecondarySortKey(indexNames = {"acting_award_year", "movie_year"})
    @DynamoDbAttribute("actingyear")
    public Integer getActingYear() {
        return actingYear;
    }

    public void setActingYear(Integer actingYear) {
        this.actingYear = actingYear;
    }

    @DynamoDbAttribute("actingschoolname")
    public String getActingSchoolName() {
        return actingSchoolName;
    }

    public void setActingSchoolName(String actingSchoolName) {
        this.actingSchoolName = actingSchoolName;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("MovieActor{");
        sb.append("movieName='").append(movieName).append('\'');
        sb.append(", actorName='").append(actorName).append('\'');
        sb.append(", actingAward='").append(actingAward).append('\'');
        sb.append(", actingYear=").append(actingYear);
        sb.append(", actingSchoolName='").append(actingSchoolName).append('\'');
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MovieActor that = (MovieActor) o;
        return Objects.equals(movieName, that.movieName) && Objects.equals(actorName, that.actorName) && Objects.equals(actingAward, that.actingAward) && Objects.equals(actingYear, that.actingYear) && Objects.equals(actingSchoolName, that.actingSchoolName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(movieName, actorName, actingAward, actingYear, actingSchoolName);
    }

    @Override
    public int compareTo(MovieActor o) {
        if (this.movieName.compareTo(o.movieName) != 0){
            return this.movieName.compareTo(o.movieName);
        } else {
            return this.actorName.compareTo(o.actorName);
        }
    }
}
```

Contoh kode yang mengikuti kueri terhadap item berikut.

#### Item dalam `MovieActor` tabel
<a name="ddb-en-client-use-movieactor-items"></a>

```
MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
MovieActor{movieName='movie02', actorName='actor0', actingAward='actingaward0', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor1', actingAward='actingaward1', actingYear=2002, actingSchoolName='actingschool1'}
MovieActor{movieName='movie02', actorName='actor2', actingAward='actingaward2', actingYear=2002, actingSchoolName='actingschool2'}
MovieActor{movieName='movie02', actorName='actor3', actingAward='actingaward3', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor4', actingAward='actingaward4', actingYear=2002, actingSchoolName='actingschool4'}
MovieActor{movieName='movie03', actorName='actor0', actingAward='actingaward0', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor1', actingAward='actingaward1', actingYear=2003, actingSchoolName='actingschool1'}
MovieActor{movieName='movie03', actorName='actor2', actingAward='actingaward2', actingYear=2003, actingSchoolName='actingschool2'}
MovieActor{movieName='movie03', actorName='actor3', actingAward='actingaward3', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor4', actingAward='actingaward4', actingYear=2003, actingSchoolName='actingschool4'}
```

Kode berikut mendefinisikan dua `QueryConditional` contoh: `keyEqual` (setelah baris komentar 1) dan `sortGreaterThanOrEqualTo` (setelah baris komentar 1a).

#### Item kueri dengan kunci partisi
<a name="keyEqual-query-conditional-example"></a>

`keyEqual`Instance mencocokkan item dengan nilai kunci partisi dari **`movie01`**. 

Contoh ini juga mendefinisikan ekspresi filter setelah baris komentar 2 yang menyaring item apa pun yang tidak memiliki **`actingschoolname`**nilai.

`QueryEnhancedRequest`Menggabungkan kondisi kunci dan ekspresi filter untuk kueri.

```
    public static void query(DynamoDbTable movieActorTable) {

        // 1. Define a QueryConditional instance to return items matching a partition value.
        QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b.partitionValue("movie01"));
        // 1a. Define a QueryConditional that adds a sort key criteria to the partition value criteria.
        QueryConditional sortGreaterThanOrEqualTo = QueryConditional.sortGreaterThanOrEqualTo(b -> b.partitionValue("movie01").sortValue("actor2"));
        // 2. Define a filter expression that filters out items whose attribute value is null.
        final Expression filterOutNoActingschoolname = Expression.builder().expression("attribute_exists(actingschoolname)").build();

        // 3. Build the query request.
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(keyEqual)
                .filterExpression(filterOutNoActingschoolname)
                .build();
        // 4. Perform the query using the "keyEqual" conditional and filter expression.
        PageIterable<MovieActor> pagedResults = movieActorTable.query(tableQuery);
        logger.info("page count: {}", pagedResults.stream().count()); // Log  number of pages.

        pagedResults.items().stream()
                .sorted()
                .forEach(
                        item -> logger.info(item.toString()) // Log the sorted list of items.
                );
```

**Example — Output menggunakan `keyEqual` query kondisional**  
Berikut ini adalah output dari menjalankan metode. Output menampilkan item dengan `movieName` nilai **movie01** dan tidak menampilkan item yang `actingSchoolName` sama dengan. **`null`**  

```
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

#### Item kueri dengan kunci partisi dan kunci sortir
<a name="sort-type-query-conditional-example"></a>

`sortGreaterThanOrEqualTo``QueryConditional`**Menyempurnakan kecocokan kunci partisi (**movie01**) dengan menambahkan kondisi kunci pengurutan untuk nilai yang lebih besar dari atau sama dengan aktor2.**

[`QueryConditional`metode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html) yang dimulai dengan `sort` memerlukan nilai kunci partisi untuk mencocokkan dan selanjutnya menyempurnakan kueri dengan perbandingan berdasarkan nilai kunci sortir. `Sort`dalam nama metode tidak berarti hasilnya diurutkan, tetapi nilai kunci sortir akan digunakan untuk perbandingan.

Dalam cuplikan berikut, kami mengubah permintaan kueri yang ditampilkan sebelumnya setelah baris komentar 3. Cuplikan ini menggantikan kueri “KeyEqual” bersyarat dengan syarat kueri "sortGreaterThanOrEqualTo" yang ditentukan setelah baris komentar 1a. Kode berikut juga menghapus ekspresi filter.

```
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(sortGreaterThanOrEqualTo).build();
```

**Example — Output menggunakan `sortGreaterThanOrEqualTo` query kondisional**  
Output berikut menampilkan hasil dari query. **Kueri mengembalikan item yang memiliki `movieName` nilai sama dengan **movie01** dan hanya item yang memiliki `actorName` nilai yang lebih besar dari atau sama dengan actor2.** Karena kita menghapus filter, query mengembalikan item yang tidak memiliki nilai untuk `actingSchoolName` atribut.  

```
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

# Lakukan operasi batch
<a name="ddb-en-client-use-multiop-batch"></a>

[DynamoDB Enhanced Client API menawarkan dua metode batch [`batchGetItem`, () dan (](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer)))`batchWriteItem`.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchWriteItem(java.util.function.Consumer))

## Contoh `batchGetItem()`
<a name="ddb-en-client-use-multiop-batch-get"></a>

Dengan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#batchGetItem(java.util.function.Consumer))metode ini, Anda dapat mengambil hingga 100 item individual di beberapa tabel dalam satu permintaan keseluruhan. Contoh berikut menggunakan kelas [`Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust)dan [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)data yang ditunjukkan sebelumnya.

Dalam contoh setelah baris 1 dan 2, Anda membangun `[ReadBatch](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ReadBatch.html)` objek yang kemudian Anda tambahkan sebagai parameter ke `batchGetItem()` metode setelah baris komentar 3. 

Kode setelah baris komentar 1 membangun batch untuk dibaca dari `Customer` tabel. Kode setelah baris komentar 1a menunjukkan penggunaan `[GetItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/GetItemEnhancedRequest.Builder.html)` pembangun yang mengambil nilai kunci primer dan nilai kunci pengurutan untuk menentukan item yang akan dibaca. Jika kelas data memiliki kunci komposit, Anda harus memberikan nilai kunci partisi dan nilai kunci sortir. 

Berbeda dengan menentukan nilai kunci untuk meminta item, Anda dapat menggunakan kelas data untuk meminta item seperti yang ditunjukkan setelah baris komentar 1b. SDK mengekstrak nilai kunci di balik layar sebelum mengirimkan permintaan.

[Saat Anda menentukan item menggunakan pendekatan berbasis kunci seperti yang ditunjukkan dalam dua pernyataan setelah 2a, Anda juga dapat menentukan bahwa DynamoDB harus melakukan pembacaan yang sangat konsisten.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html) Ketika `consistentRead()` metode ini digunakan, itu harus digunakan pada semua item yang diminta untuk tabel yang sama.

Untuk mengambil item yang DynamoDB temukan, gunakan metode `[resultsForTable() ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#resultsForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` yang ditampilkan setelah baris komentar 4. Panggil metode untuk setiap tabel yang dibaca dalam permintaan. `resultsForTable()`mengembalikan daftar item yang ditemukan yang dapat Anda proses menggunakan `java.util.List` metode apapun. Contoh ini mencatat setiap item.

Untuk menemukan item yang DynamoDB tidak memproses, gunakan pendekatan setelah baris komentar 5. `BatchGetResultPage`Kelas memiliki `[unprocessedKeysForTable()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#unprocessedKeysForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` metode yang memberi Anda akses ke setiap kunci yang belum diproses. [Referensi BatchGetItem API](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) memiliki informasi lebih lanjut tentang situasi yang menghasilkan item yang tidak diproses.

```
    public static void batchGetItemExample(DynamoDbEnhancedClient enhancedClient,
                                           DynamoDbTable<Customer> customerTable,
                                           DynamoDbTable<MovieActor> movieActorTable) {

        Customer customer2 = new Customer();
        customer2.setId("2");
        customer2.setEmail("cust2@example.org");

        // 1. Build a batch to read from the Customer table.
        ReadBatch customerBatch = ReadBatch.builder(Customer.class)
                .mappedTableResource(customerTable)
                // 1a. Specify the primary key value and sort key value for the item.
                .addGetItem(b -> b.key(k -> k.partitionValue("1").sortValue("cust1@orgname.org")))
                // 1b. Alternatively, supply a data class instances to provide the primary key values.
                .addGetItem(customer2)
                .build();

        // 2. Build a batch to read from the MovieActor table.
        ReadBatch moveActorBatch = ReadBatch.builder(MovieActor.class)
                .mappedTableResource(movieActorTable)
                // 2a. Call consistentRead(Boolean.TRUE) for each item for the same table.
                .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor1")).consistentRead(Boolean.TRUE))
                .addGetItem(b -> b.key(k -> k.partitionValue("movie01").sortValue("actor4")).consistentRead(Boolean.TRUE))
                .build();

        // 3. Add ReadBatch objects to the request.
        BatchGetResultPageIterable resultPages = enhancedClient.batchGetItem(b -> b.readBatches(customerBatch, moveActorBatch));

        // 4. Retrieve the successfully requested items from each table.
        resultPages.resultsForTable(customerTable).forEach(item -> logger.info(item.toString()));
        resultPages.resultsForTable(movieActorTable).forEach(item -> logger.info(item.toString()));

        // 5. Retrieve the keys of the items requested but not processed by the service.
        resultPages.forEach((BatchGetResultPage pageResult) -> {
            pageResult.unprocessedKeysForTable(customerTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString()));
            pageResult.unprocessedKeysForTable(movieActorTable).forEach(key -> logger.info("Unprocessed item key: " + key.toString()));
        });
    }
```

Asumsikan bahwa item berikut ada di dua tabel sebelum menjalankan kode contoh.

### Item dalam tabel
<a name="ddb-en-client-use-multiop-batch-get-tableitems"></a>

```
Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z]
Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z]
Customer [id=3, name=CustName3, email=cust3@example.org, regDate=2023-03-31T15:46:29.688Z]
Customer [id=4, name=CustName4, email=cust4@example.org, regDate=2023-03-31T15:46:30.688Z]
Customer [id=5, name=CustName5, email=cust5@example.org, regDate=2023-03-31T15:46:31.689Z]
MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

Output berikut menunjukkan item yang dikembalikan dan dicatat setelah baris komentar 4.

```
Customer [id=1, name=CustName1, email=cust1@example.org, regDate=2023-03-31T15:46:27.688Z]
Customer [id=2, name=CustName2, email=cust2@example.org, regDate=2023-03-31T15:46:28.688Z]
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
```

## Contoh `batchWriteItem()`
<a name="ddb-en-client-use-multiop-batch-write"></a>

`batchWriteItem()`Metode ini menempatkan atau menghapus beberapa item dalam satu atau lebih tabel. Anda dapat menentukan hingga 25 operasi put atau hapus individu dalam permintaan. Contoh berikut menggunakan kelas [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)dan [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)model yang ditunjukkan sebelumnya.

`WriteBatch`objek dibangun setelah baris komentar 1 dan 2. Untuk `ProductCatalog` tabel, kode menempatkan satu item dan menghapus satu item. Untuk `MovieActor` tabel setelah baris komentar 2, kode menempatkan dua item dan menghapus satu.

`batchWriteItem`Metode ini disebut setelah baris komentar 3. `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteItemEnhancedRequest.Builder.html)`Parameter menyediakan permintaan batch untuk setiap tabel.

`[BatchWriteResult](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteResult.html)`Objek yang dikembalikan menyediakan metode terpisah untuk setiap operasi untuk melihat permintaan yang belum diproses. Kode setelah baris komentar 4a menyediakan kunci untuk permintaan penghapusan yang belum diproses dan kode setelah baris komentar 4b menyediakan item put yang belum diproses.

```
    public static void batchWriteItemExample(DynamoDbEnhancedClient enhancedClient,
                                             DynamoDbTable<ProductCatalog> catalogTable,
                                             DynamoDbTable<MovieActor> movieActorTable) {

        // 1. Build a batch to write to the ProductCatalog table.
        WriteBatch products = WriteBatch.builder(ProductCatalog.class)
                .mappedTableResource(catalogTable)
                .addPutItem(b -> b.item(getProductCatItem1()))
                .addDeleteItem(b -> b.key(k -> k
                        .partitionValue(getProductCatItem2().id())
                        .sortValue(getProductCatItem2().title())))
                .build();

        // 2. Build a batch to write to the MovieActor table.
        WriteBatch movies = WriteBatch.builder(MovieActor.class)
                .mappedTableResource(movieActorTable)
                .addPutItem(getMovieActorYeoh())
                .addPutItem(getMovieActorBlanchettPartial())
                .addDeleteItem(b -> b.key(k -> k
                        .partitionValue(getMovieActorStreep().getMovieName())
                        .sortValue(getMovieActorStreep().getActorName())))
                .build();

        // 3. Add WriteBatch objects to the request.
        BatchWriteResult batchWriteResult = enhancedClient.batchWriteItem(b -> b.writeBatches(products, movies));
        // 4. Retrieve keys for items the service did not process.
        // 4a. 'unprocessedDeleteItemsForTable()' returns keys for delete requests that did not process.
        if (batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).size() > 0) {
            batchWriteResult.unprocessedDeleteItemsForTable(movieActorTable).forEach(key ->
                    logger.info(key.toString()));
        }
        // 4b. 'unprocessedPutItemsForTable()' returns keys for put requests that did not process.
        if (batchWriteResult.unprocessedPutItemsForTable(catalogTable).size() > 0) {
            batchWriteResult.unprocessedPutItemsForTable(catalogTable).forEach(key ->
                    logger.info(key.toString()));
        }
    }
```

Metode pembantu berikut menyediakan objek model untuk operasi put dan delete.

### Metode pembantu
<a name="ddb-en-client-use-multiop-batch-write-helpers"></a>

```
 1.     public static ProductCatalog getProductCatItem1() {
 2.         return ProductCatalog.builder()
 3.                 .id(2)
 4.                 .isbn("1-565-85698")
 5.                 .authors(new HashSet<>(Arrays.asList("a", "b")))
 6.                 .price(BigDecimal.valueOf(30.22))
 7.                 .title("Title 55")
 8.                 .build();
 9.     }
10. 
11.     public static ProductCatalog getProductCatItem2() {
12.         return ProductCatalog.builder()
13.                 .id(4)
14.                 .price(BigDecimal.valueOf(40.00))
15.                 .title("Title 1")
16.                 .build();
17.     }  
18. 
19.     public static MovieActor getMovieActorBlanchettPartial() {
20.         MovieActor movieActor = new MovieActor();
21.         movieActor.setActorName("Cate Blanchett");
22.         movieActor.setMovieName("Blue Jasmine");
23.         movieActor.setActingYear(2023);
24.         movieActor.setActingAward("Best Actress");
25.         return movieActor;
26.     }
27. 
28.     public static MovieActor getMovieActorStreep() {
29.         MovieActor movieActor = new MovieActor();
30.         movieActor.setActorName("Meryl Streep");
31.         movieActor.setMovieName("Sophie's Choice");
32.         movieActor.setActingYear(1982);
33.         movieActor.setActingAward("Best Actress");
34.         movieActor.setActingSchoolName("Yale School of Drama");
35.         return movieActor;
36.     }
37. 
38.     public static MovieActor getMovieActorYeoh(){
39.         MovieActor movieActor = new MovieActor();
40.         movieActor.setActorName("Michelle Yeoh");
41.         movieActor.setMovieName("Everything Everywhere All at Once");
42.         movieActor.setActingYear(2023);
43.         movieActor.setActingAward("Best Actress");
44.         movieActor.setActingSchoolName("Royal Academy of Dance");
45.         return movieActor;
46.     }
```

Asumsikan bahwa tabel berisi item berikut sebelum Anda menjalankan kode contoh.

```
MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
```

Setelah kode contoh selesai, tabel berisi item berikut.

```
MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='null'}
MovieActor{movieName='Everything Everywhere All at Once', actorName='Michelle Yeoh', actingAward='Best Actress', actingYear=2023, actingSchoolName='Royal Academy of Dance'}
ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}
```

Perhatikan dalam `MovieActor` tabel bahwa item `Blue Jasmine` film telah diganti dengan item yang digunakan dalam permintaan put yang diperoleh melalui metode `getMovieActorBlanchettPartial()` pembantu. Jika nilai atribut kacang data tidak disediakan, nilai dalam database dihapus. Inilah sebabnya mengapa hasilnya `actingSchoolName` nol untuk item `Blue Jasmine` film.

**catatan**  
Meskipun dokumentasi API menunjukkan bahwa ekspresi kondisi dapat digunakan dan bahwa kapasitas yang dikonsumsi serta metrik pengumpulan dapat dikembalikan dengan permintaan [put](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PutItemEnhancedRequest.html) dan [delete](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/DeleteItemEnhancedRequest.html) individual, ini tidak terjadi dalam skenario penulisan batch. Untuk meningkatkan kinerja operasi batch, opsi individual ini diabaikan.

# Lakukan operasi transaksi
<a name="ddb-en-client-use-multiop-trans"></a>

DynamoDB Enhanced Client API menyediakan dan metode`transactGetItems()`. `transactWriteItems()` Metode transaksi SDK for Java memberikan atomisitas, konsistensi, isolasi, dan daya tahan (ACID) dalam tabel DynamoDB, membantu Anda menjaga kebenaran data dalam aplikasi Anda.

## Contoh `transactGetItems()`
<a name="ddb-en-client-use-multiop-trans-getitems"></a>

`[transactGetItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactGetItems(java.util.function.Consumer))`Metode ini menerima hingga 100 permintaan individu untuk item. Semua item dibaca dalam satu transaksi atom. Panduan *Pengembang Amazon DynamoDB* memiliki informasi tentang [kondisi yang menyebabkan `transactGetItems()` metode gagal](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txgetitems), dan juga tentang tingkat isolasi yang digunakan saat Anda menelepon. `[transactGetItem()](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-isolation)`

Setelah baris komentar 1 dalam contoh berikut, kode memanggil `transactGetItems()` metode dengan `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html)` parameter. Builder `[addGetItem()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html#addGetItem(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource,T))` dipanggil tiga kali dengan objek data yang berisi nilai kunci yang akan digunakan SDK untuk menghasilkan permintaan akhir.

Permintaan mengembalikan daftar `[Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html)` objek setelah baris komentar 2. Daftar dokumen yang dikembalikan berisi contoh [dokumen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html) non-null dari data item dalam urutan yang sama seperti yang diminta. `[Document.getItem(MappedTableResource<T> mappedTableResource)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html#getItem(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))`Metode mengkonversi objek untyped menjadi `Document` objek Java diketik jika data item dikembalikan, jika tidak metode mengembalikan null.

```
    public static void transactGetItemsExample(DynamoDbEnhancedClient enhancedClient,
                                               DynamoDbTable<ProductCatalog> catalogTable,
                                               DynamoDbTable<MovieActor> movieActorTable) {

        // 1. Request three items from two tables using a builder.
        final List<Document> documents = enhancedClient.transactGetItems(b -> b
                .addGetItem(catalogTable, Key.builder().partitionValue(2).sortValue("Title 55").build())
                .addGetItem(movieActorTable, Key.builder().partitionValue("Sophie's Choice").sortValue("Meryl Streep").build())
                .addGetItem(movieActorTable, Key.builder().partitionValue("Blue Jasmine").sortValue("Cate Blanchett").build())
                .build());

        // 2. A list of Document objects is returned in the same order as requested.
        ProductCatalog title55 = documents.get(0).getItem(catalogTable);
        if (title55 != null) {
            logger.info(title55.toString());
        }

        MovieActor sophiesChoice = documents.get(1).getItem(movieActorTable);
        if (sophiesChoice != null) {
            logger.info(sophiesChoice.toString());
        }

        // 3. The getItem() method returns null if the Document object contains no item from DynamoDB.
        MovieActor blueJasmine = documents.get(2).getItem(movieActorTable);
        if (blueJasmine != null) {
            logger.info(blueJasmine.toString());
        }
    }
```

Tabel DynamoDB berisi item berikut sebelum contoh kode berjalan.

```
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

Output berikut dicatat. Jika item diminta tetapi tidak ditemukan, itu tidak dikembalikan seperti halnya permintaan untuk film bernama`Blue Jasmine`.

```
ProductCatalog{id=2, title='Title 55', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

## `transactWriteItems()` contoh
<a name="ddb-en-client-use-multiop-trans-writeitems"></a>

`[transactWriteItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))`Menerima hingga 100 tindakan put, update, atau delete dalam satu transaksi atom di beberapa tabel. Panduan *Pengembang Amazon DynamoDB* berisi rincian tentang pembatasan dan kondisi kegagalan operasi layanan [DynamoDB yang mendasarinya](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems).

### Contoh basic
<a name="ddb-en-client-use-multiop-trans-writeitems-basic"></a>

Dalam contoh berikut, empat operasi diminta untuk dua tabel. Kelas model yang sesuai [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)dan ditunjukkan [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)sebelumnya.

Masing-masing dari tiga kemungkinan operasi—put, update, dan delete—menggunakan parameter permintaan khusus untuk menentukan detailnya. 

Kode setelah baris komentar 1 menunjukkan variasi sederhana dari `addPutItem()` metode ini. Metode ini menerima `[MappedTableResource](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/MappedTableResource.html)` objek dan contoh objek data untuk dimasukkan. Pernyataan setelah komentar baris 2 menunjukkan variasi yang menerima `[TransactPutItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactPutItemEnhancedRequest.html)` instance. Variasi ini memungkinkan Anda menambahkan lebih banyak opsi dalam permintaan, seperti ekspresi kondisi. [Contoh](#ddb-en-client-use-multiop-trans-writeitems-opcondition) selanjutnya menunjukkan ekspresi kondisi untuk operasi individu.

Operasi pembaruan diminta setelah baris komentar 3. `[TransactUpdateItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactUpdateItemEnhancedRequest.Builder.html)`memiliki `ignoreNulls()` metode yang memungkinkan Anda mengonfigurasi apa yang dilakukan SDK dengan `null` nilai pada objek model. Jika `ignoreNulls()` metode mengembalikan true, SDK tidak menghapus nilai atribut tabel untuk atribut objek data yang`null`. Jika `ignoreNulls()` metode mengembalikan false, SDK meminta layanan DynamoDB untuk menghapus atribut dari item dalam tabel. Nilai default untuk `ignoreNulls` adalah false.

Pernyataan setelah baris komentar 4 menunjukkan variasi permintaan hapus yang mengambil objek data. Klien yang disempurnakan mengekstrak nilai-nilai kunci sebelum mengirimkan permintaan akhir.

```
    public static void transactWriteItems(DynamoDbEnhancedClient enhancedClient,
                                          DynamoDbTable<ProductCatalog> catalogTable,
                                          DynamoDbTable<MovieActor> movieActorTable) {

        enhancedClient.transactWriteItems(b -> b
                // 1. Simplest variation of put item request.
                .addPutItem(catalogTable, getProductCatId2())
                // 2. Put item request variation that accommodates condition expressions.
                .addPutItem(movieActorTable, TransactPutItemEnhancedRequest.builder(MovieActor.class)
                        .item(getMovieActorStreep())
                        .conditionExpression(Expression.builder().expression("attribute_not_exists (movie)").build())
                        .build())
                // 3. Update request that does not remove attribute values on the table if the data object's value is null.
                .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                        .item(getProductCatId4ForUpdate())
                        .ignoreNulls(Boolean.TRUE)
                        .build())
                // 4. Variation of delete request that accepts a data object. The key values are extracted for the request.
                .addDeleteItem(movieActorTable, getMovieActorBlanchett())
        );
    }
```

Metode pembantu berikut menyediakan objek data untuk `add*Item` parameter.

#### Metode pembantu
<a name="ddb-en-client-use-multiop-trans-writeitems-basic-helpers"></a>

```
    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }

    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Tar");
        movieActor.setActingYear(2022);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }

    public static MovieActor getMovieActorStreep() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Meryl Streep");
        movieActor.setMovieName("Sophie's Choice");
        movieActor.setActingYear(1982);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("Yale School of Drama");
        return movieActor;
    }
```

Tabel DynamoDB berisi item berikut sebelum contoh kode berjalan.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Item berikut ada di tabel setelah kode selesai berjalan.

```
3 | ProductCatalog{id=2, title='Title 55', isbn='1-565-85698', authors=[a, b], price=30.22}
4 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=40.0}
5 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
```

Item pada baris 2 telah dihapus dan baris 3 dan 5 menunjukkan item yang diletakkan. Baris 4 menunjukkan pembaruan baris 1. `price`Nilai adalah satu-satunya nilai yang berubah pada item. Jika `ignoreNulls()` telah mengembalikan false, baris 4 akan terlihat seperti baris berikut.

```
ProductCatalog{id=4, title='Title 1', isbn='null', authors=null, price=40.0}
```

### Contoh pemeriksaan kondisi
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond"></a>

Contoh berikut menunjukkan penggunaan pemeriksaan kondisi. Pemeriksaan kondisi digunakan untuk memeriksa apakah ada item atau untuk memeriksa kondisi atribut tertentu dari suatu item dalam database. Item yang dicek dalam pemeriksaan kondisi tidak dapat digunakan dalam operasi lain dalam transaksi.

**catatan**  
Anda tidak dapat menargetkan item yang sama dengan beberapa operasi dalam transaksi yang sama. Misalnya, Anda tidak dapat melakukan pemeriksaan kondisi dan juga mencoba memperbarui item yang sama dalam transaksi yang sama.

Contoh menunjukkan salah satu dari setiap jenis operasi dalam permintaan item tulis transaksional. Setelah baris komentar 2, `addConditionCheck()` metode memasok kondisi yang gagal transaksi jika `conditionExpression` parameter mengevaluasi`false`. Ekspresi kondisi yang dikembalikan dari metode yang ditampilkan dalam blok Metode Pembantu memeriksa apakah tahun penghargaan untuk film `Sophie's Choice` tidak sama dengan. `1982` Jika ya, ekspresi mengevaluasi `false` dan transaksi gagal.

Panduan ini membahas [ekspresi](ddb-en-client-expressions.md) secara mendalam dalam topik lain.

```
    public static void conditionCheckFailExample(DynamoDbEnhancedClient enhancedClient,
                                                 DynamoDbTable<ProductCatalog> catalogTable,
                                                 DynamoDbTable<MovieActor> movieActorTable) {

        try {
            enhancedClient.transactWriteItems(b -> b
                    // 1. Perform one of each type of operation with the next three methods.
                    .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId2()).build())
                    .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId4ForUpdate())
                            .ignoreNulls(Boolean.TRUE).build())
                    .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder()
                            .key(b1 -> b1
                                    .partitionValue(getMovieActorBlanchett().getMovieName())
                                    .sortValue(getMovieActorBlanchett().getActorName())).build())
                    // 2. Add a condition check on a table item that is not involved in another operation in this request.
                    .addConditionCheck(movieActorTable, ConditionCheck.builder()
                            .conditionExpression(buildConditionCheckExpression())
                            .key(k -> k
                                    .partitionValue("Sophie's Choice")
                                    .sortValue("Meryl Streep"))
                            // 3. Specify the request to return existing values from the item if the condition evaluates to true.
                            .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
                            .build())
                    .build());
        // 4. Catch the exception if the transaction fails and log the information.
        } catch (TransactionCanceledException ex) {
            ex.cancellationReasons().stream().forEach(cancellationReason -> {
                logger.info(cancellationReason.toString());
            });
        }
    }
```

Metode pembantu berikut digunakan dalam contoh kode sebelumnya.

#### Metode pembantu
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond-helpers"></a>

```
    private static Expression buildConditionCheckExpression() {
        Map<String, AttributeValue> expressionValue = Map.of(
                ":year", numberValue(1982));

        return Expression.builder()
                .expression("actingyear <> :year")
                .expressionValues(expressionValue)
                .build();
    }

    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }

    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Blue Jasmine");
        movieActor.setActingYear(2013);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }
```

Tabel DynamoDB berisi item berikut sebelum contoh kode berjalan.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
3 | MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Item berikut ada di tabel setelah kode selesai berjalan.

```
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
MovieActor{movieName='Sophie's Choice', actorName='Meryl Streep', actingAward='Best Actress', actingYear=1982, actingSchoolName='Yale School of Drama'}
MovieActor{movieName='Tar', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2022, actingSchoolName='National Institute of Dramatic Art'}
```

Item tetap tidak berubah dalam tabel karena transaksi gagal. `actingYear`Nilai untuk film `Sophie's Choice` adalah`1982`, seperti yang ditunjukkan pada baris 2 item dalam tabel sebelum `transactWriteItem()` metode dipanggil.

Untuk menangkap informasi pembatalan untuk transaksi, lampirkan panggilan `transactWriteItems()` metode dalam `try` blok dan`catch`. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TransactionCanceledException.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/TransactionCanceledException.html) Setelah baris komentar 4 dari contoh, kode mencatat setiap `[CancellationReason](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CancellationReason.html)` objek. Karena kode berikut baris komentar 3 dari contoh menentukan bahwa nilai harus dikembalikan untuk item yang menyebabkan transaksi gagal, log menampilkan nilai database mentah untuk item `Sophie's Choice` film.

```
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Item={actor=AttributeValue(S=Meryl Streep), movie=AttributeValue(S=Sophie's Choice), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=1982), actingschoolname=AttributeValue(S=Yale School of Drama)}, ¬
    Code=ConditionalCheckFailed, Message=The conditional request failed.)
```

### Contoh kondisi operasi tunggal
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition"></a>

Contoh berikut menunjukkan penggunaan kondisi pada operasi tunggal dalam permintaan transaksi. Operasi hapus setelah baris komentar 1 berisi kondisi yang memeriksa nilai item target operasi terhadap database. Dalam contoh ini, ekspresi kondisi yang dibuat dengan metode pembantu setelah baris komentar 2 menentukan bahwa item harus dihapus dari database jika tahun akting film tidak sama dengan 2013.

[Ekspresi](ddb-en-client-expressions.md) dibahas nanti dalam panduan ini.

```
    public static void singleOperationConditionFailExample(DynamoDbEnhancedClient enhancedClient,
                                                           DynamoDbTable<ProductCatalog> catalogTable,
                                                           DynamoDbTable<MovieActor> movieActorTable) {
        try {
            enhancedClient.transactWriteItems(b -> b
                    .addPutItem(catalogTable, TransactPutItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId2())
                            .build())
                    .addUpdateItem(catalogTable, TransactUpdateItemEnhancedRequest.builder(ProductCatalog.class)
                            .item(getProductCatId4ForUpdate())
                            .ignoreNulls(Boolean.TRUE).build())
                    // 1. Delete operation that contains a condition expression
                    .addDeleteItem(movieActorTable, TransactDeleteItemEnhancedRequest.builder()
                            .key((Key.Builder k) -> {
                                MovieActor blanchett = getMovieActorBlanchett();
                                k.partitionValue(blanchett.getMovieName())
                                        .sortValue(blanchett.getActorName());
                            })
                            .conditionExpression(buildDeleteItemExpression())
                            .returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
                            .build())
                    .build());
        } catch (TransactionCanceledException ex) {
            ex.cancellationReasons().forEach(cancellationReason -> logger.info(cancellationReason.toString()));
        }
    }

    // 2. Provide condition expression to check if 'actingyear' is not equal to 2013.
    private static Expression buildDeleteItemExpression() {
        Map<String, AttributeValue> expressionValue = Map.of(
                ":year", numberValue(2013));

        return Expression.builder()
                .expression("actingyear <> :year")
                .expressionValues(expressionValue)
                .build();
    }
```

Metode pembantu berikut digunakan dalam contoh kode sebelumnya.

#### Metode pembantu
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition-helpers"></a>

```
    public static ProductCatalog getProductCatId2() {
        return ProductCatalog.builder()
                .id(2)
                .isbn("1-565-85698")
                .authors(new HashSet<>(Arrays.asList("a", "b")))
                .price(BigDecimal.valueOf(30.22))
                .title("Title 55")
                .build();
    }

    public static ProductCatalog getProductCatId4ForUpdate() {
        return ProductCatalog.builder()
                .id(4)
                .price(BigDecimal.valueOf(40.00))
                .title("Title 1")
                .build();
    }
    public static MovieActor getMovieActorBlanchett() {
        MovieActor movieActor = new MovieActor();
        movieActor.setActorName("Cate Blanchett");
        movieActor.setMovieName("Blue Jasmine");
        movieActor.setActingYear(2013);
        movieActor.setActingAward("Best Actress");
        movieActor.setActingSchoolName("National Institute of Dramatic Art");
        return movieActor;
    }
```

Tabel DynamoDB berisi item berikut sebelum contoh kode berjalan.

```
1 | ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2 | MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
```

Item berikut ada di tabel setelah kode selesai berjalan.

```
ProductCatalog{id=4, title='Title 1', isbn='orig_isbn', authors=[b, g], price=10}
2023-03-15 11:29:07 [main] INFO  org.example.tests.TransactDemoTest:168 - MovieActor{movieName='Blue Jasmine', actorName='Cate Blanchett', actingAward='Best Actress', actingYear=2013, actingSchoolName='National Institute of Dramatic Art'}
```

Item tetap tidak berubah dalam tabel karena transaksi gagal. `actingYear`Nilai untuk film `Blue Jasmine` adalah `2013` seperti yang ditunjukkan pada baris 2 dalam daftar item sebelum contoh kode berjalan.

Baris berikut dicatat ke konsol.

```
CancellationReason(Code=None)
CancellationReason(Code=None)
CancellationReason(Item={actor=AttributeValue(S=Cate Blanchett), movie=AttributeValue(S=Blue Jasmine), actingaward=AttributeValue(S=Best Actress), actingyear=AttributeValue(N=2013), actingschoolname=AttributeValue(S=National Institute of Dramatic Art)}, 
    Code=ConditionalCheckFailed, Message=The conditional request failed)
```

# Gunakan indeks sekunder
<a name="ddb-en-client-use-secindex"></a>

Indeks sekunder meningkatkan akses data dengan mendefinisikan kunci alternatif yang Anda gunakan dalam operasi kueri dan pemindaian. Indeks sekunder global (GSI) memiliki kunci partisi dan kunci pengurutan yang dapat berbeda dari yang ada di tabel dasar. Sebaliknya, indeks sekunder lokal (LSI) menggunakan kunci partisi dari indeks primer.

## Anotasi kelas data dengan anotasi indeks sekunder
<a name="ddb-en-client-use-secindex-annomodel"></a>

Atribut yang berpartisipasi dalam indeks sekunder memerlukan `@DynamoDbSecondarySortKey` anotasi `@DynamoDbSecondaryPartitionKey` atau anotasi.

Kelas berikut menunjukkan anotasi untuk dua indeks. GSI bernama *SubjectLastPostedDateIndex*menggunakan `Subject` atribut untuk kunci partisi dan `LastPostedDateTime` untuk kunci sortir. LSI bernama *ForumLastPostedDateIndex*menggunakan `ForumName` sebagai kunci partisi dan `LastPostedDateTime` sebagai kunci sortir.

Perhatikan bahwa `Subject` atribut tersebut memiliki peran ganda. Ini adalah kunci sortir kunci primer dan kunci partisi dari GSI bernama *SubjectLastPostedDateIndex*.

### `MessageThread` kelas
<a name="ddb-en-client-use-secindex-class"></a>

`MessageThread`Kelas ini cocok untuk digunakan sebagai kelas data untuk [tabel Thread contoh](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html) di *Amazon DynamoDB* Developer Guide.

#### Impor
<a name="ddb-en-client-use-secindex-classimports"></a>

```
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.List;
```

```
@DynamoDbBean
public class MessageThread {
    private String ForumName;
    private String Subject;
    private String Message;
    private String LastPostedBy;
    private String LastPostedDateTime;
    private Integer Views;
    private Integer Replies;
    private Integer Answered;
    private List<String> Tags;

    @DynamoDbPartitionKey
    public String getForumName() {
        return ForumName;
    }

    public void setForumName(String forumName) {
        ForumName = forumName;
    }

    // Sort key for primary index and partition key for GSI "SubjectLastPostedDateIndex".
    @DynamoDbSortKey
    @DynamoDbSecondaryPartitionKey(indexNames = "SubjectLastPostedDateIndex")
    public String getSubject() {
        return Subject;
    }

    public void setSubject(String subject) {
        Subject = subject;
    }

    // Sort key for GSI "SubjectLastPostedDateIndex" and sort key for LSI "ForumLastPostedDateIndex".
    @DynamoDbSecondarySortKey(indexNames = {"SubjectLastPostedDateIndex", "ForumLastPostedDateIndex"})
    public String getLastPostedDateTime() {
        return LastPostedDateTime;
    }

    public void setLastPostedDateTime(String lastPostedDateTime) {
        LastPostedDateTime = lastPostedDateTime;
    }
    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }

    public String getLastPostedBy() {
        return LastPostedBy;
    }

    public void setLastPostedBy(String lastPostedBy) {
        LastPostedBy = lastPostedBy;
    }

    public Integer getViews() {
        return Views;
    }

    public void setViews(Integer views) {
        Views = views;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "ForumRepliesIndex")
    public Integer getReplies() {
        return Replies;
    }

    public void setReplies(Integer replies) {
        Replies = replies;
    }

    public Integer getAnswered() {
        return Answered;
    }

    public void setAnswered(Integer answered) {
        Answered = answered;
    }

    public List<String> getTags() {
        return Tags;
    }

    public void setTags(List<String> tags) {
        Tags = tags;
    }

    public MessageThread() {
        this.Answered = 0;
        this.LastPostedBy = "";
        this.ForumName = "";
        this.Message = "";
        this.LastPostedDateTime = "";
        this.Replies = 0;
        this.Views = 0;
        this.Subject = "";
    }

    @Override
    public String toString() {
        return "MessageThread{" +
                "ForumName='" + ForumName + '\'' +
                ", Subject='" + Subject + '\'' +
                ", Message='" + Message + '\'' +
                ", LastPostedBy='" + LastPostedBy + '\'' +
                ", LastPostedDateTime='" + LastPostedDateTime + '\'' +
                ", Views=" + Views +
                ", Replies=" + Replies +
                ", Answered=" + Answered +
                ", Tags=" + Tags +
                '}';
    }
}
```

## Buat indeks
<a name="ddb-en-client-use-secindex-confindex"></a>

Dimulai dengan versi 2.20.86 SDK for Java, `createTable()` metode ini secara otomatis menghasilkan indeks sekunder dari anotasi kelas data. Secara default, semua atribut dari tabel dasar disalin ke indeks dan nilai throughput yang disediakan adalah 20 unit kapasitas baca dan 20 unit kapasitas tulis.

Namun, jika Anda menggunakan versi SDK sebelum 2.20.86, Anda perlu membuat indeks bersama dengan tabel seperti yang ditunjukkan pada contoh berikut. Contoh ini membangun dua indeks untuk tabel. `Thread` Parameter [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) memiliki metode untuk mengkonfigurasi kedua jenis indeks seperti yang ditunjukkan setelah baris komentar 1 dan 2. Anda menggunakan `indexName()` metode pembuat indeks untuk mengaitkan nama indeks yang ditentukan dalam anotasi kelas data dengan jenis indeks yang dimaksud.

Kode ini mengkonfigurasi semua atribut tabel untuk berakhir di kedua indeks setelah baris komentar 3 dan 4. Informasi selengkapnya tentang [proyeksi atribut](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Projections) tersedia di Panduan Pengembang *Amazon DynamoDB*.

```
    public static void createMessageThreadTable(DynamoDbTable<MessageThread> messageThreadDynamoDbTable, DynamoDbClient dynamoDbClient) {
        messageThreadDynamoDbTable.createTable(b -> b
                // 1. Generate the GSI.
                .globalSecondaryIndices(gsi -> gsi.indexName("SubjectLastPostedDateIndex")
                        // 3. Populate the GSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
                // 2. Generate the LSI.
                .localSecondaryIndices(lsi -> lsi.indexName("ForumLastPostedDateIndex")
                        // 4. Populate the LSI with all attributes.
                        .projection(p -> p
                                .projectionType(ProjectionType.ALL))
                )
        );
```

## Kueri dengan menggunakan indeks
<a name="ddb-en-client-use-secindex-query"></a>

Contoh berikut query indeks *ForumLastPostedDateIndex*sekunder lokal.

Mengikuti baris komentar 2, Anda membuat [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)objek yang diperlukan saat memanggil [DynamoDbIndexmetode.query ()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbIndex.html#query(java.util.function.Consumer)). 

Anda mendapatkan referensi ke indeks yang ingin Anda kueri setelah baris komentar 3 dengan meneruskan nama indeks. Mengikuti baris komentar 4, Anda memanggil `query()` metode pada indeks yang lewat di `QueryConditional` objek. 

Anda juga mengonfigurasi kueri untuk mengembalikan tiga nilai atribut seperti yang ditunjukkan setelah baris komentar 5. Jika tidak `attributesToProject()` dipanggil, query mengembalikan semua nilai atribut. Perhatikan bahwa nama atribut yang ditentukan dimulai dengan huruf kecil. Nama atribut ini cocok dengan yang digunakan dalam tabel, belum tentu nama atribut dari kelas data.

Mengikuti baris komentar 6, ulangi hasil dan log setiap item yang dikembalikan oleh kueri dan juga menyimpannya dalam daftar untuk kembali ke pemanggil.

```
public class IndexScanExamples {
    private static Logger logger = LoggerFactory.getLogger(IndexScanExamples.class);

    public static List<MessageThread> queryUsingSecondaryIndices(String lastPostedDate,
                                                                 DynamoDbTable<MessageThread> threadTable) {
        // 1. Log the parameter value.
        logger.info("lastPostedDate value: {}", lastPostedDate);

        // 2. Create a QueryConditional whose sort key value must be greater than or equal to the parameter value.
        QueryConditional queryConditional = QueryConditional.sortGreaterThanOrEqualTo(qc ->
                qc.partitionValue("Forum02").sortValue(lastPostedDate));

        // 3. Specify the index name to query.
        final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex");

        // 4. Perform the query using the QueryConditional object.
        final SdkIterable<Page<MessageThread>> pagedResult = forumLastPostedDateIndex.query(q -> q
                .queryConditional(queryConditional)
                // 5. Request three attribute in the results.
                .attributesToProject("forumName", "subject", "lastPostedDateTime"));

        List<MessageThread> collectedItems = new ArrayList<>();
        // 6. Iterate through pages response and sort the items.
        pagedResult.stream().forEach(page -> page.items().stream()
                .sorted(Comparator.comparing(MessageThread::getLastPostedDateTime))
                .forEach(mt -> {
                    // 7. Log the returned items and add the collection to return to the caller.
                    logger.info(mt.toString());
                    collectedItems.add(mt);
                }));
        return collectedItems;
    }
```

Item berikut ada dalam database sebelum query dijalankan.

```
MessageThread{ForumName='Forum01', Subject='Subject01', Message='Message01', LastPostedBy='', LastPostedDateTime='2023.03.28', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject02', Message='Message02', LastPostedBy='', LastPostedDateTime='2023.03.29', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject04', Message='Message04', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='Message08', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='Message10', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject03', Message='Message03', LastPostedBy='', LastPostedDateTime='2023.03.30', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject06', Message='Message06', LastPostedBy='', LastPostedDateTime='2023.04.02', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum03', Subject='Subject09', Message='Message09', LastPostedBy='', LastPostedDateTime='2023.04.05', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum05', Subject='Subject05', Message='Message05', LastPostedBy='', LastPostedDateTime='2023.04.01', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum07', Subject='Subject07', Message='Message07', LastPostedBy='', LastPostedDateTime='2023.04.03', Views=0, Replies=0, Answered=0, Tags=null}
```

Pernyataan logging pada baris 1 dan 6 menghasilkan output konsol berikut.

```
lastPostedDate value: 2023.03.31
MessageThread{ForumName='Forum02', Subject='Subject04', Message='', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject08', Message='', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null}
MessageThread{ForumName='Forum02', Subject='Subject10', Message='', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}
```

*Kueri mengembalikan item dengan `forumName` nilai *Forum02* dan `lastPostedDateTime` nilai lebih besar dari atau sama dengan 2023.03.31.* Hasilnya menunjukkan `message` nilai dengan string kosong meskipun `message` atribut memiliki nilai dalam indeks. Ini karena atribut pesan tidak diproyeksikan oleh kode setelah baris komentar 5. 

# Gunakan fitur pemetaan tingkat lanjut
<a name="ddb-en-client-adv-features"></a>

Pelajari tentang fitur skema tabel lanjutan di DynamoDB Enhanced Client API.

## Memahami jenis skema tabel
<a name="ddb-en-client-adv-features-schm-overview"></a>

`[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)`adalah antarmuka ke fungsionalitas pemetaan DynamoDB Enhanced Client API. Hal ini dapat memetakan objek data ke dan dari peta [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html). Sebuah `TableSchema` objek perlu tahu tentang struktur tabel yang dipetakannya. Informasi struktur ini disimpan dalam suatu [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.html)objek.

API klien yang disempurnakan memiliki beberapa implementasi`TableSchema`, yang mengikuti. 

### Skema tabel yang dihasilkan dari kelas beranotasi
<a name="ddb-en-client-adv-features-schema-mapped"></a>

Ini adalah operasi yang cukup mahal untuk membangun `TableSchema` dari kelas beranotasi, jadi kami sarankan melakukan ini sekali, saat startup aplikasi.

 [ BeanTableSchema ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.html)   
Implementasi ini dibangun berdasarkan atribut dan anotasi kelas kacang. Contoh pendekatan ini ditunjukkan di [bagian Memulai](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean).  
Jika a `BeanTableSchema` tidak berperilaku seperti yang Anda harapkan, aktifkan pencatatan debug untuk. `software.amazon.awssdk.enhanced.dynamodb.beans`

[ImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchema.html)  
Implementasi ini dibangun dari kelas data yang tidak dapat diubah. Pendekatan ini dijelaskan di [Bekerja dengan kelas data yang tidak dapat diubah](ddb-en-client-use-immut.md) bagian ini.

### Skema tabel yang dihasilkan dengan pembangun
<a name="ddb-en-client-adv-features-schema-static"></a>

Berikut `TableSchema` s dibangun dari kode dengan menggunakan pembangun. Pendekatan ini lebih murah daripada pendekatan yang menggunakan kelas data beranotasi. Pendekatan builder menghindari penggunaan anotasi dan tidak memerlukan standar JavaBean penamaan.

[StaticTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchema.html)  
Implementasi ini dibangun untuk kelas data yang bisa berubah. Bagian memulai dari panduan ini menunjukkan cara [membuat `StaticTableSchema` menggunakan pembangun](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder).

[StaticImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html)  
Demikian pula dengan cara Anda membangun`StaticTableSchema`, Anda menghasilkan implementasi jenis ini `TableSchema` menggunakan [pembangun](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html) untuk digunakan dengan kelas data yang tidak dapat diubah.

### Skema tabel untuk data tanpa skema tetap
<a name="ddb-en-client-adv-features-schema-document"></a>

[DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)  
Tidak seperti implementasi lain dari`TableSchema`, Anda tidak mendefinisikan atribut untuk sebuah `DocumentTableSchema` instance. Biasanya, Anda hanya menentukan kunci utama dan penyedia konverter atribut. Sebuah `EnhancedDocument` instance menyediakan atribut yang Anda bangun dari elemen individual atau dari string JSON.

# Sertakan atau kecualikan atribut secara eksplisit
<a name="ddb-en-client-adv-features-inex-attr"></a>

DynamoDB Enhanced Client API menawarkan anotasi untuk mengecualikan atribut kelas data agar tidak menjadi atribut pada tabel. Dengan API, Anda juga dapat menggunakan nama atribut yang berbeda dari nama atribut kelas data.

## Kecualikan atribut
<a name="ddb-en-client-adv-features-inex-attr-ex"></a>

Untuk mengabaikan atribut yang seharusnya tidak dipetakan ke tabel DynamoDB, tandai atribut dengan anotasi. `@DynamoDbIgnore`

```
private String internalKey;

@DynamoDbIgnore
public String getInternalKey() { return this.internalKey; }
public void setInternalKey(String internalKey) { this.internalKey = internalKey;}
```

## Sertakan atribut
<a name="ddb-en-client-adv-features-inex-attr-in"></a>

Untuk mengubah nama atribut yang digunakan dalam tabel DynamoDB, tandai dengan anotasi dan berikan nama `@DynamoDbAttribute` yang berbeda.

```
private String internalKey;

@DynamoDbAttribute("renamedInternalKey")
public String getInternalKey() { return this.internalKey; }
public void setInternalKey(String internalKey) { this.internalKey = internalKey;}
```

# Konversi atribut kontrol
<a name="ddb-en-client-adv-features-conversion"></a>

Secara default, skema tabel menyediakan konverter untuk banyak jenis Java umum melalui implementasi default antarmuka. `[AttributeConverterProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverterProvider.html)` Anda dapat mengubah keseluruhan perilaku default dengan `AttributeConverterProvider` implementasi kustom. Anda juga dapat mengubah konverter untuk satu atribut.

Untuk daftar konverter yang tersedia, lihat [AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html)antarmuka Java doc.

## Menyediakan penyedia konverter atribut khusus
<a name="ddb-en-client-adv-features-conversion-prov"></a>

Anda dapat memberikan satu `AttributeConverterProvider` atau satu rantai `AttributeConverterProvider` s yang dipesan melalui `@DynamoDbBean` `(converterProviders = {…})` anotasi. Setiap kustom `AttributeConverterProvider` harus memperluas `AttributeConverterProvider` antarmuka.

Perhatikan bahwa jika Anda menyediakan rantai penyedia konverter atribut Anda sendiri, Anda akan mengganti penyedia konverter default,`DefaultAttributeConverterProvider`. Jika Anda ingin menggunakan fungsionalitas`DefaultAttributeConverterProvider`, Anda harus memasukkannya ke dalam rantai. 

Dimungkinkan juga untuk membubuhi keterangan kacang dengan array kosong. `{}` Ini menonaktifkan penggunaan penyedia konverter atribut apa pun, termasuk default. Dalam hal ini semua atribut yang akan dipetakan harus memiliki konverter atribut mereka sendiri.

Cuplikan berikut menunjukkan penyedia konverter tunggal.

```
@DynamoDbBean(converterProviders = ConverterProvider1.class)
public class Customer {

}
```

Cuplikan berikut menunjukkan penggunaan rantai penyedia konverter. Karena default SDK disediakan terakhir, ia memiliki prioritas terendah.

```
@DynamoDbBean(converterProviders = {
   ConverterProvider1.class, 
   ConverterProvider2.class,
   DefaultAttributeConverterProvider.class})
public class Customer {

}
```

Pembangun skema tabel statis memiliki `attributeConverterProviders()` metode yang bekerja dengan cara yang sama. Ini ditunjukkan dalam cuplikan berikut.

```
private static final StaticTableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
  StaticTableSchema.builder(Customer.class)
    .newItemSupplier(Customer::new)
    .addAttribute(String.class, a -> a.name("name")
                                     a.getter(Customer::getName)
                                     a.setter(Customer::setName))
    .attributeConverterProviders(converterProvider1, converterProvider2)
    .build();
```

## Ganti pemetaan atribut tunggal
<a name="ddb-en-client-adv-features-conversion-single"></a>

Untuk mengganti cara atribut tunggal dipetakan, berikan atribut `AttributeConverter` untuk atribut. Penambahan ini mengesampingkan konverter apa pun yang disediakan oleh skema `AttributeConverterProviders` tabel. Ini menambahkan konverter khusus hanya untuk atribut itu. Atribut lain, bahkan yang dari tipe yang sama, tidak akan menggunakan konverter itu kecuali jika secara eksplisit ditentukan untuk atribut lainnya.

`@DynamoDbConvertedBy`Anotasi ini digunakan untuk menentukan `AttributeConverter` kelas kustom seperti yang ditunjukkan dalam cuplikan berikut.

```
@DynamoDbBean
public class Customer {
    private String name;

    @DynamoDbConvertedBy(CustomAttributeConverter.class)
    public String getName() { return this.name; }
    public void setName(String name) { this.name = name;}
}
```

Pembangun untuk skema statis memiliki `attributeConverter()` metode pembangun atribut yang setara. Metode ini mengambil contoh dari `AttributeConverter` sebagai berikut menunjukkan.

```
private static final StaticTableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
  StaticTableSchema.builder(Customer.class)
    .newItemSupplier(Customer::new)
    .addAttribute(String.class, a -> a.name("name")
                                     a.getter(Customer::getName)
                                     a.setter(Customer::setName)
                                     a.attributeConverter(customAttributeConverter))
    .build();
```

## Contoh
<a name="ddb-en-client-adv-features-conversion-example"></a>

Contoh ini menunjukkan `AttributeConverterProvider` implementasi yang menyediakan konverter atribut untuk [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpCookie.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpCookie.html)objek. 

`SimpleUser`Kelas berikut berisi atribut bernama `lastUsedCookie` yang merupakan instance dari`HttpCookie`.

Parameter untuk `@DynamoDbBean` anotasi mencantumkan dua `AttributeConverterProvider` kelas yang menyediakan konverter.

------
#### [ Class with annotations ]

```
    @DynamoDbBean(converterProviders = {CookieConverterProvider.class, DefaultAttributeConverterProvider.class})
    public static final class SimpleUser {
        private String name;
        private HttpCookie lastUsedCookie;

        @DynamoDbPartitionKey
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public HttpCookie getLastUsedCookie() {
            return lastUsedCookie;
        }

        public void setLastUsedCookie(HttpCookie lastUsedCookie) {
            this.lastUsedCookie = lastUsedCookie;
        }
```

------
#### [ Static table schema ]

```
    private static final TableSchema<SimpleUser> SIMPLE_USER_TABLE_SCHEMA =
            TableSchema.builder(SimpleUser.class)
                    .newItemSupplier(SimpleUser::new)
                    .attributeConverterProviders(CookieConverterProvider.create(), AttributeConverterProvider.defaultProvider())
                    .addAttribute(String.class, a -> a.name("name")
                            .setter(SimpleUser::setName)
                            .getter(SimpleUser::getName)
                            .tags(StaticAttributeTags.primaryPartitionKey()))
                    .addAttribute(HttpCookie.class, a -> a.name("lastUsedCookie")
                            .setter(SimpleUser::setLastUsedCookie)
                            .getter(SimpleUser::getLastUsedCookie))
                    .build();
```

------

`CookieConverterProvider`Dalam contoh berikut memberikan contoh dari sebuah`HttpCookeConverter`.

```
    public static final class CookieConverterProvider implements AttributeConverterProvider {
        private final Map<EnhancedType<?>, AttributeConverter<?>> converterCache = ImmutableMap.of(
                // 1. Add HttpCookieConverter to the internal cache.
                EnhancedType.of(HttpCookie.class), new HttpCookieConverter());

        public static CookieConverterProvider create() {
            return new CookieConverterProvider();
        }

        // The SDK calls this method to find out if the provider contains a AttributeConverter instance
        // for the EnhancedType<T> argument.
        @SuppressWarnings("unchecked")
        @Override
        public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
            return (AttributeConverter<T>) converterCache.get(enhancedType);
        }
    }
```

### Kode konversi
<a name="ddb-en-client-adv-features-conversion-example-code"></a>

Dalam `transformFrom()` metode `HttpCookieConverter` kelas berikut, kode menerima `HttpCookie` instance dan mengubahnya menjadi peta DynamoDB yang disimpan sebagai atribut.

`transformTo()`Metode menerima parameter peta DynamoDB, kemudian memanggil konstruktor `HttpCookie` yang membutuhkan nama dan nilai.

```
    public static final class HttpCookieConverter implements AttributeConverter<HttpCookie> {

        @Override
        public AttributeValue transformFrom(HttpCookie httpCookie) {

            return AttributeValue.fromM(
            Map.of ("cookieName", AttributeValue.fromS(httpCookie.getName()),
                    "cookieValue", AttributeValue.fromS(httpCookie.getValue()))
            );
        }

        @Override
        public HttpCookie transformTo(AttributeValue attributeValue) {
            Map<String, AttributeValue> map = attributeValue.m();
            return new HttpCookie(
                    map.get("cookieName").s(),
                    map.get("cookieValue").s());
        }

        @Override
        public EnhancedType<HttpCookie> type() {
            return EnhancedType.of(HttpCookie.class);
        }

        @Override
        public AttributeValueType attributeValueType() {
            return AttributeValueType.M;
        }
    }
```

# Ubah perilaku pembaruan atribut
<a name="ddb-en-client-adv-features-upd-behavior"></a>

Anda dapat menyesuaikan perilaku pembaruan atribut individual saat Anda melakukan operasi *pembaruan*. [Beberapa contoh operasi pembaruan di DynamoDB Enhanced Client API [adalah updateItem](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#updateItem(T)) () dan (). transactWriteItems](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))

Misalnya, bayangkan Anda ingin menyimpan stempel waktu yang *dibuat pada* catatan Anda. Namun, Anda ingin nilainya ditulis hanya jika tidak ada nilai yang ada untuk atribut yang sudah ada dalam database. Dalam hal ini, Anda menggunakan perilaku `[WRITE\$1IF\$1NOT\$1EXISTS](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html#WRITE_IF_NOT_EXISTS)` pembaruan.

Contoh berikut menunjukkan anotasi yang menambahkan perilaku ke `createdOn` atribut.

```
@DynamoDbBean
public class Customer extends GenericRecord {
    private String id;
    private Instant createdOn;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }
    public void setId(String id) { this.name = id; }

    @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)
    public Instant getCreatedOn() { return this.createdOn; }    
    public void setCreatedOn(Instant createdOn) { this.createdOn = createdOn; }
}
```

Anda dapat mendeklarasikan perilaku pembaruan yang sama ketika Anda membangun skema tabel statis seperti yang ditunjukkan pada contoh berikut setelah baris komentar 1.

```
static final TableSchema<Customer> CUSTOMER_TABLE_SCHEMA =
     TableSchema.builder(Customer.class)
       .newItemSupplier(Customer::new)
       .addAttribute(String.class, a -> a.name("id")
                                         .getter(Customer::getId)
                                         .setter(Customer::setId)
                                         .tags(StaticAttributeTags.primaryPartitionKey()))
       .addAttribute(Instant.class, a -> a.name("createdOn")
                                          .getter(Customer::getCreatedOn)
                                          .setter(Customer::setCreatedOn)
                                          // 1. Add an UpdateBehavior.
                                          .tags(StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)))
       .build();
```

# Ratakan atribut dari kelas lain
<a name="ddb-en-client-adv-features-flatmap"></a>

Jika atribut untuk tabel Anda tersebar di beberapa kelas Java yang berbeda, baik melalui pewarisan atau komposisi, DynamoDB Enhanced Client API menyediakan dukungan untuk meratakan atribut menjadi satu kelas.

## Gunakan warisan
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

Jika kelas Anda menggunakan pewarisan, gunakan pendekatan berikut untuk meratakan hierarki.

### Gunakan kacang beranotasi
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

Untuk pendekatan anotasi, kedua kelas harus membawa `@DynamoDbBean` anotasi dan kelas harus membawa satu atau lebih anotasi kunci primer.

Berikut ini menunjukkan contoh kelas data yang memiliki hubungan warisan.

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

@DynamoDbBean
public abstract class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

[`onMethod`Opsi](https://projectlombok.org/features/experimental/onX) Lombok menyalin anotasi DynamoDB berbasis atribut, seperti, ke kode yang dihasilkan. `@DynamoDbPartitionKey`

```
@DynamoDbBean
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord {
    private String name;
}

@Data
@DynamoDbBean
public abstract class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

### Gunakan skema statis
<a name="ddb-en-client-adv-features-flatmap-inheritance-static"></a>

Untuk pendekatan skema statis, gunakan `extend()` metode pembangun untuk menciutkan atribut kelas induk ke kelas anak. Ini ditampilkan setelah komentar baris 1 dalam contoh berikut.

```
        StaticTableSchema<org.example.tests.model.inheritance.stat.GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.GenericRecord.class)
                        // The partition key will be inherited by the top level mapper.
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getId)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getCreatedDate)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<org.example.tests.model.inheritance.stat.Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.Customer.class)
                        .newItemSupplier(org.example.tests.model.inheritance.stat.Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(org.example.tests.model.inheritance.stat.Customer::getName)
                                .setter(org.example.tests.model.inheritance.stat.Customer::setName))
                        // 1. Use the extend() method to collapse the parent attributes onto the child class.
                        .extend(GENERIC_RECORD_SCHEMA)     // All the attributes of the GenericRecord schema are added to Customer.
                        .build();
```

Contoh skema statis sebelumnya menggunakan kelas data berikut. Karena pemetaan didefinisikan ketika Anda membangun skema tabel statis, kelas data tidak memerlukan anotasi.

#### Kelas data
<a name="gunk"></a>

------
#### [ Standard data class ]

```
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}


public abstract class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
```

------
#### [ Lombok ]

```
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord{
    private String name;
}

@Data
public abstract class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

## Gunakan komposisi
<a name="ddb-en-client-adv-features-flatmap-comp"></a>

Jika kelas Anda menggunakan komposisi, gunakan pendekatan berikut untuk meratakan hierarki.

### Gunakan kacang beranotasi
<a name="ddb-en-client-adv-features-flatmap-comp-anno"></a>

`@DynamoDbFlatten`Anotasi meratakan kelas yang terkandung.

Contoh kelas data berikut menggunakan `@DynamoDbFlatten` anotasi untuk secara efektif menambahkan semua atribut kelas yang terkandung ke `GenericRecord` `Customer` kelas.

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    @DynamoDbFlatten
    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

@DynamoDbBean
public class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
@DynamoDbBean
public class Customer {
    private String name;
    @Getter(onMethod_=@DynamoDbFlatten)
    private GenericRecord record;
}

@Data
@DynamoDbBean
public class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

Anda dapat menggunakan anotasi rata untuk meratakan sebanyak mungkin kelas yang memenuhi syarat yang Anda butuhkan. Batasan berikut berlaku:
+ Semua nama atribut harus unik setelah diratakan.
+ Tidak boleh ada lebih dari satu kunci partisi, kunci sortir, atau nama tabel.

### Gunakan skema statis
<a name="ddb-en-client-adv-features-flatmap-comp-static"></a>

Saat Anda membuat skema tabel statis, gunakan `flatten()` metode pembangun. Anda juga menyediakan metode pengambil dan penyetel yang mengidentifikasi kelas yang terkandung.

```
        StaticTableSchema<GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(GenericRecord.class)
                        .newItemSupplier(GenericRecord::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(GenericRecord::getId)
                                .setter(GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(GenericRecord::getCreatedDate)
                                .setter(GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getName)
                                .setter(Customer::setName))
                        // Because we are flattening a component object, we supply a getter and setter so the
                        // mapper knows how to access it.
                        .flatten(GENERIC_RECORD_SCHEMA, Customer::getRecord, Customer::setRecord)
                        .build();
```

Contoh skema statis sebelumnya menggunakan kelas data berikut.

#### Kelas data
<a name="ddb-en-client-adv-features-flatmap-comp-static-supporting"></a>

------
#### [ Standard data class ]

```
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

public class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
public class Customer {
    private String name;
    private GenericRecord record;
}

@Data
public class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

Anda dapat menggunakan pola pembangun untuk meratakan sebanyak mungkin kelas yang memenuhi syarat yang Anda butuhkan.

## Implikasi untuk kode lain
<a name="ddb-en-client-adv-features-flatmap-compare"></a>

Bila Anda menggunakan `@DynamoDbFlatten` atribut (atau metode `flatten()` builder), item di DynamoDB berisi atribut untuk setiap atribut dari objek yang disusun. Ini juga mencakup atribut dari objek penulisan. 

Sebaliknya, jika Anda membuat anotasi kelas data dengan kelas tersusun dan tidak menggunakan`@DynamoDbFlatten`, item disimpan dengan objek tersusun sebagai atribut tunggal.

Misalnya, bandingkan `Customer` kelas yang ditunjukkan dalam [perataan dengan contoh komposisi dengan](#ddb-en-client-adv-features-flatmap-comp-anno) dan tanpa perataan atribut. `record` Anda dapat memvisualisasikan perbedaannya dengan JSON seperti yang ditunjukkan pada tabel berikut.


****  

| Dengan perataan | Tanpa perataan | 
| --- | --- | 
| 3 atribut | 2 atribut | 
|  <pre>{<br />  "id": "1",<br />  "createdDate": "today",<br />  "name": "my name"<br />}</pre>  |  <pre>{<br />  "id": "1",<br />  "record": {<br />      "createdDate": "today",<br />      "name": "my name"<br />  }<br />}</pre>  | 

Perbedaannya menjadi penting jika Anda memiliki kode lain yang mengakses tabel DynamoDB yang mengharapkan untuk menemukan atribut tertentu.

# Bekerja dengan atribut yang kacang, peta, daftar, dan set
<a name="ddb-en-client-adv-features-nested"></a>

Definisi kacang, seperti `Person` kelas yang ditunjukkan di bawah ini, mungkin mendefinisikan properti (atau atribut) yang merujuk ke tipe dengan atribut tambahan. Misalnya, di `Person` kelas, `mainAddress` adalah properti yang mengacu pada `Address` kacang yang mendefinisikan atribut nilai tambahan. `addresses`mengacu pada Peta Jawa, yang unsur-unsurnya mengacu pada `Address` kacang. Tipe kompleks ini dapat dianggap sebagai wadah atribut sederhana yang Anda gunakan untuk nilai datanya dalam konteks DynamoDB. 

*DynamoDB mengacu pada properti nilai elemen bersarang, seperti peta, daftar, atau kacang, sebagai atribut bersarang.* *Panduan [Pengembang Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) mengacu pada bentuk yang disimpan dari peta Java, daftar atau kacang sebagai jenis dokumen.* Atribut sederhana yang Anda gunakan untuk nilai data mereka di Java disebut sebagai *tipe skalar* di DynamoDB. Set, yang berisi beberapa elemen skalar dari jenis yang sama, dan disebut sebagai *tipe set*. 

Penting untuk diketahui bahwa DynamoDB Enhanced Client API mengonversi properti yang bean ke jenis dokumen peta DynamoDB saat disimpan.

## `Person` kelas
<a name="ddb-en-client-adv-features-nested-person"></a>

```
@DynamoDbBean
public class Person {
    private Integer id;
    private String firstName;
    private String lastName;
    private Integer age;
    private Address mainAddress;
    private Map<String, Address> addresses;
    private List<PhoneNumber> phoneNumbers;
    private Set<String> hobbies;

    @DynamoDbPartitionKey
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getMainAddress() {
        return mainAddress;
    }

    public void setMainAddress(Address mainAddress) {
        this.mainAddress = mainAddress;
    }

    public Map<String, Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(Map<String, Address> addresses) {
        this.addresses = addresses;
    }

    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }

    public Set<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(Set<String> hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public String toString() {
        return "Person{" +
               "addresses=" + addresses +
               ", id=" + id +
               ", firstName='" + firstName + '\'' +
               ", lastName='" + lastName + '\'' +
               ", age=" + age +
               ", mainAddress=" + mainAddress +
               ", phoneNumbers=" + phoneNumbers +
               ", hobbies=" + hobbies +
               '}';
    }
}
```

## `Address` kelas
<a name="ddb-en-client-adv-features-nested-address"></a>

```
@DynamoDbBean
public class Address {
    private String street;
    private String city;
    private String state;
    private String zipCode;

    public Address() {
    }

    public String getStreet() {
        return this.street;
    }

    public String getCity() {
        return this.city;
    }

    public String getState() {
        return this.state;
    }

    public String getZipCode() {
        return this.zipCode;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public void setState(String state) {
        this.state = state;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return Objects.equals(street, address.street) && Objects.equals(city, address.city) && Objects.equals(state, address.state) && Objects.equals(zipCode, address.zipCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(street, city, state, zipCode);
    }

    @Override
    public String toString() {
        return "Address{" +
                "street='" + street + '\'' +
                ", city='" + city + '\'' +
                ", state='" + state + '\'' +
                ", zipCode='" + zipCode + '\'' +
                '}';
    }
}
```

## `PhoneNumber` kelas
<a name="ddb-en-client-adv-features-nested-phonenumber"></a>

```
@DynamoDbBean
public class PhoneNumber {
    String type;
    String number;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "PhoneNumber{" +
                "type='" + type + '\'' +
                ", number='" + number + '\'' +
                '}';
    }
}
```

## Simpan tipe kompleks
<a name="ddb-en-client-adv-features-nested-mapping"></a>

### Gunakan kelas data beranotasi
<a name="ddb-en-client-adv-features-nested-map-anno"></a>

Anda menyimpan atribut bersarang untuk kelas khusus hanya dengan membuat anotasi. `Address`Kelas dan `PhoneNumber` kelas yang ditampilkan sebelumnya dianotasi hanya dengan anotasi. `@DynamoDbBean` Saat DynamoDB Enhanced Client API membangun skema tabel untuk `Person` kelas dengan cuplikan berikut, API akan menemukan penggunaan class `PhoneNumber` dan dan membangun pemetaan yang sesuai agar berfungsi dengan DynamoDB. `Address`

```
TableSchema<Person> personTableSchema = TableSchema.fromBean(Person.class);
```

### Gunakan skema abstrak dengan pembangun
<a name="ddb-en-client-adv-features-nested-map-builder"></a>

Pendekatan alternatifnya adalah dengan menggunakan pembangun skema tabel statis untuk setiap kelas kacang bersarang seperti yang ditunjukkan pada kode berikut.

Skema tabel untuk `PhoneNumber` kelas `Address` dan abstrak dalam arti bahwa mereka tidak dapat digunakan dengan tabel DynamoDB. Ini karena mereka tidak memiliki definisi untuk kunci utama. Mereka digunakan, bagaimanapun, sebagai skema bersarang dalam skema tabel untuk kelas. `Person`

Setelah baris komentar 1 dan 2 dalam definisi`PERSON_TABLE_SCHEMA`, Anda melihat kode yang menggunakan skema tabel abstrak. Penggunaan `documentOf` dalam `EnhanceType.documentOf(...)` metode tidak menunjukkan bahwa metode mengembalikan `EnhancedDocument` jenis API Dokumen yang Ditingkatkan. `documentOf(...)`Metode dalam konteks ini mengembalikan objek yang tahu bagaimana memetakan argumen kelasnya ke dan dari DynamoDB atribut tabel dengan menggunakan argumen skema tabel.

#### Kode skema statis
<a name="ddb-en-client-adv-features-nested-map-builder-code"></a>

```
    // Abstract table schema that cannot be used to work with a DynamoDB table,
    // but can be used as a nested schema.
    public static final TableSchema<Address> TABLE_SCHEMA_ADDRESS = TableSchema.builder(Address.class)
        .newItemSupplier(Address::new)
        .addAttribute(String.class, a -> a.name("street")
            .getter(Address::getStreet)
            .setter(Address::setStreet))
        .addAttribute(String.class, a -> a.name("city")
            .getter(Address::getCity)
            .setter(Address::setCity))
        .addAttribute(String.class, a -> a.name("zipcode")
            .getter(Address::getZipCode)
            .setter(Address::setZipCode))
        .addAttribute(String.class, a -> a.name("state")
            .getter(Address::getState)
            .setter(Address::setState))
        .build();

    // Abstract table schema that cannot be used to work with a DynamoDB table,
    // but can be used as a nested schema.
    public static final TableSchema<PhoneNumber> TABLE_SCHEMA_PHONENUMBER = TableSchema.builder(PhoneNumber.class)
        .newItemSupplier(PhoneNumber::new)
        .addAttribute(String.class, a -> a.name("type")
            .getter(PhoneNumber::getType)
            .setter(PhoneNumber::setType))
        .addAttribute(String.class, a -> a.name("number")
            .getter(PhoneNumber::getNumber)
            .setter(PhoneNumber::setNumber))
        .build();

    // A static table schema that can be used with a DynamoDB table.
    // The table schema contains two nested schemas that are used to perform mapping to/from DynamoDB.
    public static final TableSchema<Person> PERSON_TABLE_SCHEMA =
        TableSchema.builder(Person.class)
            .newItemSupplier(Person::new)
            .addAttribute(Integer.class, a -> a.name("id")
                .getter(Person::getId)
                .setter(Person::setId)
                .addTag(StaticAttributeTags.primaryPartitionKey()))
            .addAttribute(String.class, a -> a.name("firstName")
                .getter(Person::getFirstName)
                .setter(Person::setFirstName))
            .addAttribute(String.class, a -> a.name("lastName")
                .getter(Person::getLastName)
                .setter(Person::setLastName))
            .addAttribute(Integer.class, a -> a.name("age")
                .getter(Person::getAge)
                .setter(Person::setAge))
            .addAttribute(EnhancedType.documentOf(Address.class, TABLE_SCHEMA_ADDRESS), a -> a.name("mainAddress")
                .getter(Person::getMainAddress)
                .setter(Person::setMainAddress))
            .addAttribute(EnhancedType.listOf(String.class), a -> a.name("hobbies")
                .getter(Person::getHobbies)
                .setter(Person::setHobbies))
            .addAttribute(EnhancedType.mapOf(
                EnhancedType.of(String.class),
                // 1. Use mapping functionality of the Address table schema.
                EnhancedType.documentOf(Address.class, TABLE_SCHEMA_ADDRESS)), a -> a.name("addresses")
                .getter(Person::getAddresses)
                .setter(Person::setAddresses))
            .addAttribute(EnhancedType.listOf(
                // 2. Use mapping functionality of the PhoneNumber table schema.
                EnhancedType.documentOf(PhoneNumber.class, TABLE_SCHEMA_PHONENUMBER)), a -> a.name("phoneNumbers")
                .getter(Person::getPhoneNumbers)
                .setter(Person::setPhoneNumbers))
            .build();
```

## Atribut proyek dari tipe kompleks
<a name="ddb-en-client-adv-features-nested-projection"></a>

Untuk `query()` dan `scan()` metode, Anda dapat menentukan atribut mana yang ingin Anda kembalikan dalam hasil dengan menggunakan panggilan metode seperti `addNestedAttributeToProject()` dan`attributesToProject()`. DynamoDB Enhanced Client API mengubah parameter panggilan metode Java [menjadi ekspresi proyeksi sebelum permintaan dikirim](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html).

Contoh berikut mengisi `Person` tabel dengan dua item, kemudian melakukan tiga operasi pemindaian. 

Pemindaian pertama mengakses semua item dalam tabel untuk membandingkan hasilnya dengan operasi pemindaian lainnya. 

Pemindaian kedua menggunakan metode [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName))builder untuk mengembalikan hanya nilai `street` atribut.

Operasi pemindaian ketiga menggunakan metode [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...))builder untuk mengembalikan data untuk atribut tingkat pertama,`hobbies`. Jenis atribut `hobbies` adalah daftar. Untuk mengakses item daftar individual, lakukan `get()` operasi pada daftar.

```
        personDynamoDbTable = getDynamoDbEnhancedClient().table("Person", PERSON_TABLE_SCHEMA);
        PersonUtils.createPersonTable(personDynamoDbTable, getDynamoDbClient());
        // Use a utility class to add items to the Person table.
        List<Person> personList = PersonUtils.getItemsForCount(2);
        // This utility method performs a put against DynamoDB to save the instances in the list argument.
        PersonUtils.putCollection(getDynamoDbEnhancedClient(), personList, personDynamoDbTable);

        // The first scan logs all items in the table to compare to the results of the subsequent scans.
        final PageIterable<Person> allItems = personDynamoDbTable.scan();
        allItems.items().forEach(p ->
                // 1. Log what is in the table.
                logger.info(p.toString()));

        // Scan for nested attributes.
        PageIterable<Person> streetScanResult = personDynamoDbTable.scan(b -> b
                // Use the 'addNestedAttributeToProject()' or 'addNestedAttributesToProject()' to access data nested in maps in DynamoDB.
                .addNestedAttributeToProject(
                        NestedAttributeName.create("addresses", "work", "street")
                ));

        streetScanResult.items().forEach(p ->
                //2. Log the results of requesting nested attributes.
                logger.info(p.toString()));

        // Scan for a top-level list attribute.
        PageIterable<Person> hobbiesScanResult = personDynamoDbTable.scan(b -> b
                // Use the 'attributesToProject()' method to access first-level attributes.
                .attributesToProject("hobbies"));

        hobbiesScanResult.items().forEach((p) -> {
            // 3. Log the results of the request for the 'hobbies' attribute.
            logger.info(p.toString());
            // To access an item in a list, first get the parent attribute, 'hobbies', then access items in the list.
            String hobby = p.getHobbies().get(1);
            // 4. Log an item in the list.
            logger.info(hobby);
        });
```

```
// Logged results from comment line 1.
Person{id=2, firstName='first name 2', lastName='last name 2', age=11, addresses={work=Address{street='street 21', city='city 21', state='state 21', zipCode='33333'}, home=Address{street='street 2', city='city 2', state='state 2', zipCode='22222'}}, phoneNumbers=[PhoneNumber{type='home', number='222-222-2222'}, PhoneNumber{type='work', number='333-333-3333'}], hobbies=[hobby 2, hobby 21]}
Person{id=1, firstName='first name 1', lastName='last name 1', age=11, addresses={work=Address{street='street 11', city='city 11', state='state 11', zipCode='22222'}, home=Address{street='street 1', city='city 1', state='state 1', zipCode='11111'}}, phoneNumbers=[PhoneNumber{type='home', number='111-111-1111'}, PhoneNumber{type='work', number='222-222-2222'}], hobbies=[hobby 1, hobby 11]}

// Logged results from comment line 2.
Person{id=null, firstName='null', lastName='null', age=null, addresses={work=Address{street='street 21', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=null}
Person{id=null, firstName='null', lastName='null', age=null, addresses={work=Address{street='street 11', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=null}

// Logged results from comment lines 3 and 4.
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
hobby 21
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
hobby 11
```

**catatan**  
Jika `attributesToProject()` metode mengikuti metode pembangun lain yang menambahkan atribut yang ingin Anda proyeksikan, daftar nama atribut yang diberikan ke `attributesToProject()` menggantikan semua nama atribut lainnya.  
Pemindaian yang dilakukan dengan `ScanEnhancedRequest` instance dalam cuplikan berikut hanya mengembalikan data hobi.  

```
ScanEnhancedRequest lastOverwrites = ScanEnhancedRequest.builder()
        .addNestedAttributeToProject(
                NestedAttributeName.create("addresses", "work", "street"))
        .addAttributeToProject("firstName")
        // If the 'attributesToProject()' method follows other builder methods that add attributes for projection,
        // its list of attributes replace all previous attributes.
        .attributesToProject("hobbies")
        .build();
PageIterable<Person> hobbiesOnlyResult = personDynamoDbTable.scan(lastOverwrites);
hobbiesOnlyResult.items().forEach(p ->
        logger.info(p.toString()));

// Logged results.
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
Person{id=null, firstName='null', lastName='null', age=null, addresses=null, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
```
Cuplikan kode berikut menggunakan `attributesToProject()` metode terlebih dahulu. Urutan ini mempertahankan semua atribut lain yang diminta.  

```
ScanEnhancedRequest attributesPreserved = ScanEnhancedRequest.builder()
        // Use 'attributesToProject()' first so that the method call does not replace all other attributes
        // that you want to project.
        .attributesToProject("firstName")
        .addNestedAttributeToProject(
                NestedAttributeName.create("addresses", "work", "street"))
        .addAttributeToProject("hobbies")
        .build();
PageIterable<Person> allAttributesResult = personDynamoDbTable.scan(attributesPreserved);
allAttributesResult.items().forEach(p ->
        logger.info(p.toString()));

// Logged results.
Person{id=null, firstName='first name 2', lastName='null', age=null, addresses={work=Address{street='street 21', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=[hobby 2, hobby 21]}
Person{id=null, firstName='first name 1', lastName='null', age=null, addresses={work=Address{street='street 11', city='null', state='null', zipCode='null'}}, phoneNumbers=null, hobbies=[hobby 1, hobby 11]}
```

## Gunakan tipe kompleks dalam ekspresi
<a name="ddb-en-client-adv-features-nested-expressions"></a>

Anda dapat menggunakan tipe kompleks dalam ekspresi, seperti ekspresi filter dan ekspresi kondisi, dengan menggunakan operator dereferencing untuk menavigasi struktur tipe kompleks. Untuk objek dan peta, gunakan `. (dot)` dan untuk elemen daftar gunakan `[n]` (tanda kurung siku di sekitar nomor urut elemen). Anda tidak dapat merujuk ke elemen individual dari satu set, tetapi Anda dapat menggunakan [`contains`fungsi](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) tersebut.

Contoh berikut menunjukkan dua ekspresi filter yang digunakan dalam operasi scan. Ekspresi filter menentukan kondisi kecocokan untuk item yang Anda inginkan dalam hasil. Contoh menggunakan`Person`,`Address`, dan `PhoneNumber` kelas yang ditampilkan sebelumnya.

```
    public void scanUsingFilterOfNestedAttr() {
        // The following is a filter expression for an attribute that is a map of Address objects.
        // By using this filter expression, the SDK returns Person objects that have an address
        // with 'mailing' as a key and 'MS2' for a state value.
        Expression addressFilter = Expression.builder()
                .expression("addresses.#type.#field = :value")
                .putExpressionName("#type", "mailing")
                .putExpressionName("#field", "state")
                .putExpressionValue(":value", AttributeValue.builder().s("MS2").build())
                .build();

        PageIterable<Person> addressFilterResults = personDynamoDbTable.scan(rb -> rb.
                filterExpression(addressFilter));
        addressFilterResults.items().stream().forEach(p -> logger.info("Person: {}", p));

        assert addressFilterResults.items().stream().count() == 1;


        // The following is a filter expression for an attribute that is a list of phone numbers.
        // By using this filter expression, the SDK returns Person objects whose second phone number
        // in the list has a type equal to 'cell'.
        Expression phoneFilter = Expression.builder()
                .expression("phoneNumbers[1].#type = :type")
                .putExpressionName("#type", "type")
                .putExpressionValue(":type", AttributeValue.builder().s("cell").build())
                .build();

        PageIterable<Person> phoneFilterResults = personDynamoDbTable.scan(rb -> rb
                .filterExpression(phoneFilter)
                .attributesToProject("id", "firstName", "lastName", "phoneNumbers")
        );

        phoneFilterResults.items().stream().forEach(p -> logger.info("Person: {}", p));

        assert phoneFilterResults.items().stream().count() == 1;
        assert phoneFilterResults.items().stream().findFirst().get().getPhoneNumbers().get(1).getType().equals("cell");
    }
```

### Metode pembantu yang mengisi tabel
<a name="nested-expressions-helper-method"></a>

```
    public static void populateDatabase() {
        Person person1 = new Person();
        person1.setId(1);
        person1.setFirstName("FirstName1");
        person1.setLastName("LastName1");

        Address billingAddr1 = new Address();
        billingAddr1.setState("BS1");
        billingAddr1.setCity("BillingTown1");

        Address mailing1 = new Address();
        mailing1.setState("MS1");
        mailing1.setCity("MailingTown1");

        person1.setAddresses(Map.of("billing", billingAddr1, "mailing", mailing1));

        PhoneNumber pn1_1 = new PhoneNumber();
        pn1_1.setType("work");
        pn1_1.setNumber("111-111-1111");

        PhoneNumber pn1_2 = new PhoneNumber();
        pn1_2.setType("home");
        pn1_2.setNumber("222-222-2222");

        List<PhoneNumber> phoneNumbers1 = List.of(pn1_1, pn1_2);
        person1.setPhoneNumbers(phoneNumbers1);

        personDynamoDbTable.putItem(person1);

        Person person2 = person1;
        person2.setId(2);
        person2.setFirstName("FirstName2");
        person2.setLastName("LastName2");

        Address billingAddress2 = billingAddr1;
        billingAddress2.setCity("BillingTown2");
        billingAddress2.setState("BS2");

        Address mailing2 = mailing1;
        mailing2.setCity("MailingTown2");
        mailing2.setState("MS2");

        person2.setAddresses(Map.of("billing", billingAddress2, "mailing", mailing2));

        PhoneNumber pn2_1 = new PhoneNumber();
        pn2_1.setType("work");
        pn2_1.setNumber("333-333-3333");

        PhoneNumber pn2_2 = new PhoneNumber();
        pn2_2.setType("cell");
        pn2_2.setNumber("444-444-4444");

        List<PhoneNumber> phoneNumbers2 = List.of(pn2_1, pn2_2);
        person2.setPhoneNumbers(phoneNumbers2);

        personDynamoDbTable.putItem(person2);
    }
```

### Representasi JSON item dalam database
<a name="nested-attributes-expression-json-items"></a>

```
{
 "id": 1,
 "addresses": {
  "billing": {
   "city": "BillingTown1",
   "state": "BS1",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown1",
   "state": "MS1",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName1",
 "lastName": "LastName1",
 "phoneNumbers": [
  {
   "number": "111-111-1111",
   "type": "work"
  },
  {
   "number": "222-222-2222",
   "type": "home"
  }
 ]
}

{
 "id": 2,
 "addresses": {
  "billing": {
   "city": "BillingTown2",
   "state": "BS2",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown2",
   "state": "MS2",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName2",
 "lastName": "LastName2",
 "phoneNumbers": [
  {
   "number": "333-333-3333",
   "type": "work"
  },
  {
   "number": "444-444-4444",
   "type": "cell"
  }
 ]
}
```

## Perbarui item yang berisi tipe kompleks
<a name="ddb-en-client-adv-features-nested-updates"></a>

Untuk memperbarui item yang berisi tipe kompleks, Anda memiliki dua pendekatan dasar:
+ Pendekatan 1: Pertama ambil item (dengan menggunakan`getItem`), perbarui objek, lalu panggil`DynamoDbTable#updateItem`.
+ Pendekatan 2: Jangan mengambil item, tetapi buat instance baru, atur properti yang ingin Anda perbarui, dan kirimkan instance `DynamoDbTable#updateItem` dengan menyetel nilai yang sesuai dari. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html) Pendekatan ini tidak mengharuskan Anda mengambil item sebelum memperbaruinya.

Contoh yang ditunjukkan di bagian ini menggunakan`Person`,`Address`, dan `PhoneNumber` kelas yang ditunjukkan sebelumnya.

### Perbarui pendekatan 1: ambil, lalu perbarui
<a name="ddb-en-client-adv-features-nested-updates-retreive"></a>

Dengan menggunakan pendekatan ini, Anda memastikan bahwa tidak ada data yang hilang pada pembaruan. DynamoDB Enhanced Client API membuat ulang bean dengan atribut dari item yang disimpan di DynamoDB termasuk nilai tipe kompleks. Anda kemudian perlu menggunakan getter dan setter untuk memperbarui kacang. Kelemahan dari pendekatan ini adalah biaya yang Anda keluarkan untuk mengambil item terlebih dahulu.

Contoh berikut menunjukkan bahwa tidak ada data yang hilang jika Anda pertama kali mengambil item sebelum memperbaruinya.

```
    public void retrieveThenUpdateExample()  {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        person.setFirstName("FirstName");
        person.setLastName("LastName");

        Address mainAddress = new Address();
        mainAddress.setStreet("123 MyStreet");
        mainAddress.setCity("MyCity");
        mainAddress.setState("MyState");
        mainAddress.setZipCode("MyZipCode");
        person.setMainAddress(mainAddress);

        PhoneNumber homePhone = new PhoneNumber();
        homePhone.setNumber("1111111");
        homePhone.setType("HOME");
        person.setPhoneNumbers(List.of(homePhone));

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.
        // First, retrieve the item
        Person retrievedPerson = personDynamoDbTable.getItem(Key.builder().partitionValue(1).build());

        // Make any updates.
        retrievedPerson.getMainAddress().setCity("YourCity");

        // Save the updated bean. 'updateItem' returns the bean as it appears after the update.
        Person updatedPerson = personDynamoDbTable.updateItem(retrievedPerson);

        // Verify for this example.
        Address updatedMainAddress = updatedPerson.getMainAddress();
        assert updatedMainAddress.getCity().equals("YourCity");
        assert updatedMainAddress.getState().equals("MyState"); // Unchanged.
        // The list of phone numbers remains; it was not set to null;
        assert updatedPerson.getPhoneNumbers().size() == 1;
    }
```

### Pendekatan pembaruan 2: Gunakan `IgnoreNullsMode` enum tanpa mengambil item terlebih dahulu
<a name="ddb-en-client-adv-features-nested-updates-nullmode"></a>

Untuk memperbarui item di DynamoDB, Anda dapat memberikan objek baru yang hanya memiliki properti yang ingin diperbarui dan membiarkan nilai lainnya sebagai null. Dengan pendekatan ini, Anda perlu mengetahui bagaimana nilai nol dalam objek diperlakukan oleh SDK dan bagaimana Anda dapat mengontrol perilaku.

Untuk menentukan properti bernilai nol mana yang ingin diabaikan oleh SDK, berikan `IgnoreNullsMode` enum saat Anda membuat. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/UpdateItemEnhancedRequest.Builder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/UpdateItemEnhancedRequest.Builder.html) Sebagai contoh menggunakan salah satu nilai yang disebutkan, cuplikan berikut menggunakan mode. `IgnoreNullsMode.SCALAR_ONLY`

```
// Create a new Person object to update the existing item in DynamoDB.
Person personForUpdate = new Person();
personForUpdate.setId(1);
personForUpdate.setFirstName("updatedFirstName");  // 'firstName' is a top scalar property.

Address addressForUpdate = new Address();
addressForUpdate.setCity("updatedCity");
personForUpdate.setMainAddress(addressForUpdate);

personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY));

/* With IgnoreNullsMode.SCALAR_ONLY provided, The SDK ignores all null properties. The SDK adds or replaces
the 'firstName' property with the provided value, "updatedFirstName". The SDK updates the 'city' value of
'mainAddress', as long as the 'mainAddress' attribute already exists in DynamoDB.

In the background, the SDK generates an update expression that it sends in the request to DynamoDB.
The following JSON object is a simplified version of what it sends. Notice that the SDK includes the paths
to 'mainAddress.city' and 'firstName' in the SET clause of the update expression. No null values in
'personForUpdate' are included.

{
  "TableName": "PersonTable",
  "Key": {
    "id": {
      "N": "1"
    }
  },
  "ReturnValues": "ALL_NEW",
  "UpdateExpression": "SET #mainAddress.#city = :mainAddress_city, #firstName = :firstName",
  "ExpressionAttributeNames": {
    "#city": "city",
    "#firstName": "firstName",
    "#mainAddress": "mainAddress"
  },
  "ExpressionAttributeValues": {
    ":firstName": {
      "S": "updatedFirstName"
    },
    ":mainAddress_city": {
      "S": "updatedCity"
    }
  }
}

Had we chosen 'IgnoreNullsMode.DEFAULT' instead of 'IgnoreNullsMode.SCALAR_ONLY', the SDK would have included
null values in the "ExpressionAttributeValues" section of the request as shown in the following snippet.

  "ExpressionAttributeValues": {
    ":mainAddress": {
      "M": {
        "zipCode": {
          "NULL": true
        },
        "city": {
          "S": "updatedCity"
        },
        "street": {
          "NULL": true
        },
        "state": {
          "NULL": true
        }
      }
    },
    ":firstName": {
      "S": "updatedFirstName"
    }
  }
*/
```

[Panduan Pengembang Amazon DynamoDB berisi informasi lebih lanjut tentang ekspresi pembaruan.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html)

#### Deskripsi opsi `IgnoreNullsMode`
<a name="ignore-nulls-mode-descriptions"></a>
+ `IgnoreNullsMode.SCALAR_ONLY`- Gunakan pengaturan ini untuk memperbarui atribut skalar di tingkat manapun. SDK membuat pernyataan pembaruan yang hanya mengirimkan atribut skalar non-null ke DynamoDB. SDK mengabaikan atribut skalar bernilai nol dari kacang atau peta, mempertahankan nilai yang disimpan di DynamoDB.

  Saat Anda memperbarui atribut skalar map atau bean, peta harus sudah ada di DynamoDB. Jika Anda menambahkan peta atau kacang ke objek yang belum ada untuk objek di DynamoDB, Anda mendapatkan dengan *pesan Jalur dokumen `DynamoDbException` yang disediakan dalam ekspresi pembaruan tidak valid untuk pembaruan*. Anda harus menggunakan `MAPS_ONLY` mode untuk menambahkan kacang atau peta ke DynamoDB sebelum Anda memperbarui salah satu atributnya.
+ `IgnoreNullsMode.MAPS_ONLY`- Gunakan pengaturan ini untuk menambah atau mengganti properti yang merupakan kacang atau peta. SDK menggantikan atau menambahkan peta atau kacang apa pun yang disediakan dalam objek. Setiap kacang atau peta yang null dalam objek diabaikan, mempertahankan peta yang ada di DynamoDB.
+ `IgnoreNullsMode.DEFAULT`- Dengan pengaturan ini, SDK tidak pernah mengabaikan nilai null. Atribut skalar pada tingkat manapun yang null diperbarui ke null. SDK memperbarui properti bean, map, list, atau set bernilai nol dalam objek ke null di DynamoDB. Saat Anda menggunakan mode ini—atau tidak menyediakan mode karena ini adalah mode default—Anda harus mengambil item terlebih dahulu sehingga nilai di DynamoDB tidak disetel ke null yang disediakan dalam objek untuk diperbarui, kecuali niat Anda adalah untuk mengatur nilai ke null.

Dalam semua mode, jika Anda memberikan objek `updateItem` yang memiliki daftar atau set non-null, daftar atau set disimpan ke DynamoDB. 

#### Mengapa mode?
<a name="ddb-en-client-adv-features-nested-updates-nullmodes-why"></a>

Saat Anda memberikan objek dengan kacang atau peta ke `updateItem` metode, SDK tidak dapat mengetahui apakah objek tersebut harus menggunakan nilai properti dalam kacang (atau nilai entri di peta) untuk memperbarui item, atau apakah keseluruhan bean/map harus menggantikan apa yang telah disimpan ke DynamoDB.

Bekerja dari contoh sebelumnya yang menunjukkan pengambilan item terlebih dahulu, mari kita coba memperbarui `city` atribut `mainAddress` tanpa pengambilan.

```
/* The retrieval example saved the Person object with a 'mainAddress' property whose 'city' property value is "MyCity".
/* Note that we create a new Person with only the necessary information to update the city value
of the mainAddress. */
Person personForUpdate = new Person();
personForUpdate.setId(1);
// The update we want to make changes the city.
Address mainAddressForUpdate = new Address();
mainAddressForUpdate.setCity("YourCity");
personForUpdate.setMainAddress(mainAddressForUpdate);

// Lets' try the following:
Person updatedPerson = personDynamoDbTable.updateItem(personForUpdate);
/*
 Since we haven't retrieved the item, we don't know if the 'mainAddress' property
 already exists, so what update expression should the SDK generate?

A) Should it replace or add the 'mainAddress' with the provided object (setting all attributes to null other than city)
   as shown in the following simplified JSON?

      {
        "TableName": "PersonTable",
        "Key": {
          "id": {
            "N": "1"
          }
        },
        "ReturnValues": "ALL_NEW",
        "UpdateExpression": "SET #mainAddress = :mainAddress",
        "ExpressionAttributeNames": {
          "#mainAddress": "mainAddress"
        },
        "ExpressionAttributeValues": {
          ":mainAddress": {
            "M": {
              "zipCode": {
                "NULL": true
              },
              "city": {
                "S": "YourCity"
              },
              "street": {
                "NULL": true
              },
              "state": {
                "NULL": true
              }
            }
          }
        }
      }
 
B) Or should it update only the 'city' attribute of an existing 'mainAddress' as shown in the following simplified JSON?

      {
        "TableName": "PersonTable",
        "Key": {
          "id": {
            "N": "1"
          }
        },
        "ReturnValues": "ALL_NEW",
        "UpdateExpression": "SET #mainAddress.#city = :mainAddress_city",
        "ExpressionAttributeNames": {
          "#city": "city",
          "#mainAddress": "mainAddress"
        },
        "ExpressionAttributeValues": {
          ":mainAddress_city": {
            "S": "YourCity"
          }
        }
      }

However, assume that we don't know if the 'mainAddress' already exists. If it doesn't exist, the SDK would try to update 
an attribute of a non-existent map, which results in an exception.

In this particular case, we would likely select option B (SCALAR_ONLY) to retain the other values of the 'mainAddress'.
*/
```

Dua contoh berikut menunjukkan penggunaan nilai `MAPS_ONLY` dan `SCALAR_ONLY` enumerasi. `MAPS_ONLY`menambahkan peta dan `SCALAR_ONLY` memperbarui peta.

##### Contoh `IgnoreNullsMode.MAPS_ONLY`
<a name="scalar-only-example"></a>

```
    public void mapsOnlyModeExample() {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        person.setFirstName("FirstName");

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.

        /* Note that we create a new Person with only the necessary information to update the city value
        of the mainAddress. */
        Person personForUpdate = new Person();
        personForUpdate.setId(1);
        // The update we want to make changes the city.
        Address mainAddressForUpdate = new Address();
        mainAddressForUpdate.setCity("YourCity");
        personForUpdate.setMainAddress(mainAddressForUpdate);


        Person updatedPerson = personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.MAPS_ONLY)); // Since the mainAddress property does not exist, use MAPS_ONLY mode.
        assert updatedPerson.getMainAddress().getCity().equals("YourCity");
        assert updatedPerson.getMainAddress().getState() == null;
    }
```

##### `IgnoreNullsMode.SCALAR_ONLY example`
<a name="maps-only-example"></a>

```
    public void scalarOnlyExample() {
        // Assume that we ran this code yesterday.
        Person person = new Person();
        person.setId(1);
        Address mainAddress = new Address();
        mainAddress.setCity("MyCity");
        mainAddress.setState("MyState");
        person.setMainAddress(mainAddress);

        personDynamoDbTable.putItem(person);

        // Assume that we are running this code now.

        /* Note that we create a new Person with only the necessary information to update the city value
        of the mainAddress. */
        Person personForUpdate = new Person();
        personForUpdate.setId(1);
        // The update we want to make changes the city.
        Address mainAddressForUpdate = new Address();
        mainAddressForUpdate.setCity("YourCity");
        personForUpdate.setMainAddress(mainAddressForUpdate);

        Person updatedPerson = personDynamoDbTable.updateItem(r -> r
                .item(personForUpdate)
                .ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY)); // SCALAR_ONLY mode ignores null properties in the in mainAddress.
        assert updatedPerson.getMainAddress().getCity().equals("YourCity");
        assert updatedPerson.getMainAddress().getState().equals("MyState"); // The state property remains the same.
    }
```

Lihat tabel berikut untuk melihat nilai null mana yang diabaikan untuk setiap mode. Anda sering dapat bekerja dengan salah satu `SCALAR_ONLY` dan `MAPS_ONLY` kecuali ketika Anda bekerja dengan kacang atau peta.


**Properti bernilai nol mana dalam objek yang dikirimkan yang diabaikan SDK untuk `updateItem` setiap mode?**  

| Jenis properti | dalam mode SCALAR\$1ONLY | dalam mode MAPS\$1ONLY | dalam mode DEFAULT | 
| --- | --- | --- | --- | 
| Skalar teratas | Ya | Ya | Tidak | 
| Kacang atau peta | Ya | Ya | Tidak | 
| Nilai skalar entri kacang atau peta | Ya1 | Tidak 2 | Tidak | 
| Daftar atau set | Ya | Ya | Tidak | 

1 Ini mengasumsikan peta sudah ada di DynamoDB. Nilai skalar apa pun—null atau bukan null—dari kacang atau peta yang Anda berikan di objek untuk pembaruan mengharuskan jalur ke nilai ada di DynamoDB. SDK membuat jalur ke atribut dengan menggunakan operator `. (dot)` dereference sebelum mengirimkan permintaan.

2 Karena Anda menggunakan `MAPS_ONLY` mode untuk sepenuhnya mengganti atau menambahkan kacang atau peta, semua nilai nol dalam kacang atau peta dipertahankan di peta yang disimpan ke DynamoDB.

# Pertahankan benda kosong dengan `@DynamoDbPreserveEmptyObject`
<a name="ddb-en-client-adv-features-empty"></a>

Jika Anda menyimpan kacang ke Amazon DynamoDB dengan objek kosong dan Anda ingin SDK membuat ulang objek kosong saat pengambilan, beri anotasi pengambil kacang bagian dalam dengan. `@DynamoDbPreserveEmptyObject`

Untuk mengilustrasikan cara kerja anotasi, contoh kode menggunakan dua kacang berikut.

## Contoh kacang
<a name="ddb-en-client-adv-features-empty-ex1"></a>

Kelas data berikut berisi dua `InnerBean` bidang. Metode getter,`getInnerBeanWithoutAnno()`, tidak dijelaskan dengan. `@DynamoDbPreserveEmptyObject` `getInnerBeanWithAnno()`Metode ini dijelaskan.

```
@DynamoDbBean
public class MyBean {

    private String id;
    private String name;
    private InnerBean innerBeanWithoutAnno;
    private InnerBean innerBeanWithAnno;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public InnerBean getInnerBeanWithoutAnno() { return innerBeanWithoutAnno; }
    public void setInnerBeanWithoutAnno(InnerBean innerBeanWithoutAnno) { this.innerBeanWithoutAnno = innerBeanWithoutAnno; }

    @DynamoDbPreserveEmptyObject
    public InnerBean getInnerBeanWithAnno() { return innerBeanWithAnno; }
    public void setInnerBeanWithAnno(InnerBean innerBeanWithAnno) { this.innerBeanWithAnno = innerBeanWithAnno; }

    @Override
    public String toString() {
        return new StringJoiner(", ", MyBean.class.getSimpleName() + "[", "]")
                .add("innerBeanWithoutAnno=" + innerBeanWithoutAnno)
                .add("innerBeanWithAnno=" + innerBeanWithAnno)
                .add("id='" + id + "'")
                .add("name='" + name + "'")
                .toString();
    }
}
```

Contoh dari `InnerBean` kelas berikut adalah bidang `MyBean` dan diinisialisasi sebagai objek kosong dalam kode contoh.

```
@DynamoDbBean
public class InnerBean {

    private String innerBeanField;

    public String getInnerBeanField() {
        return innerBeanField;
    }

    public void setInnerBeanField(String innerBeanField) {
        this.innerBeanField = innerBeanField;
    }

    @Override
    public String toString() {
        return "InnerBean{" +
                "innerBeanField='" + innerBeanField + '\'' +
                '}';
    }
}
```

Contoh kode berikut menyimpan `MyBean` objek dengan kacang dalam yang diinisialisasi ke DynamoDB dan kemudian mengambil item tersebut. Output yang dicatat menunjukkan bahwa tidak `innerBeanWithoutAnno` diinisialisasi, tetapi `innerBeanWithAnno` telah dibuat.

```
    public MyBean preserveEmptyObjectAnnoUsingGetItemExample(DynamoDbTable<MyBean> myBeanTable) {
        // Save an item to DynamoDB.
        MyBean bean = new MyBean();
        bean.setId("1");
        bean.setInnerBeanWithoutAnno(new InnerBean());   // Instantiate the inner bean.
        bean.setInnerBeanWithAnno(new InnerBean());      // Instantiate the inner bean.
        myBeanTable.putItem(bean);

        GetItemEnhancedRequest request = GetItemEnhancedRequest.builder()
                .key(Key.builder().partitionValue("1").build())
                .build();
        MyBean myBean = myBeanTable.getItem(request);

        logger.info(myBean.toString());
        // Output 'MyBean[innerBeanWithoutAnno=null, innerBeanWithAnno=InnerBean{innerBeanField='null'}, id='1', name='null']'.

        return myBean;
    }
```

## Skema statis alternatif
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Anda dapat menggunakan `StaticTableSchema` versi skema tabel berikut sebagai pengganti anotasi pada kacang.

```
    public static TableSchema<MyBean> buildStaticSchemas() {

        StaticTableSchema<InnerBean> innerBeanStaticTableSchema =
                StaticTableSchema.builder(InnerBean.class)
                        .newItemSupplier(InnerBean::new)
                        .addAttribute(String.class, a -> a.name("innerBeanField")
                                .getter(InnerBean::getInnerBeanField)
                                .setter(InnerBean::setInnerBeanField))
                        .build();

        return StaticTableSchema.builder(MyBean.class)
                .newItemSupplier(MyBean::new)
                .addAttribute(String.class, a -> a.name("id")
                        .getter(MyBean::getId)
                        .setter(MyBean::setId)
                        .addTag(primaryPartitionKey()))
                .addAttribute(String.class, a -> a.name("name")
                        .getter(MyBean::getName)
                        .setter(MyBean::setName))
                .addAttribute(EnhancedType.documentOf(InnerBean.class,
                                innerBeanStaticTableSchema),
                        a -> a.name("innerBean1")
                                .getter(MyBean::getInnerBeanWithoutAnno)
                                .setter(MyBean::setInnerBeanWithoutAnno))
                .addAttribute(EnhancedType.documentOf(InnerBean.class,
                                innerBeanStaticTableSchema,
                                b -> b.preserveEmptyObject(true)),
                        a -> a.name("innerBean2")
                                .getter(MyBean::getInnerBeanWithAnno)
                                .setter(MyBean::setInnerBeanWithAnno))
                .build();
    }
```

# Hindari menyimpan atribut null dari objek bersarang
<a name="ddb-en-client-adv-features-ignore-null"></a>

Anda dapat melewati atribut null dari objek bersarang saat menyimpan objek kelas data ke DynamoDB dengan menerapkan anotasi. `@DynamoDbIgnoreNulls` Sebaliknya, atribut tingkat atas dengan nilai null tidak pernah disimpan ke database.

Untuk mengilustrasikan cara kerja anotasi, contoh kode menggunakan dua kacang berikut.

## Contoh kacang
<a name="ddb-en-client-adv-features-ignore-null-ex1"></a>

Kelas data berikut berisi dua `InnerBean` bidang. Metode getter,`getInnerBeanWithoutAnno()`, tidak dijelaskan. `getInnerBeanWithIgnoreNullsAnno()`Metode ini dianotasi dengan. `@DynamoDbIgnoreNulls`

```
@DynamoDbBean
public class MyBean {

    private String id;
    private String name;
    private InnerBean innerBeanWithoutAnno;
    private InnerBean innerBeanWithIgnoreNullsAnno;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public InnerBean getInnerBeanWithoutAnno() { return innerBeanWithoutAnno; }
    public void setInnerBeanWithoutAnno(InnerBean innerBeanWithoutAnno) { this.innerBeanWithoutAnno = innerBeanWithoutAnno; }

    @DynamoDbIgnoreNulls
    public InnerBean getInnerBeanWithIgnoreNullsAnno() { return innerBeanWithIgnoreNullsAnno; }
    public void setInnerBeanWithIgnoreNullsAnno(InnerBean innerBeanWithAnno) { this.innerBeanWithIgnoreNullsAnno = innerBeanWithAnno; }

    @Override
    public String toString() {
        return new StringJoiner(", ", MyBean.class.getSimpleName() + "[", "]")
                .add("innerBeanWithoutAnno=" + innerBeanWithoutAnno)
                .add("innerBeanWithIgnoreNullsAnno=" + innerBeanWithIgnoreNullsAnno)
                .add("id='" + id + "'")
                .add("name='" + name + "'")
                .toString();
    }
}
```

Contoh dari `InnerBean` kelas berikut adalah bidang `MyBean` dan digunakan dalam kode contoh berikut.

```
@DynamoDbBean
public class InnerBean {

    private String innerBeanFieldString;
    private Integer innerBeanFieldInteger;

    public String getInnerBeanFieldString() { return innerBeanFieldString; }
    public void setInnerBeanFieldString(String innerBeanFieldString) { this.innerBeanFieldString = innerBeanFieldString; }

    public Integer getInnerBeanFieldInteger() { return innerBeanFieldInteger; }
    public void setInnerBeanFieldInteger(Integer innerBeanFieldInteger) { this.innerBeanFieldInteger = innerBeanFieldInteger; }

    @Override
    public String toString() {
        return new StringJoiner(", ", InnerBean.class.getSimpleName() + "[", "]")
                .add("innerBeanFieldString='" + innerBeanFieldString + "'")
                .add("innerBeanFieldInteger=" + innerBeanFieldInteger)
                .toString();
    }
}
```

Contoh kode berikut menciptakan `InnerBean` objek dan menetapkan hanya satu dari dua atribut dengan nilai. 

```
    public void ignoreNullsAnnoUsingPutItemExample(DynamoDbTable<MyBean> myBeanTable) {
        // Create an InnerBean object and give only one attribute a value.
        InnerBean innerBeanOneAttributeSet = new InnerBean();
        innerBeanOneAttributeSet.setInnerBeanFieldInteger(200);

        // Create a MyBean instance and use the same InnerBean instance both for attributes.
        MyBean bean = new MyBean();
        bean.setId("1");
        bean.setInnerBeanWithoutAnno(innerBeanOneAttributeSet);
        bean.setInnerBeanWithIgnoreNullsAnno(innerBeanOneAttributeSet);

        Map<String, AttributeValue> itemMap = myBeanTable.tableSchema().itemToMap(bean, true);
        logger.info(itemMap.toString());
        // Log the map that is sent to the database.
        // {innerBeanWithIgnoreNullsAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200)}), id=AttributeValue(S=1), innerBeanWithoutAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200), innerBeanFieldString=AttributeValue(NUL=true)})}
        
        // Save the MyBean object to the table.
        myBeanTable.putItem(bean);
    }
```

Untuk memvisualisasikan data tingkat rendah yang dikirim ke DynamoDB, kode mencatat peta atribut sebelum menyimpan objek. `MyBean`

Output yang dicatat menunjukkan bahwa `innerBeanWithIgnoreNullsAnno` output satu atribut,

```
innerBeanWithIgnoreNullsAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200)})
```

`innerBeanWithoutAnno`Instance menghasilkan dua atribut. Satu atribut memiliki nilai 200 dan yang lainnya adalah atribut bernilai nol.

```
innerBeanWithoutAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200), innerBeanFieldString=AttributeValue(NUL=true)})
```

## Representasi JSON dari peta atribut
<a name="ddb-en-client-adv-features-ignore-null-ex2"></a>

Representasi JSON berikut membuatnya lebih mudah untuk melihat data yang disimpan ke DynamoDB.

```
{
  "id": {
    "S": "1"
  },
  "innerBeanWithIgnoreNullsAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      }
    }
  },
  "innerBeanWithoutAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      },
      "innerBeanFieldString": {
        "NULL": true
      }
    }
  }
}
```

## Skema statis alternatif
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Anda dapat menggunakan `StaticTableSchema` versi berikut dari skema tabel di tempat anotasi kelas data.

```
public static TableSchema<MyBean> buildStaticSchemas() {

    StaticTableSchema<InnerBean> innerBeanStaticTableSchema =
        StaticTableSchema.builder(InnerBean.class)
            .newItemSupplier(InnerBean::new)
            .addAttribute(String.class, a -> a.name("innerBeanFieldString")
                .getter(InnerBean::getInnerBeanFieldString)
                .setter(InnerBean::setInnerBeanFieldString))
            .addAttribute(Integer.class, a -> a.name("innerBeanFieldInteger")
                .getter(InnerBean::getInnerBeanFieldInteger)
                .setter(InnerBean::setInnerBeanFieldInteger))
            .build();

    return StaticTableSchema.builder(MyBean.class)
        .newItemSupplier(MyBean::new)
        .addAttribute(String.class, a -> a.name("id")
            .getter(MyBean::getId)
            .setter(MyBean::setId)
            .addTag(primaryPartitionKey()))
        .addAttribute(String.class, a -> a.name("name")
            .getter(MyBean::getName)
            .setter(MyBean::setName))
        .addAttribute(EnhancedType.documentOf(InnerBean.class,
                innerBeanStaticTableSchema),
            a -> a.name("innerBeanWithoutAnno")
                .getter(MyBean::getInnerBeanWithoutAnno)
                .setter(MyBean::setInnerBeanWithoutAnno))
        .addAttribute(EnhancedType.documentOf(InnerBean.class,
                innerBeanStaticTableSchema,
                b -> b.ignoreNulls(true)),
            a -> a.name("innerBeanWithIgnoreNullsAnno")
                .getter(MyBean::getInnerBeanWithIgnoreNullsAnno)
                .setter(MyBean::setInnerBeanWithIgnoreNullsAnno))
        .build();
}
```

# Bekerja dengan dokumen JSON dengan Enhanced Document API untuk DynamoDB
<a name="ddb-en-client-doc-api"></a>

[Enhanced Document API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) for AWS SDK for Java 2.x dirancang untuk bekerja dengan data berorientasi dokumen yang tidak memiliki skema tetap. Namun, ini juga memungkinkan Anda menggunakan kelas khusus untuk memetakan atribut individual.

 Enhanced Document API adalah penerus [Document API](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/DynamoDB.html) dari AWS SDK untuk Java v1.x.

**Contents**
+ [Mulai menggunakan Enhanced Document API](ddb-en-client-doc-api-steps.md)
  + [Buat `DocumentTableSchema` dan a `DynamoDbTable`](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema)
+ [Membangun dokumen yang disempurnakan](ddb-en-client-doc-api-steps-create-ed.md)
  + [Membangun dari string JSON](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromJson)
  + [Membangun dari elemen individu](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts)
+ [Lakukan operasi CRUD](ddb-en-client-doc-api-steps-use.md)
+ [Akses atribut dokumen yang disempurnakan sebagai objek khusus](ddb-en-client-doc-api-convert.md)
+ [Gunakan `EnhancedDocument` tanpa DynamoDB](ddb-en-client-doc-api-standalone.md)

# Mulai menggunakan Enhanced Document API
<a name="ddb-en-client-doc-api-steps"></a>

Enhanced Document API memerlukan [dependensi](ddb-en-client-getting-started.md#ddb-en-client-gs-dep) yang sama yang diperlukan untuk DynamoDB Enhanced Client API. Ini juga membutuhkan [`DynamoDbEnhancedClient`contoh](ddb-en-client-getting-started-dynamodbTable.md#ddb-en-client-getting-started-dynamodbTable-eclient) seperti yang ditunjukkan di awal topik ini.

Karena API Dokumen yang Ditingkatkan dirilis dengan versi 2.20.3 AWS SDK for Java 2.x, Anda memerlukan versi itu atau lebih tinggi.

## Buat `DocumentTableSchema` dan a `DynamoDbTable`
<a name="ddb-en-client-doc-api-steps-createschema"></a>

Untuk menjalankan perintah terhadap tabel DynamoDB menggunakan Enhanced Document API, kaitkan tabel dengan objek resource < > sisi [DynamoDbTableklien EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html). 

`table()`Metode klien yang disempurnakan membuat `DynamoDbTable<EnhancedDocument>` instance dan membutuhkan parameter untuk nama tabel DynamoDB dan a. `DocumentTableSchema` 

Pembangun untuk a [DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)memerlukan kunci indeks utama dan satu atau lebih penyedia konverter atribut. `AttributeConverterProvider.defaultProvider()`Metode ini menyediakan konverter untuk [tipe default](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/package-summary.html). Itu harus ditentukan bahkan jika Anda menyediakan penyedia konverter atribut khusus. Anda dapat menambahkan kunci indeks sekunder opsional ke pembangun.

Cuplikan kode berikut menunjukkan kode yang menghasilkan representasi sisi klien dari tabel DynamoDB yang menyimpan objek tanpa skema. `person` `EnhancedDocument`

```
DynamoDbTable<EnhancedDocument> documentDynamoDbTable = 
                enhancedClient.table("person",
                        TableSchema.documentSchemaBuilder()
                            // Specify the primary key attributes.
                            .addIndexPartitionKey(TableMetadata.primaryIndexName(),"id", AttributeValueType.S)
                            .addIndexSortKey(TableMetadata.primaryIndexName(), "lastName", AttributeValueType.S)
                            // Specify attribute converter providers. Minimally add the default one.
                            .attributeConverterProviders(AttributeConverterProvider.defaultProvider())
                            .build());
                                                         
// Call documentTable.createTable() if "person" does not exist in DynamoDB.
// createTable() should be called only one time.
```

Berikut ini menunjukkan representasi JSON dari `person` objek yang digunakan di seluruh bagian ini.

### Objek JSON `person`
<a name="ddb-en-client-doc-api-steps-createschema-obj"></a>

```
{
  "id": 1,
  "firstName": "Richard",
  "lastName": "Roe",
  "age": 25,
  "addresses":
    {
      "home": {
        "zipCode": "00000",
        "city": "Any Town",
        "state": "FL",
        "street": "123 Any Street"
      },
      "work": {
        "zipCode": "00001",
        "city": "Anywhere",
        "state": "FL",
        "street": "100 Main Street"
      }
    },
  "hobbies": [
    "Hobby 1",
    "Hobby 2"
  ],
  "phoneNumbers": [
    {
      "type": "Home",
      "number": "555-0100"
    },
    {
      "type": "Work",
      "number": "555-0119"
    }
  ]
}
```

# Membangun dokumen yang disempurnakan
<a name="ddb-en-client-doc-api-steps-create-ed"></a>

An `[EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html)` merupakan objek tipe dokumen yang memiliki struktur kompleks dengan atribut bersarang. Sebuah `EnhancedDocument` membutuhkan atribut tingkat atas yang cocok dengan atribut kunci utama yang ditentukan untuk atribut. `DocumentTableSchema` Konten yang tersisa bersifat arbitrer dan dapat terdiri dari atribut tingkat atas dan juga atribut yang sangat bersarang.

Anda membuat `EnhancedDocument` instance dengan menggunakan builder yang menyediakan beberapa cara untuk menambahkan elemen.

## Membangun dari string JSON
<a name="ddb-en-client-doc-api-steps-create-ed-fromJson"></a>

Dengan string JSON, Anda dapat membangun panggilan `EnhancedDocument` dalam satu metode. Cuplikan berikut membuat `EnhancedDocument` dari string JSON dikembalikan oleh metode helper. `jsonPerson()` `jsonPerson()`Metode mengembalikan versi string JSON dari [objek orang](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema-obj) yang ditunjukkan sebelumnya.

```
EnhancedDocument document = 
        EnhancedDocument.builder()
                        .json( jsonPerson() )
                        .build());
```

## Membangun dari elemen individu
<a name="ddb-en-client-doc-api-steps-create-ed-fromparts"></a>

Atau, Anda dapat membangun sebuah `EnhancedDocument` instance dari komponen individual menggunakan metode type-safe dari builder.

Contoh berikut membangun dokumen yang `person` disempurnakan mirip dengan dokumen yang disempurnakan yang dibangun dari string JSON pada contoh sebelumnya.

```
        /* Define the shape of an address map whose JSON representation looks like the following.
           Use 'addressMapEnhancedType' in the following EnhancedDocument.builder() to simplify the code.
           "home": {
             "zipCode": "00000",
             "city": "Any Town",
             "state": "FL",
             "street": "123 Any Street"
           }*/
        EnhancedType<Map<String, String>> addressMapEnhancedType =
                EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(String.class));


        //  Use the builder's typesafe methods to add elements to the enhanced document.
        EnhancedDocument personDocument = EnhancedDocument.builder()
                .putNumber("id", 50)
                .putString("firstName", "Shirley")
                .putString("lastName", "Rodriguez")
                .putNumber("age", 53)
                .putNull("nullAttribute")
                .putJson("phoneNumbers", phoneNumbersJSONString())
                /* Add the map of addresses whose JSON representation looks like the following.
                        {
                          "home": {
                            "zipCode": "00000",
                            "city": "Any Town",
                            "state": "FL",
                            "street": "123 Any Street"
                          }
                        } */
                .putMap("addresses", getAddresses(), EnhancedType.of(String.class), addressMapEnhancedType)
                .putList("hobbies", List.of("Theater", "Golf"), EnhancedType.of(String.class))
                .build();
```

### Metode pembantu
<a name="ddb-en-client-doc-api-steps-use-fromparts-helpers"></a>

```
    private static String phoneNumbersJSONString() {
        return "  [" +
                "    {" +
                "      \"type\": \"Home\"," +
                "      \"number\": \"555-0140\"" +
                "    }," +
                "    {" +
                "      \"type\": \"Work\"," +
                "      \"number\": \"555-0155\"" +
                "    }" +
                "  ]";
    }

    private static Map<String, Map<String, String>> getAddresses() {
        return Map.of(
                "home", Map.of(
                        "zipCode", "00002",
                        "city", "Any Town",
                        "state", "ME",
                        "street", "123 Any Street"));

    }
```

# Lakukan operasi CRUD
<a name="ddb-en-client-doc-api-steps-use"></a>

Setelah Anda mendefinisikan sebuah `EnhancedDocument` instance, Anda dapat menyimpannya ke tabel DynamoDB. Cuplikan kode berikut menggunakan [personDocument](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts) yang dibuat dari elemen individual.

```
documentDynamoDbTable.putItem(personDocument);
```

Setelah Anda membaca instance dokumen yang disempurnakan dari DynamoDB, Anda dapat mengekstrak nilai atribut individual menggunakan getter seperti yang ditunjukkan dalam cuplikan kode berikut yang mengakses data yang disimpan dari. `personDocument` Atau, Anda dapat mengekstrak konten lengkap ke string JSON seperti yang ditunjukkan pada bagian terakhir dari kode contoh.

```
        // Read the item.
        EnhancedDocument personDocFromDb = documentDynamoDbTable.getItem(Key.builder().partitionValue(50).build());

        // Access top-level attributes.
        logger.info("Name: {} {}", personDocFromDb.getString("firstName"), personDocFromDb.getString("lastName"));
        // Name: Shirley Rodriguez

        // Typesafe access of a deeply nested attribute. The addressMapEnhancedType shown previously defines the shape of an addresses map.
        Map<String, Map<String, String>> addresses = personDocFromDb.getMap("addresses", EnhancedType.of(String.class), addressMapEnhancedType);
        addresses.keySet().forEach(k -> logger.info(addresses.get(k).toString()));
        // {zipCode=00002, city=Any Town, street=123 Any Street, state=ME}

        // Alternatively, work with AttributeValue types checking along the way for deeply nested attributes.
        Map<String, AttributeValue> addressesMap = personDocFromDb.getMapOfUnknownType("addresses");
        addressesMap.keySet().forEach((String k) -> {
            logger.info("Looking at data for [{}] address", k);
            // Looking at data for [home] address
            AttributeValue value = addressesMap.get(k);
            AttributeValue cityValue = value.m().get("city");
            if (cityValue != null) {
                logger.info(cityValue.s());
                // Any Town
            }
        });

        List<AttributeValue> phoneNumbers = personDocFromDb.getListOfUnknownType("phoneNumbers");
        phoneNumbers.forEach((AttributeValue av) -> {
            if (av.hasM()) {
                AttributeValue type = av.m().get("type");
                if (type.s() != null) {
                    logger.info("Type of phone: {}", type.s());
                    // Type of phone: Home
                    // Type of phone: Work
                }
            }
        });

        String jsonPerson = personDocFromDb.toJson();
        logger.info(jsonPerson);
        // {"firstName":"Shirley","lastName":"Rodriguez","addresses":{"home":{"zipCode":"00002","city":"Any Town","street":"123 Any Street","state":"ME"}},"hobbies":["Theater","Golf"],
        //     "id":50,"nullAttribute":null,"age":53,"phoneNumbers":[{"number":"555-0140","type":"Home"},{"number":"555-0155","type":"Work"}]}
```

`EnhancedDocument`instance dapat digunakan dengan metode apa pun dari `[DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)` atau [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)di tempat kelas data yang dipetakan.

# Akses atribut dokumen yang disempurnakan sebagai objek khusus
<a name="ddb-en-client-doc-api-convert"></a>

Selain menyediakan API untuk membaca dan menulis atribut dengan struktur tanpa skema, API Dokumen yang Ditingkatkan memungkinkan Anda mengonversi atribut ke dan dari instance kelas khusus.

Enhanced Document API menggunakan `AttributeConverterProvider` s dan `AttributeConverter` s yang ditampilkan di bagian [konversi atribut kontrol](ddb-en-client-adv-features-conversion.md) sebagai bagian dari DynamoDB Enhanced Client API.

Dalam contoh berikut, kita menggunakan a `CustomAttributeConverterProvider` dengan `AddressConverter` kelas bersarang untuk mengkonversi `Address` objek. 

Contoh ini menunjukkan bahwa Anda dapat mencampur data dari kelas dan juga data dari struktur yang dibangun sesuai kebutuhan. Contoh ini juga menunjukkan bahwa kelas kustom dapat digunakan pada setiap tingkat struktur bersarang. `Address`Objek dalam contoh ini adalah nilai yang digunakan dalam peta.

```
    public static void attributeToAddressClassMappingExample(DynamoDbEnhancedClient enhancedClient, DynamoDbClient standardClient) {
        String tableName = "customer";

        // Define the DynamoDbTable for an enhanced document.
        // The schema builder provides methods for attribute converter providers and keys.
        DynamoDbTable<EnhancedDocument> documentDynamoDbTable = enhancedClient.table(tableName,
                DocumentTableSchema.builder()
                        // Add the CustomAttributeConverterProvider along with the default when you build the table schema.
                        .attributeConverterProviders(
                                List.of(
                                        new CustomAttributeConverterProvider(),
                                        AttributeConverterProvider.defaultProvider()))
                        .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.N)
                        .addIndexSortKey(TableMetadata.primaryIndexName(), "lastName", AttributeValueType.S)
                        .build());
        // Create the DynamoDB table if needed.
        documentDynamoDbTable.createTable();
        waitForTableCreation(tableName, standardClient);


        // The getAddressesForCustomMappingExample() helper method that provides 'addresses' shows the use of a custom Address class
        // rather than using a Map<String, Map<String, String> to hold the address data.
        Map<String, Address> addresses = getAddressesForCustomMappingExample();

        // Build an EnhancedDocument instance to save an item with a mix of structures defined as needed and static classes.
        EnhancedDocument personDocument = EnhancedDocument.builder()
                .putNumber("id", 50)
                .putString("firstName", "Shirley")
                .putString("lastName", "Rodriguez")
                .putNumber("age", 53)
                .putNull("nullAttribute")
                .putJson("phoneNumbers", phoneNumbersJSONString())
                // Note the use of 'EnhancedType.of(Address.class)' instead of the more generic
                // 'EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(String.class))' that was used in a previous example.
                .putMap("addresses", addresses, EnhancedType.of(String.class), EnhancedType.of(Address.class))
                .putList("hobbies", List.of("Hobby 1", "Hobby 2"), EnhancedType.of(String.class))
                .build();
        // Save the item to DynamoDB.
        documentDynamoDbTable.putItem(personDocument);

        // Retrieve the item just saved.
        EnhancedDocument srPerson = documentDynamoDbTable.getItem(Key.builder().partitionValue(50).sortValue("Rodriguez").build());

        // Access the addresses attribute.
        Map<String, Address> srAddresses = srPerson.get("addresses",
                EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.of(Address.class)));

        srAddresses.keySet().forEach(k -> logger.info(addresses.get(k).toString()));

        documentDynamoDbTable.deleteTable();

// The content logged to the console shows that the saved maps were converted to Address instances.
Address{street='123 Main Street', city='Any Town', state='NC', zipCode='00000'}
Address{street='100 Any Street', city='Any Town', state='NC', zipCode='00000'}
```

## `CustomAttributeConverterProvider`kode
<a name="ddb-en-client-doc-api-convert-provider"></a>

```
public class CustomAttributeConverterProvider implements AttributeConverterProvider {

    private final Map<EnhancedType<?>, AttributeConverter<?>> converterCache = ImmutableMap.of(
            // 1. Add AddressConverter to the internal cache.
            EnhancedType.of(Address.class), new AddressConverter());

    public static CustomAttributeConverterProvider create() {
        return new CustomAttributeConverterProvider();
    }

    // 2. The enhanced client queries the provider for attribute converters if it
    //    encounters a type that it does not know how to convert.
    @SuppressWarnings("unchecked")
    @Override
    public <T> AttributeConverter<T> converterFor(EnhancedType<T> enhancedType) {
        return (AttributeConverter<T>) converterCache.get(enhancedType);
    }

    // 3. Custom attribute converter
    private class AddressConverter implements AttributeConverter<Address> {
        // 4. Transform an Address object into a DynamoDB map.
        @Override
        public AttributeValue transformFrom(Address address) {

            Map<String, AttributeValue> attributeValueMap = Map.of(
                    "street", AttributeValue.fromS(address.getStreet()),
                    "city", AttributeValue.fromS(address.getCity()),
                    "state", AttributeValue.fromS(address.getState()),
                    "zipCode", AttributeValue.fromS(address.getZipCode()));

            return AttributeValue.fromM(attributeValueMap);
        }

        // 5. Transform the DynamoDB map attribute to an Address oject.
        @Override
        public Address transformTo(AttributeValue attributeValue) {
            Map<String, AttributeValue> m = attributeValue.m();
            Address address = new Address();
            address.setStreet(m.get("street").s());
            address.setCity(m.get("city").s());
            address.setState(m.get("state").s());
            address.setZipCode(m.get("zipCode").s());

            return address;
        }

        @Override
        public EnhancedType<Address> type() {
            return EnhancedType.of(Address.class);
        }

        @Override
        public AttributeValueType attributeValueType() {
            return AttributeValueType.M;
        }
    }
}
```

## `Address` kelas
<a name="ddb-en-client-doc-api-convert-address"></a>

```
public class Address {
                  private String street;
                  private String city;
                  private String state;
                  private String zipCode;

                  public Address() {
                  }

                  public String getStreet() {
                  return this.street;
                  }

                  public String getCity() {
                  return this.city;
                  }

                  public String getState() {
                  return this.state;
                  }

                  public String getZipCode() {
                  return this.zipCode;
                  }

                  public void setStreet(String street) {
                  this.street = street;
                  }

                  public void setCity(String city) {
                  this.city = city;
                  }

                  public void setState(String state) {
                  this.state = state;
                  }

                  public void setZipCode(String zipCode) {
                  this.zipCode = zipCode;
                  }
                  }
```

## Metode pembantu yang menyediakan alamat
<a name="ddb-en-client-doc-api-convert-helper"></a>

Metode pembantu berikut menyediakan peta yang menggunakan `Address` instance kustom untuk nilai daripada `Map<String, String>` contoh generik untuk nilai.

```
    private static Map<String, Address> getAddressesForCustomMappingExample() {
        Address homeAddress = new Address();
        homeAddress.setStreet("100 Any Street");
        homeAddress.setCity("Any Town");
        homeAddress.setState("NC");
        homeAddress.setZipCode("00000");

        Address workAddress = new Address();
        workAddress.setStreet("123 Main Street");
        workAddress.setCity("Any Town");
        workAddress.setState("NC");
        workAddress.setZipCode("00000");

        return Map.of("home", homeAddress,
                "work", workAddress);
    }
```

# Gunakan `EnhancedDocument` tanpa DynamoDB
<a name="ddb-en-client-doc-api-standalone"></a>

Meskipun Anda biasanya menggunakan instance `EnhancedDocument` untuk membaca dan menulis item DynamoDB tipe dokumen, itu juga dapat digunakan secara independen dari DynamoDB. 

Anda dapat menggunakan kemampuan mereka `EnhancedDocuments` untuk mengkonversi antara string JSON atau objek kustom ke peta tingkat rendah `AttributeValues` seperti yang ditunjukkan dalam contoh berikut.

```
    public static void conversionWithoutDynamoDbExample() {
        Address address = new Address();
        address.setCity("my city");
        address.setState("my state");
        address.setStreet("my street");
        address.setZipCode("00000");

        // Build an EnhancedDocument instance for its conversion functionality alone.
        EnhancedDocument addressEnhancedDoc = EnhancedDocument.builder()
                // Important: You must specify attribute converter providers when you build an EnhancedDocument instance not used with a DynamoDB table.
                .attributeConverterProviders(new CustomAttributeConverterProvider(), DefaultAttributeConverterProvider.create())
                .put("addressDoc", address, Address.class)
                .build();

        // Convert address to a low-level item representation.
        final Map<String, AttributeValue> addressAsAttributeMap = addressEnhancedDoc.getMapOfUnknownType("addressDoc");
        logger.info("addressAsAttributeMap: {}", addressAsAttributeMap.toString());

        // Convert address to a JSON string.
        String addressAsJsonString = addressEnhancedDoc.getJson("addressDoc");
        logger.info("addressAsJsonString: {}", addressAsJsonString);
        // Convert addressEnhancedDoc back to an Address instance.
        Address addressConverted =  addressEnhancedDoc.get("addressDoc", Address.class);
        logger.info("addressConverted: {}", addressConverted.toString());
    }

   /* Console output:
          addressAsAttributeMap: {zipCode=AttributeValue(S=00000), state=AttributeValue(S=my state), street=AttributeValue(S=my street), city=AttributeValue(S=my city)}
          addressAsJsonString: {"zipCode":"00000","state":"my state","street":"my street","city":"my city"}
          addressConverted: Address{street='my street', city='my city', state='my state', zipCode='00000'}
   */
```

**catatan**  
Bila Anda menggunakan dokumen yang disempurnakan independen dari tabel DynamoDB, pastikan Anda secara eksplisit menetapkan penyedia konverter atribut pada pembangun.  
Sebaliknya, skema tabel dokumen memasok penyedia konverter ketika dokumen yang disempurnakan digunakan dengan tabel DynamoDB.

# Gunakan ekstensi untuk menyesuaikan operasi DynamoDB Enhanced Client
<a name="ddb-en-client-extensions"></a>

DynamoDB Enhanced Client API mendukung ekstensi plugin yang menyediakan fungsionalitas di luar operasi pemetaan. Ekstensi menggunakan dua metode hook untuk memodifikasi data selama operasi baca dan tulis:
+ `beforeWrite()`- Memodifikasi operasi tulis sebelum itu terjadi
+ `afterRead()`- Memodifikasi hasil operasi baca setelah itu terjadi

Beberapa operasi (seperti pembaruan item) melakukan penulisan dan kemudian membaca, sehingga kedua metode kait dipanggil.

## Bagaimana ekstensi dimuat
<a name="ddb-en-client-extensions-loading"></a>

Ekstensi dimuat dalam urutan yang Anda tentukan di pembuat klien yang disempurnakan. Urutan pemuatan dapat menjadi penting karena satu ekstensi dapat bertindak berdasarkan nilai yang telah diubah oleh ekstensi sebelumnya.

Secara default, klien yang disempurnakan memuat dua ekstensi:
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Memberikan penguncian optimis
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Secara otomatis menambah atribut penghitung

Anda dapat mengganti perilaku default dengan pembuat klien yang disempurnakan dan memuat ekstensi apa pun. Anda juga dapat menentukan none jika Anda tidak ingin ekstensi default.

**penting**  
Jika Anda memuat ekstensi Anda sendiri, klien yang disempurnakan tidak memuat ekstensi default apa pun. Jika Anda menginginkan perilaku yang disediakan oleh salah satu ekstensi default, Anda perlu menambahkannya secara eksplisit ke daftar ekstensi.

Contoh berikut menunjukkan cara memuat ekstensi kustom yang `verifyChecksumExtension` dinamai`VersionedRecordExtension`. `AtomicCounterExtension`Tidak dimuat dalam contoh ini.

```
DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build();

DynamoDbEnhancedClient enhancedClient = 
    DynamoDbEnhancedClient.builder()
                          .dynamoDbClient(dynamoDbClient)
                          .extensions(versionedRecordExtension, verifyChecksumExtension)
                          .build();
```

## Detail dan konfigurasi ekstensi yang tersedia
<a name="ddb-en-client-extensions-details"></a>

Bagian berikut memberikan informasi rinci tentang setiap ekstensi yang tersedia di SDK.

### Terapkan penguncian optimis dengan `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

`VersionedRecordExtension`Ekstensi ini memberikan penguncian optimis dengan menambah dan melacak nomor versi item saat item ditulis ke database. Kondisi ditambahkan ke setiap penulisan yang menyebabkan penulisan gagal jika nomor versi item tetap yang sebenarnya tidak cocok dengan nilai yang terakhir dibaca aplikasi.

#### Konfigurasi
<a name="ddb-en-client-extensions-VRE-conf"></a>

Untuk menentukan atribut mana yang akan digunakan untuk melacak nomor versi item, beri tag atribut numerik dalam skema tabel.

Cuplikan berikut menentukan bahwa `version` atribut harus menyimpan nomor versi item.

```
    @DynamoDbVersionAttribute
    public Integer getVersion() {...};
    public void setVersion(Integer version) {...};
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
    .addAttribute(Integer.class, a -> a.name("version")
                                       .getter(Customer::getVersion)
                                       .setter(Customer::setVersion)
                                        // Apply the 'version' tag to the attribute.
                                       .tags(VersionedRecordExtension.AttributeTags.versionAttribute())
```

#### Cara kerjanya
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

Penguncian optimis dengan `VersionedRecordExtension` memiliki dampak berikut pada ini `DynamoDbEnhancedClient` dan `DynamoDbTable` metode:

**`putItem`**  
Item baru diberi nilai versi awal 0. Ini dapat dikonfigurasi dengan`@DynamoDbVersionAttribute(startAt = X)`.

**`updateItem`**  
Jika Anda mengambil item, memperbarui satu atau beberapa propertinya, dan mencoba menyimpan perubahan, operasi hanya berhasil jika nomor versi di sisi klien dan sisi server cocok.  
Jika berhasil, nomor versi secara otomatis bertambah 1. Ini dapat dikonfigurasi dengan`@DynamoDbVersionAttribute(incrementBy = X)`.

**`deleteItem`**  
`DynamoDbVersionAttribute`Anotasi tidak berpengaruh. Anda harus menambahkan ekspresi kondisi secara manual saat menghapus item.  
Contoh berikut menambahkan ekspresi bersyarat untuk memastikan bahwa item yang dihapus adalah item yang telah dibaca. Dalam contoh berikut `recordVersion` adalah atribut kacang yang dianotasi dengan. `@DynamoDbVersionAttribute`  

```
// 1. Read the item and get its current version.
Customer item = customerTable.getItem(Key.builder().partitionValue("someId").build());
// `recordVersion` is the bean's attribute that is annotated with `@DynamoDbVersionAttribute`.
AttributeValue currentVersion = item.getRecordVersion();

// 2. Create conditional delete with the `currentVersion` value.
DeleteItemEnhancedRequest deleteItemRequest =
    DeleteItemEnhancedRequest.builder()
       .key(KEY)
       .conditionExpression(Expression.builder()
           .expression("recordVersion = :current_version_value")
           .putExpressionValue(":current_version_value", currentVersion)
           .build()).build();

customerTable.deleteItem(deleteItemRequest);
```

**`transactWriteItems`**  
+ `addPutItem`: Metode ini memiliki perilaku yang sama dengan`putItem`.
+ `addUpdateItem`: Metode ini memiliki perilaku yang sama dengan`updateItem`.
+ `addDeleteItem`: Metode ini memiliki perilaku yang sama dengan`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Metode ini memiliki perilaku yang sama dengan`putItem`.
+ `addDeleteItem`: Metode ini memiliki perilaku yang sama dengan`deleteItem`.

**catatan**  
Tabel global DynamoDB menggunakan rekonsiliasi ['penulis terakhir menang'](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) antara pembaruan bersamaan, di mana DynamoDB melakukan upaya terbaik untuk menentukan penulis terakhir. Jika Anda menggunakan tabel global, kebijakan 'penulis terakhir menang' ini berarti bahwa strategi penguncian mungkin tidak berfungsi seperti yang diharapkan, karena semua replika pada akhirnya akan bertemu berdasarkan penulisan terakhir yang ditentukan oleh DynamoDB. 

#### Cara menonaktifkan
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Untuk menonaktifkan penguncian optimis, jangan gunakan `@DynamoDbVersionAttribute` anotasi.

### Menerapkan penghitung dengan `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

`AtomicCounterExtension`Ekstensi menambah atribut numerik yang ditandai setiap kali catatan ditulis ke database. Anda dapat menentukan nilai awal dan kenaikan. Jika tidak ada nilai yang ditentukan, nilai awal diatur ke 0 dan nilai atribut meningkat sebesar 1.

#### Konfigurasi
<a name="ddb-en-client-extensions-ACE-conf"></a>

Untuk menentukan atribut mana yang merupakan penghitung, beri tag atribut tipe `Long` dalam skema tabel.

Cuplikan berikut menunjukkan penggunaan nilai awal dan kenaikan default untuk atribut. `counter`

```
    @DynamoDbAtomicCounter
    public Long getCounter() {...};
    public void setCounter(Long counter) {...};
```

Pendekatan skema tabel statis ditunjukkan dalam cuplikan berikut. Ekstensi penghitung atom menggunakan nilai awal 10 dan menambah nilai sebesar 5 setiap kali catatan ditulis.

```
    .addAttribute(Integer.class, a -> a.name("counter")
                                       .getter(Customer::getCounter)
                                       .setter(Customer::setCounter)
                                        // Apply the 'atomicCounter' tag to the attribute with start and increment values.
                                       .tags(StaticAttributeTags.atomicCounter(10L, 5L))
```

### Tambahkan stempel waktu dengan `AutoGeneratedTimestampRecordExtension`
<a name="ddb-en-client-extensions-AGTE"></a>

`AutoGeneratedTimestampRecordExtension`Ekstensi secara otomatis memperbarui atribut tipe yang ditandai `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` dengan stempel waktu saat ini setiap kali item berhasil ditulis ke database. Ekstensi ini tidak dimuat secara default.

#### Konfigurasi
<a name="ddb-en-client-extensions-AGTE-conf"></a>

Untuk menentukan atribut mana yang akan diperbarui dengan stempel waktu saat ini, beri tag `Instant` atribut dalam skema tabel.

`lastUpdate`Atribut adalah target perilaku ekstensi dalam cuplikan berikut. Perhatikan persyaratan bahwa atribut harus berupa `Instant` tipe.

```
    @DynamoDbAutoGeneratedTimestampAttribute
    public Instant getLastUpdate() {...}
    public void setLastUpdate(Instant lastUpdate) {...}
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
     .addAttribute(Instant.class, a -> a.name("lastUpdate")
                                        .getter(Customer::getLastUpdate)
                                        .setter(Customer::setLastUpdate)
                                        // Applying the 'autoGeneratedTimestamp' tag to the attribute.
                                        .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())
```

### Hasilkan UUID dengan AutoGeneratedUuidExtension
<a name="ddb-en-client-extensions-AGUE"></a>

`AutoGeneratedUuidExtension`Ekstensi menghasilkan UUID unik (Universally Unique Identifier) untuk atribut ketika catatan baru ditulis ke database. Menggunakan metode Java JDK [UUID.randomUUId ()](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--) dan berlaku untuk atribut tipe. `java.lang.String` Ekstensi ini tidak dimuat secara default.

#### Konfigurasi
<a name="ddb-en-client-extensions-AGUE-conf"></a>

`uniqueId`Atribut adalah target perilaku ekstensi dalam cuplikan berikut.

```
    @AutoGeneratedUuidExtension
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

Pendekatan skema tabel statis setara ditunjukkan dalam cuplikan berikut.

```
     .addAttribute(String.class, a -> a.name("uniqueId")
                                        .getter(Customer::getUniqueId)
                                        .setter(Customer::setUniqueId)
                                        // Applying the 'autoGeneratedUuid' tag to the attribute.
                                        .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())
```

Jika Anda ingin ekstensi mengisi UUID hanya untuk `putItem` metode dan bukan untuk `updateItem` metode, tambahkan anotasi [perilaku pembaruan](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) seperti yang ditunjukkan pada cuplikan berikut.

```
    @AutoGeneratedUuidExtension
    @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

Jika Anda menggunakan pendekatan skema tabel statis, gunakan kode setara berikut.

```
     .addAttribute(String.class, a -> a.name("uniqueId")
                                        .getter(Customer::getUniqueId)
                                        .setter(Customer::setUniqueId)
                                        // Applying the 'autoGeneratedUuid' tag to the attribute.
                                        .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute(),
                                              StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS))
```

# Contoh ekstensi kustom
<a name="ddb-en-client-extensions-custom"></a>

Anda dapat membuat ekstensi khusus dengan mengimplementasikan `DynamoDbEnhancedClientExtension` antarmuka. Kelas ekstensi kustom berikut menunjukkan `beforeWrite()` metode yang menggunakan ekspresi pembaruan untuk mengatur `registrationDate` atribut jika item dalam database belum memilikinya.

```
public final class CustomExtension implements DynamoDbEnhancedClientExtension {

    // 1. In a custom extension, use an UpdateExpression to define what action to take before
    //    an item is updated.
    @Override
    public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) {
        if ( context.operationContext().tableName().equals("Customer")
                && context.operationName().equals(OperationName.UPDATE_ITEM)) {
            return WriteModification.builder()
                    .updateExpression(createUpdateExpression())
                    .build();
        }
        return WriteModification.builder().build();  // Return an "empty" WriteModification instance if the extension should not be applied.
                                                     // In this case, if the code is not updating an item on the Customer table.
    }

    private static UpdateExpression createUpdateExpression() {

        // 2. Use a SetAction, a subclass of UpdateAction, to provide the values in the update.
        SetAction setAction =
                SetAction.builder()
                        .path("registrationDate")
                        .value("if_not_exists(registrationDate, :regValue)")
                        .putExpressionValue(":regValue", AttributeValue.fromS(Instant.now().toString()))
                        .build();
        // 3. Build the UpdateExpression with one or more UpdateAction.
        return UpdateExpression.builder()
                .addAction(setAction)
                .build();
    }
}
```

# Gunakan DynamoDB Enhanced Client API secara asinkron
<a name="ddb-en-client-async"></a>

Jika aplikasi Anda memerlukan panggilan asinkron non-pemblokiran ke DynamoDB, Anda dapat menggunakan file. [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html) Ini mirip dengan implementasi sinkron tetapi dengan perbedaan utama berikut:

1. Ketika Anda membangun`DynamoDbEnhancedAsyncClient`, Anda harus menyediakan versi asinkron dari klien standar,`DynamoDbAsyncClient`, seperti yang ditunjukkan dalam cuplikan berikut.

   ```
    DynamoDbEnhancedAsyncClient enhancedClient = 
        DynamoDbEnhancedAsyncClient.builder()
                                   .dynamoDbClient(dynamoDbAsyncClient)
                                   .build();
   ```

1. Metode yang mengembalikan objek data tunggal `CompletableFuture` mengembalikan hasil bukan hanya hasilnya. Aplikasi Anda kemudian dapat melakukan pekerjaan lain tanpa harus memblokir hasilnya. Cuplikan berikut menunjukkan metode `getItem()` asinkron. 

   ```
   CompletableFuture<Customer> result = customerDynamoDbTable.getItem(customer);
   // Perform other work here.
   return result.join();   // Now block and wait for the result.
   ```

1. Metode yang mengembalikan daftar hasil paginasi mengembalikan sebuah [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)alih-alih [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html)yang dikembalikan sinkron `DynamoDbEnhanceClient` untuk metode yang sama. Aplikasi Anda kemudian dapat berlangganan handler ke penerbit itu untuk menangani hasil secara asinkron tanpa harus memblokir.

   ```
   PagePublisher<Customer> results = customerDynamoDbTable.query(r -> r.queryConditional(keyEqualTo(k -> k.partitionValue("Smith"))));
   results.subscribe(myCustomerResultsProcessor);
   // Perform other work and let the processor handle the results asynchronously.
   ```

   Untuk contoh yang lebih lengkap tentang bekerja dengan`SdkPublisher API`, lihat [contoh di](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-scan-async) bagian yang membahas `scan()` metode asinkron dari panduan ini.

# Anotasi kelas data
<a name="ddb-en-client-anno-index"></a>

Tabel berikut mencantumkan anotasi yang dapat digunakan pada kelas data dan menyediakan tautan ke informasi dan contoh dalam panduan ini. Tabel diurutkan dalam urutan abjad menaik dengan nama anotasi.


**Anotasi kelas data yang digunakan dalam panduan ini**  

| Nama anotasi | Anotasi berlaku untuk 1 | Apa yang dilakukannya | Dimana itu ditampilkan dalam panduan ini | 
| --- | --- | --- | --- | 
| DynamoDbAtomicCounter | atribut 2 | Menambah atribut numerik yang ditandai setiap kali catatan ditulis ke database. | [Pengantar dan diskusi.](ddb-en-client-extensions.md#ddb-en-client-extensions-ACE) | 
| DynamoDbAttribute | atribut | Mendefinisikan atau mengganti nama properti kacang yang dipetakan ke atribut tabel DynamoDB. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbAutoGeneratedTimestampAttribute | atribut | Memperbarui atribut yang ditandai dengan stempel waktu saat ini setiap kali item berhasil ditulis ke database | [Pengantar dan diskusi](ddb-en-client-extensions.md#ddb-en-client-extensions-AGTE). | 
| DynamoDbAutoGeneratedUuid | atribut | Menghasilkan UUID unik (Universally Unique Identifier) untuk atribut ketika catatan baru ditulis ke database. | [Pengantar dan diskusi.](ddb-en-client-extensions.md#ddb-en-client-extensions-AGUE) | 
| DynamoDbBean | class | Menandai kelas data sebagai dapat dipetakan ke skema tabel. | Pertama gunakan pada [kelas Pelanggan](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) di bagian Memulai. Beberapa penggunaan muncul di seluruh panduan. | 
| DynamoDbConvertedBy | atribut | Mengaitkan kustom AttributeConverter dengan atribut beranotasi. | [Diskusi awal dan contoh.](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-single) | 
| DynamoDbFlatten | atribut | Meratakan semua atribut dari kelas data DynamoDB terpisah dan menambahkannya sebagai atribut tingkat atas ke catatan yang dibaca dan ditulis ke database.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnore | atribut |  Menghasilkan atribut yang tersisa tidak dipetakan.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnoreNulls | atribut | Mencegah menyimpan atribut null dari objek bersarang DynamoDb . | [Diskusi dan contoh.](ddb-en-client-adv-features-ignore-null.md) | 
| DynamoDbImmutable | class |  Menandai kelas data yang tidak dapat diubah sebagai dapat dipetakan ke skema tabel.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPartitionKey | atribut |  Menandai atribut sebagai kunci partisi primer (kunci hash) dari DynamoDb tabel.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPreserveEmptyObject | atribut |  Menentukan bahwa jika tidak ada data hadir untuk objek dipetakan ke atribut beranotasi, objek harus diinisialisasi dengan semua bidang null.  | [Diskusi dan contoh.](ddb-en-client-adv-features-empty.md) | 
| DynamoDbSecondaryPartitionKey | atribut |  Menandai atribut sebagai kunci partisi untuk indeks sekunder global.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSecondarySortKey | atribut |  Menandai atribut sebagai kunci pengurutan opsional untuk indeks sekunder global atau lokal.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSortKey | atribut |  Menandai atribut sebagai kunci sortir primer opsional (range key).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbUpdateBehavior | atribut |  Menentukan perilaku ketika atribut ini diperbarui sebagai bagian dari operasi 'update' seperti UpdateItem.  | [Pendahuluan dan contoh.](ddb-en-client-adv-features-upd-behavior.md) | 
| DynamoDbVersionAttribute | atribut | Menambah nomor versi item. | [Pengantar dan diskusi.](ddb-en-client-extensions.md#ddb-en-client-extensions-VRE) | 

1 Anda dapat menerapkan anotasi tingkat atribut ke pengambil atau penyetel, tetapi tidak keduanya. Panduan ini menunjukkan anotasi tentang getter.

2 Istilah `property` ini biasanya digunakan untuk nilai yang dienkapsulasi dalam kelas data. JavaBean Namun, panduan ini menggunakan istilah `attribute` sebagai gantinya, agar konsisten dengan terminologi yang digunakan oleh DynamoDB.

# Bekerja dengan Amazon EC2
<a name="examples-ec2"></a>

Bagian ini memberikan contoh pemrograman [Amazon EC2](https://docs.aws.amazon.com/ec2/)yang menggunakan AWS SDK untuk Java 2.x.

**Topics**
+ [Kelola Amazon EC2 instance](examples-ec2-instances.md)
+ [Zona Penggunaan Wilayah AWS dan Ketersediaan](examples-ec2-regions-zones.md)
+ [Bekerja dengan kelompok keamanan di Amazon EC2](examples-ec2-security-groups.md)
+ [Bekerja dengan metadata instans Amazon EC2](examples-ec2-IMDS.md)

# Kelola Amazon EC2 instance
<a name="examples-ec2-instances"></a>

## Buatlah sebuah instans
<a name="create-an-instance"></a>

Buat Amazon EC2 instance baru dengan memanggil [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#runInstances(software.amazon.awssdk.services.ec2.model.RunInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#runInstances(software.amazon.awssdk.services.ec2.model.RunInstancesRequest))metode [Ec2Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html), sediakan dengan [RunInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesRequest.html)berisi [Amazon Machine Image (AMI)](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/AMIs.html) untuk digunakan dan jenis [instance](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/instance-types.html).

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.InstanceType;
import software.amazon.awssdk.services.ec2.model.RunInstancesRequest;
import software.amazon.awssdk.services.ec2.model.RunInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Tag;
import software.amazon.awssdk.services.ec2.model.CreateTagsRequest;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
```

 **Kode** 

```
   public static String createEC2Instance(Ec2Client ec2,String name, String amiId ) {

        RunInstancesRequest runRequest = RunInstancesRequest.builder()
                .imageId(amiId)
                .instanceType(InstanceType.T1_MICRO)
                .maxCount(1)
                .minCount(1)
                .build();

        RunInstancesResponse response = ec2.runInstances(runRequest);
        String instanceId = response.instances().get(0).instanceId();

        Tag tag = Tag.builder()
                .key("Name")
                .value(name)
                .build();

        CreateTagsRequest tagRequest = CreateTagsRequest.builder()
                .resources(instanceId)
                .tags(tag)
                .build();

        try {
            ec2.createTags(tagRequest);
            System.out.printf(
                    "Successfully started EC2 Instance %s based on AMI %s",
                    instanceId, amiId);

          return instanceId;

        } catch (Ec2Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }

        return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateInstance.java) di GitHub.

## Memulai instans
<a name="start-an-instance"></a>

Untuk memulai sebuah Amazon EC2 instance, panggil [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#startInstances(software.amazon.awssdk.services.ec2.model.StartInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#startInstances(software.amazon.awssdk.services.ec2.model.StartInstancesRequest))metode Ec2Client, sediakan dengan ID [StartInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StartInstancesRequest.html)yang berisi instance untuk memulai.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
```

 **Kode** 

```
    public static void startInstance(Ec2Client ec2, String instanceId) {

        StartInstancesRequest request = StartInstancesRequest.builder()
                .instanceIds(instanceId)
                .build();

        ec2.startInstances(request);
        System.out.printf("Successfully started instance %s", instanceId);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) di GitHub.

## Menghentikan instans
<a name="stop-an-instance"></a>

Untuk menghentikan Amazon EC2 instance, panggil [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#stopInstances(software.amazon.awssdk.services.ec2.model.StopInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#stopInstances(software.amazon.awssdk.services.ec2.model.StopInstancesRequest))metode Ec2Client, berikan ID yang [StopInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StopInstancesRequest.html)berisi instance untuk berhenti.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
```

 **Kode** 

```
    public static void stopInstance(Ec2Client ec2, String instanceId) {

        StopInstancesRequest request = StopInstancesRequest.builder()
                .instanceIds(instanceId)
                .build();

        ec2.stopInstances(request);
        System.out.printf("Successfully stopped instance %s", instanceId);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) di GitHub.

## Menyalakan ulang instans
<a name="reboot-an-instance"></a>

Untuk me-reboot sebuah Amazon EC2 instance, panggil [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#rebootInstances(software.amazon.awssdk.services.ec2.model.RebootInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#rebootInstances(software.amazon.awssdk.services.ec2.model.RebootInstancesRequest))metode Ec2Client, berikan ID yang [RebootInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RebootInstancesRequest.html)berisi instance untuk reboot.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.RebootInstancesRequest;
```

 **Kode** 

```
    public static void rebootEC2Instance(Ec2Client ec2, String instanceId) {

      try {
            RebootInstancesRequest request = RebootInstancesRequest.builder()
                .instanceIds(instanceId)
                    .build();

            ec2.rebootInstances(request);
            System.out.printf(
                "Successfully rebooted instance %s", instanceId);
    } catch (Ec2Exception e) {
          System.err.println(e.awsErrorDetails().errorMessage());
          System.exit(1);
     }
  }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/RebootInstance.java) di GitHub.

## Menjelaskan instans
<a name="describe-instances"></a>

Untuk membuat daftar instance Anda, buat [DescribeInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesRequest.html)dan panggil metode Ec2Client. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#describeInstances(software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#describeInstances(software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest)) Ini akan mengembalikan [DescribeInstancesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesResponse.html)objek yang dapat Anda gunakan untuk daftar Amazon EC2 instance untuk akun dan wilayah Anda.

*Instans dikelompokkan berdasarkan reservasi.* Setiap reservasi sesuai dengan panggilan `startInstances` yang meluncurkan instance. Untuk membuat daftar instance Anda, Anda harus terlebih dahulu memanggil `reservations` metode `DescribeInstancesResponse` kelas, dan kemudian memanggil `instances` setiap objek [Reservasi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Reservation.html) yang dikembalikan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.Reservation;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
```

 **Kode** 

```
    public static void describeEC2Instances( Ec2Client ec2){

        String nextToken = null;

        try {

            do {
                DescribeInstancesRequest request = DescribeInstancesRequest.builder().maxResults(6).nextToken(nextToken).build();
                DescribeInstancesResponse response = ec2.describeInstances(request);

                for (Reservation reservation : response.reservations()) {
                    for (Instance instance : reservation.instances()) {
                        System.out.println("Instance Id is " + instance.instanceId());
                        System.out.println("Image id is "+  instance.imageId());
                        System.out.println("Instance type is "+  instance.instanceType());
                        System.out.println("Instance state name is "+  instance.state().name());
                        System.out.println("monitoring information is "+  instance.monitoring().state());

                }
            }
                nextToken = response.nextToken();
            } while (nextToken != null);

        } catch (Ec2Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Hasil paged; Anda bisa mendapatkan hasil lebih lanjut dengan meneruskan nilai yang dikembalikan dari `nextToken` metode objek hasil ke `nextToken` metode objek permintaan baru, kemudian menggunakan objek permintaan baru dalam panggilan berikutnya. `describeInstances`

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeInstances.java) di GitHub.

## Memantau sebuah instance
<a name="monitor-an-instance"></a>

Anda dapat memantau berbagai aspek Amazon EC2 instance Anda, seperti CPU dan pemanfaatan jaringan, memori yang tersedia, dan ruang disk yang tersisa. Untuk mempelajari lebih lanjut tentang pemantauan instans, lihat [Pemantauan Amazon EC2](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/monitoring_ec2.html) di Panduan Amazon EC2 Pengguna untuk Instans Linux.

Untuk mulai memantau instance, Anda harus membuat [MonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/MonitorInstancesRequest.html)dengan ID instance untuk dipantau, dan meneruskannya ke metode [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#monitorInstances(software.amazon.awssdk.services.ec2.model.MonitorInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#monitorInstances(software.amazon.awssdk.services.ec2.model.MonitorInstancesRequest))Ec2Client.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.MonitorInstancesRequest;
import software.amazon.awssdk.services.ec2.model.UnmonitorInstancesRequest;
```

 **Kode** 

```
    public static void monitorInstance( Ec2Client ec2, String instanceId) {

        MonitorInstancesRequest request = MonitorInstancesRequest.builder()
                .instanceIds(instanceId).build();

        ec2.monitorInstances(request);
        System.out.printf(
                "Successfully enabled monitoring for instance %s",
                instanceId);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) di GitHub.

## Hentikan pemantauan instans
<a name="stop-instance-monitoring"></a>

Untuk menghentikan pemantauan instance, buat [UnmonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/UnmonitorInstancesRequest.html)dengan ID instance untuk menghentikan pemantauan, dan teruskan ke metode Ec2Client. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#unmonitorInstances(software.amazon.awssdk.services.ec2.model.UnmonitorInstancesRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#unmonitorInstances(software.amazon.awssdk.services.ec2.model.UnmonitorInstancesRequest))

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.MonitorInstancesRequest;
import software.amazon.awssdk.services.ec2.model.UnmonitorInstancesRequest;
```

 **Kode** 

```
    public static void unmonitorInstance(Ec2Client ec2, String instanceId) {
        UnmonitorInstancesRequest request = UnmonitorInstancesRequest.builder()
                .instanceIds(instanceId).build();

        ec2.unmonitorInstances(request);

        System.out.printf(
                "Successfully disabled monitoring for instance %s",
                instanceId);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html)di Referensi Amazon EC2 API
+  [DescribeInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html)di Referensi Amazon EC2 API
+  [StartInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StartInstances.html)di Referensi Amazon EC2 API
+  [StopInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StopInstances.html)di Referensi Amazon EC2 API
+  [RebootInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RebootInstances.html)di Referensi Amazon EC2 API
+  [MonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_MonitorInstances.html)di Referensi Amazon EC2 API
+  [UnmonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_UnmonitorInstances.html)di Referensi Amazon EC2 API

# Zona Penggunaan Wilayah AWS dan Ketersediaan
<a name="examples-ec2-regions-zones"></a>

## Menjelaskan Wilayah
<a name="describe-regions"></a>

Untuk mencantumkan Wilayah yang tersedia untuk akun Anda, hubungi metode Ec2Client. `describeRegions` Ini mengembalikan a [DescribeRegionsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeRegionsResponse.html). Panggil `regions` metode objek yang dikembalikan untuk mendapatkan daftar objek [Region](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Region.html) yang mewakili setiap Region.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeRegionsResponse;
import software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesResponse;
import java.util.concurrent.CompletableFuture;
```

 **Kode** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeRegionsResponse;
import software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesResponse;
import java.util.concurrent.CompletableFuture;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class DescribeRegionsAndZones {
    public static void main(String[] args) {
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();

        try {
            CompletableFuture<Void> future = describeEC2RegionsAndZonesAsync(ec2AsyncClient);
            future.join(); // Wait for both async operations to complete.
        } catch (RuntimeException rte) {
            System.err.println("An exception occurred: " + (rte.getCause() != null ? rte.getCause().getMessage() : rte.getMessage()));
        }
    }

    /**
     * Asynchronously describes the EC2 regions and availability zones.
     *
     * @param ec2AsyncClient the EC2 async client used to make the API calls
     * @return a {@link CompletableFuture} that completes when both the region and availability zone descriptions are complete
     */
    public static CompletableFuture<Void> describeEC2RegionsAndZonesAsync(Ec2AsyncClient ec2AsyncClient) {
        // Initiate the asynchronous request to describe regions
        CompletableFuture<DescribeRegionsResponse> regionsResponse = ec2AsyncClient.describeRegions();

        // Handle the response or exception for regions
        CompletableFuture<DescribeRegionsResponse> regionsFuture = regionsResponse.whenComplete((regionsResp, ex) -> {
            if (ex != null) {
                // Handle the exception by throwing a RuntimeException
                throw new RuntimeException("Failed to describe EC2 regions.", ex);
            } else if (regionsResp == null || regionsResp.regions().isEmpty()) {
                // Throw an exception if the response is null or the result is empty
                throw new RuntimeException("No EC2 regions found.");
            } else {
                // Process the response if no exception occurred and the result is not empty
                regionsResp.regions().forEach(region -> {
                    System.out.printf(
                        "Found Region %s with endpoint %s%n",
                        region.regionName(),
                        region.endpoint());
                });
            }
        });

        CompletableFuture<DescribeAvailabilityZonesResponse> zonesResponse = ec2AsyncClient.describeAvailabilityZones();
        CompletableFuture<DescribeAvailabilityZonesResponse> zonesFuture = zonesResponse.whenComplete((zonesResp, ex) -> {
            if (ex != null) {
                throw new RuntimeException("Failed to describe EC2 availability zones.", ex);
            } else if (zonesResp == null || zonesResp.availabilityZones().isEmpty()) {
                throw new RuntimeException("No EC2 availability zones found.");
            } else {
                zonesResp.availabilityZones().forEach(zone -> {
                    System.out.printf(
                        "Found Availability Zone %s with status %s in region %s%n",
                        zone.zoneName(),
                        zone.state(),
                        zone.regionName()
                    );
                });
            }
        });

        return CompletableFuture.allOf(regionsFuture, zonesFuture);
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) di GitHub.

## Jelaskan zona ketersediaan
<a name="describe-availability-zones"></a>

Untuk mencantumkan setiap Availability Zone yang tersedia untuk akun Anda, hubungi metode Ec2Client. `describeAvailabilityZones` Ini mengembalikan a [DescribeAvailabilityZonesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAvailabilityZonesResponse.html). Panggil `availabilityZones` metodenya untuk mendapatkan daftar [AvailabilityZone](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AvailabilityZone.html)objek yang mewakili setiap Availability Zone.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeRegionsResponse;
import software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesResponse;
import java.util.concurrent.CompletableFuture;
```

 **Kode** 

Buat Ec2Client.

```
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();
```

Kemudian panggil describeAvailabilityZones () dan ambil hasilnya.

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeRegionsResponse;
import software.amazon.awssdk.services.ec2.model.DescribeAvailabilityZonesResponse;
import java.util.concurrent.CompletableFuture;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class DescribeRegionsAndZones {
    public static void main(String[] args) {
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();

        try {
            CompletableFuture<Void> future = describeEC2RegionsAndZonesAsync(ec2AsyncClient);
            future.join(); // Wait for both async operations to complete.
        } catch (RuntimeException rte) {
            System.err.println("An exception occurred: " + (rte.getCause() != null ? rte.getCause().getMessage() : rte.getMessage()));
        }
    }

    /**
     * Asynchronously describes the EC2 regions and availability zones.
     *
     * @param ec2AsyncClient the EC2 async client used to make the API calls
     * @return a {@link CompletableFuture} that completes when both the region and availability zone descriptions are complete
     */
    public static CompletableFuture<Void> describeEC2RegionsAndZonesAsync(Ec2AsyncClient ec2AsyncClient) {
        // Initiate the asynchronous request to describe regions
        CompletableFuture<DescribeRegionsResponse> regionsResponse = ec2AsyncClient.describeRegions();

        // Handle the response or exception for regions
        CompletableFuture<DescribeRegionsResponse> regionsFuture = regionsResponse.whenComplete((regionsResp, ex) -> {
            if (ex != null) {
                // Handle the exception by throwing a RuntimeException
                throw new RuntimeException("Failed to describe EC2 regions.", ex);
            } else if (regionsResp == null || regionsResp.regions().isEmpty()) {
                // Throw an exception if the response is null or the result is empty
                throw new RuntimeException("No EC2 regions found.");
            } else {
                // Process the response if no exception occurred and the result is not empty
                regionsResp.regions().forEach(region -> {
                    System.out.printf(
                        "Found Region %s with endpoint %s%n",
                        region.regionName(),
                        region.endpoint());
                });
            }
        });

        CompletableFuture<DescribeAvailabilityZonesResponse> zonesResponse = ec2AsyncClient.describeAvailabilityZones();
        CompletableFuture<DescribeAvailabilityZonesResponse> zonesFuture = zonesResponse.whenComplete((zonesResp, ex) -> {
            if (ex != null) {
                throw new RuntimeException("Failed to describe EC2 availability zones.", ex);
            } else if (zonesResp == null || zonesResp.availabilityZones().isEmpty()) {
                throw new RuntimeException("No EC2 availability zones found.");
            } else {
                zonesResp.availabilityZones().forEach(zone -> {
                    System.out.printf(
                        "Found Availability Zone %s with status %s in region %s%n",
                        zone.zoneName(),
                        zone.state(),
                        zone.regionName()
                    );
                });
            }
        });

        return CompletableFuture.allOf(regionsFuture, zonesFuture);
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) di GitHub.

## Jelaskan akun
<a name="describe-accounts"></a>

Untuk membuat daftar informasi EC2 terkait tentang akun Anda, hubungi metode Ec2Client. `describeAccountAttributes` Metode ini mengembalikan [DescribeAccountAttributesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAccountAttributesResponse.html)objek. Memanggil `accountAttributes` metode objek ini untuk mendapatkan daftar [AccountAttribute](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttribute.html)objek. Anda dapat mengulangi melalui daftar untuk mengambil objek`AccountAttribute`.

Anda bisa mendapatkan nilai atribut akun Anda dengan menjalankan `attributeValues` metode `AccountAttribute` objek. Metode ini mengembalikan daftar [AccountAttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttributeValue.html)objek. Anda dapat mengulangi melalui daftar kedua ini untuk menampilkan nilai atribut (lihat contoh kode berikut).

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeAccountAttributesResponse;
import java.util.concurrent.CompletableFuture;
```

 **Kode** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2AsyncClient;
import software.amazon.awssdk.services.ec2.model.DescribeAccountAttributesResponse;
import java.util.concurrent.CompletableFuture;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class DescribeAccount {
    public static void main(String[] args) {
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();

        try {
            CompletableFuture<DescribeAccountAttributesResponse> future = describeEC2AccountAsync(ec2AsyncClient);
            future.join();
            System.out.println("EC2 Account attributes described successfully.");
        } catch (RuntimeException rte) {
            System.err.println("An exception occurred: " + (rte.getCause() != null ? rte.getCause().getMessage() : rte.getMessage()));
        }
    }

    /**
     * Describes the EC2 account attributes asynchronously.
     *
     * @param ec2AsyncClient the EC2 asynchronous client to use for the operation
     * @return a {@link CompletableFuture} containing the {@link DescribeAccountAttributesResponse} with the account attributes
     */
    public static CompletableFuture<DescribeAccountAttributesResponse> describeEC2AccountAsync(Ec2AsyncClient ec2AsyncClient) {
        CompletableFuture<DescribeAccountAttributesResponse> response = ec2AsyncClient.describeAccountAttributes();
        return response.whenComplete((accountResults, ex) -> {
            if (ex != null) {
                // Handle the exception by throwing a RuntimeException.
                throw new RuntimeException("Failed to describe EC2 account attributes.", ex);
            } else if (accountResults == null || accountResults.accountAttributes().isEmpty()) {
                // Throw an exception if the response is null or no account attributes are found.
                throw new RuntimeException("No account attributes found.");
            } else {
                // Process the response if no exception occurred.
                accountResults.accountAttributes().forEach(attribute -> {
                    System.out.println("\nThe name of the attribute is " + attribute.attributeName());
                    attribute.attributeValues().forEach(
                        myValue -> System.out.println("The value of the attribute is " + myValue.attributeValue()));
                });
            }
        });
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeAccount.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Wilayah dan Availability Zone](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/using-regions-availability-zones.html) di Panduan Amazon EC2 Pengguna untuk Instans Linux
+  [DescribeRegions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html)di Referensi Amazon EC2 API
+  [DescribeAvailabilityZones](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html)di Referensi Amazon EC2 API

# Bekerja dengan kelompok keamanan di Amazon EC2
<a name="examples-ec2-security-groups"></a>

## Membuat grup keamanan
<a name="create-a-security-group"></a>

Untuk membuat grup keamanan, panggil `createSecurityGroup` metode Ec2Client dengan [CreateSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/CreateSecurityGroupRequest.html)yang berisi nama kunci.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.CreateSecurityGroupRequest;
import software.amazon.awssdk.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
import software.amazon.awssdk.services.ec2.model.AuthorizeSecurityGroupIngressResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.IpPermission;
import software.amazon.awssdk.services.ec2.model.CreateSecurityGroupResponse;
import software.amazon.awssdk.services.ec2.model.IpRange;
```

 **Kode** 

```
            CreateSecurityGroupRequest createRequest = CreateSecurityGroupRequest.builder()
                .groupName(groupName)
                .description(groupDesc)
                .vpcId(vpcId)
                .build();

            CreateSecurityGroupResponse resp= ec2.createSecurityGroup(createRequest);
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) di GitHub.

## Konfigurasikan grup keamanan
<a name="configure-a-security-group"></a>

Grup keamanan dapat mengontrol lalu lintas masuk (masuk) dan keluar (keluar) ke instans Anda. Amazon EC2 

Untuk menambahkan aturan ingress ke grup keamanan Anda, gunakan `authorizeSecurityGroupIngress` metode Ec2Client, dengan memberikan nama grup keamanan dan aturan akses ([IpPermission](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/IpPermission.html)) yang ingin Anda tetapkan di dalam objek. [AuthorizeSecurityGroupIngressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupIngressRequest.html) Contoh berikut menunjukkan cara menambahkan izin IP ke grup keamanan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.CreateSecurityGroupRequest;
import software.amazon.awssdk.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
import software.amazon.awssdk.services.ec2.model.AuthorizeSecurityGroupIngressResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.IpPermission;
import software.amazon.awssdk.services.ec2.model.CreateSecurityGroupResponse;
import software.amazon.awssdk.services.ec2.model.IpRange;
```

 **Kode** 

Pertama, buat Ec2Client

```
        Region region = Region.US_WEST_2;
        Ec2Client ec2 = Ec2Client.builder()
                .region(region)
                .build();
```

Kemudian gunakan metode Ec2Client, `authorizeSecurityGroupIngress`

```
            IpRange ipRange = IpRange.builder()
                .cidrIp("0.0.0.0/0").build();

            IpPermission ipPerm = IpPermission.builder()
                .ipProtocol("tcp")
                .toPort(80)
                .fromPort(80)
                .ipRanges(ipRange)
                .build();

            IpPermission ipPerm2 = IpPermission.builder()
                .ipProtocol("tcp")
                .toPort(22)
                .fromPort(22)
                .ipRanges(ipRange)
                .build();

            AuthorizeSecurityGroupIngressRequest authRequest =
                AuthorizeSecurityGroupIngressRequest.builder()
                        .groupName(groupName)
                        .ipPermissions(ipPerm, ipPerm2)
                        .build();

            AuthorizeSecurityGroupIngressResponse authResponse =
            ec2.authorizeSecurityGroupIngress(authRequest);

            System.out.printf(
                "Successfully added ingress policy to Security Group %s",
                groupName);

            return resp.groupId();

        } catch (Ec2Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return "";
    }
```

Untuk menambahkan aturan keluar ke grup keamanan, berikan data serupa dalam metode Ec2Client. [AuthorizeSecurityGroupEgressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupEgressRequest.html)`authorizeSecurityGroupEgress`

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) di GitHub.

## Jelaskan kelompok keamanan
<a name="describe-security-groups"></a>

Untuk mendeskripsikan grup keamanan Anda atau mendapatkan informasi tentang mereka, hubungi metode Ec2Client. `describeSecurityGroups` Ia mengembalikan [DescribeSecurityGroupsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeSecurityGroupsResponse.html)yang dapat Anda gunakan untuk mengakses daftar grup keamanan dengan memanggil `securityGroups` metodenya, yang mengembalikan daftar [SecurityGroup](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/SecurityGroup.html)objek.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DescribeSecurityGroupsRequest;
import software.amazon.awssdk.services.ec2.model.DescribeSecurityGroupsResponse;
import software.amazon.awssdk.services.ec2.model.SecurityGroup;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
```

 **Kode** 

```
     public static void describeEC2SecurityGroups(Ec2Client ec2, String groupId) {

        try {
            DescribeSecurityGroupsRequest request =
                DescribeSecurityGroupsRequest.builder()
                        .groupIds(groupId).build();

            DescribeSecurityGroupsResponse response =
                ec2.describeSecurityGroups(request);

             for(SecurityGroup group : response.securityGroups()) {
                System.out.printf(
                    "Found Security Group with id %s, " +
                            "vpc id %s " +
                            "and description %s",
                    group.groupId(),
                    group.vpcId(),
                    group.description());
            }
        } catch (Ec2Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeSecurityGroups.java) di GitHub.

## Menghapus grup keamanan
<a name="delete-a-security-group"></a>

Untuk menghapus grup keamanan, panggil `deleteSecurityGroup` metode Ec2Client, berikan [DeleteSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DeleteSecurityGroupRequest.html)yang berisi ID grup keamanan untuk dihapus.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DeleteSecurityGroupRequest;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
```

 **Kode** 

```
    public static void deleteEC2SecGroup(Ec2Client ec2,String groupId) {

        try {
            DeleteSecurityGroupRequest request = DeleteSecurityGroupRequest.builder()
                .groupId(groupId)
                .build();

            ec2.deleteSecurityGroup(request);
            System.out.printf(
                "Successfully deleted Security Group with id %s", groupId);

        } catch (Ec2Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
     }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DeleteSecurityGroup.java) di GitHub.

## Informasi lain
<a name="more-information"></a>
+  [Amazon EC2 Grup Keamanan](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html) dalam Panduan Amazon EC2 Pengguna untuk Instans Linux
+  [Otorisasi lalu lintas masuk untuk Instans Linux Anda](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html) di Panduan Amazon EC2 Pengguna untuk Instans Linux
+  [CreateSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateSecurityGroup.html)di Referensi Amazon EC2 API
+  [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)di Referensi Amazon EC2 API
+  [DeleteSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteSecurityGroup.html)di Referensi Amazon EC2 API
+  [AuthorizeSecurityGroupIngress](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AuthorizeSecurityGroupIngress.html)di Referensi Amazon EC2 API

# Bekerja dengan metadata instans Amazon EC2
<a name="examples-ec2-IMDS"></a>

Klien Java SDK untuk Layanan Metadata Instans Amazon EC2 (klien metadata) memungkinkan aplikasi Anda mengakses metadata pada instans EC2 lokal mereka. Klien metadata bekerja dengan instance lokal [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)(Instance Metadata Service v2) dan menggunakan permintaan berorientasi sesi. 

Dua kelas klien tersedia di SDK. Sinkron `[Ec2MetadataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataClient.html)` adalah untuk memblokir operasi, dan untuk kasus penggunaan asinkron, non-pemblokiran. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataAsyncClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataAsyncClient.html) 

## Memulai
<a name="examples-ec2-IMDS-getstarted"></a>

Untuk menggunakan klien metadata, tambahkan artefak `imds` Maven ke proyek Anda. Anda juga memerlukan kelas untuk `[SdkHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/SdkHttpClient.html)` (atau `[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)` untuk varian asinkron) pada classpath. 

Berikut Maven XMLmenunjukkan cuplikan dependensi untuk menggunakan sinkron [UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)bersama dengan ketergantungan untuk klien metadata.

```
<dependencyManagement>
   <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>VERSION</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>imds</artifactId>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>url-connection-client</artifactId>
    </dependency>
    <!-- other dependencies --> 
</dependencies>
```

Cari [repositori pusat Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) untuk versi artefak terbaru. `bom`

Untuk menggunakan klien HTTP asinkron, ganti cuplikan ketergantungan untuk artefak. `url-connection-client` Misalnya, cuplikan berikut membawa implementasi. [NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>netty-nio-client</artifactId>
    </dependency>
```

## Gunakan klien metadata
<a name="examples-ec2-IMDS-use"></a>

### Membuat instance klien metadata
<a name="examples-ec2-IMDS-use-create"></a>

Anda dapat membuat instance sinkron `Ec2MetadataClient` ketika hanya satu implementasi `SdkHttpClient` antarmuka yang ada di classpath. Untuk melakukannya, panggil `Ec2MetadataClient#create()` metode statis seperti yang ditunjukkan pada cuplikan berikut. 

```
Ec2MetadataClient client = Ec2MetadataClient.create(); // 'Ec2MetadataAsyncClient#create' is the asynchronous version.
```

Jika aplikasi Anda memiliki beberapa implementasi `SdkHttpAsyncClient` antarmuka `SdkHttpClient` atau, Anda harus menentukan implementasi untuk klien metadata untuk digunakan seperti yang ditunjukkan di bagian. [Klien HTTP yang dapat dikonfigurasi](#examples-ec2-IMDS-features-http) 

**catatan**  
Untuk sebagian besar klien layanan, seperti Amazon S3, SDK for Java secara otomatis menambahkan implementasi antarmuka atau. `SdkHttpClient` `SdkHttpAsyncClient` Jika klien metadata Anda menggunakan implementasi yang sama, maka `Ec2MetadataClient#create()` akan berfungsi. Jika Anda memerlukan implementasi yang berbeda, Anda harus menentukannya saat Anda membuat klien metadata.

### Kirim permintaan
<a name="examples-ec2-IMDS-use-req"></a>

[Untuk mengambil metadata instance, buat instance `EC2MetadataClient` class dan panggil `get` method dengan parameter path yang menentukan kategori metadata instance.](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)

Contoh berikut mencetak nilai yang terkait dengan `ami-id` kunci ke konsol.

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/ami-id");
System.out.println(response.asString());
client.close(); // Closes the internal resources used by the Ec2MetadataClient class.
```

Jika jalur tidak valid, `get` metode melempar pengecualian. 

Gunakan kembali instance klien yang sama untuk beberapa permintaan, tetapi panggil `close` klien ketika tidak lagi diperlukan untuk melepaskan sumber daya. Setelah metode close dipanggil, instance klien tidak dapat digunakan lagi.

### Mengurai tanggapan
<a name="examples-ec2-IMDS-use-pares"></a>

Metadata instans EC2 dapat menjadi output dalam format yang berbeda. Teks biasa dan JSON adalah format yang paling umum digunakan. Klien metadata menawarkan cara untuk bekerja dengan format tersebut. 

Seperti contoh berikut menunjukkan, menggunakan `asString` metode untuk mendapatkan data sebagai string Java. Anda juga dapat menggunakan `asList` metode ini untuk memisahkan respons teks biasa yang mengembalikan beberapa baris. 

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/");
String fullResponse = response.asString();
List<String> splits = response.asList();
```

Jika respon dalam JSON, gunakan `Ec2MetadataResponse#asDocument` metode untuk mengurai respon JSON ke dalam contoh [Dokumen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/Document.html) seperti yang ditunjukkan dalam cuplikan kode berikut.

```
Document fullResponse = response.asDocument();
```

Pengecualian akan dilemparkan jika format metadata tidak ada di JSON. Jika respons berhasil diuraikan, Anda dapat menggunakan [API dokumen](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/package-summary.html) untuk memeriksa respons secara lebih rinci. Lihat [bagan kategori metadata instance untuk mempelajari kategori](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html) metadata mana yang memberikan respons berformat JSON.

## Konfigurasikan klien metadata
<a name="examples-ec2-IMDS-config"></a>

### Percobaan ulang
<a name="examples-ec2-IMDS-config-retries"></a>

Anda dapat mengonfigurasi klien metadata dengan mekanisme coba lagi. Jika Anda melakukannya, maka klien dapat secara otomatis mencoba kembali permintaan yang gagal karena alasan yang tidak terduga. Secara default, klien mencoba ulang tiga kali pada permintaan yang gagal dengan waktu backoff eksponensial di antara upaya.

Jika kasus penggunaan Anda memerlukan mekanisme coba lagi yang berbeda, Anda dapat menyesuaikan klien menggunakan `retryPolicy` metode pada pembuatnya. Misalnya, contoh berikut menunjukkan klien sinkron yang dikonfigurasi dengan penundaan tetap dua detik antara upaya dan lima upaya coba lagi.

```
BackoffStrategy fixedBackoffStrategy = FixedDelayBackoffStrategy.create(Duration.ofSeconds(2));
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .retryPolicy(retryPolicyBuilder -> retryPolicyBuilder.numRetries(5)
                                                                           .backoffStrategy(fixedBackoffStrategy))
                     .build();
```

Ada beberapa [BackoffStrategies](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/package-summary.html)yang dapat Anda gunakan dengan klien metadata.

Anda juga dapat menonaktifkan mekanisme coba lagi sepenuhnya, seperti yang ditunjukkan cuplikan berikut.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                    .retryPolicy(Ec2MetadataRetryPolicy.none())
                    .build();
```

Menggunakan `Ec2MetadataRetryPolicy#none()` menonaktifkan kebijakan coba ulang default sehingga klien metadata tidak mencoba lagi.

### Versi IP
<a name="examples-ec2-IMDS-config-ipversion"></a>

Secara default, klien metadata menggunakan titik IPV4 akhir di. `http://169.254.169.254` Untuk mengubah klien untuk menggunakan IPV6 versi, gunakan salah satu `endpointMode` atau `endpoint` metode pembangun. Hasil pengecualian jika kedua metode dipanggil pada pembangun.

Contoh berikut menunjukkan kedua IPV6 opsi.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpointMode(EndpointMode.IPV6)
                     .build();
```

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpoint(URI.create("http://[fd00:ec2::254]"))
                     .build();
```

## Fitur utama
<a name="examples-ec2-IMDS-features"></a>

### Klien asinkron
<a name="examples-ec2-IMDS-features-async"></a>

Untuk menggunakan versi klien yang tidak memblokir, buat instance kelas. `Ec2MetadataAsyncClient` Kode dalam contoh berikut membuat klien asinkron dengan pengaturan default dan menggunakan `get` metode untuk mengambil nilai untuk kunci. `ami-id`

```
Ec2MetadataAsyncClient asyncClient = Ec2MetadataAsyncClient.create();
CompletableFuture<Ec2MetadataResponse> response = asyncClient.get("/latest/meta-data/ami-id");
```

Yang `java.util.concurrent.CompletableFuture` dikembalikan oleh `get` metode selesai ketika respon kembali. Contoh berikut mencetak `ami-id` metadata ke konsol.

```
response.thenAccept(metadata -> System.out.println(metadata.asString()));
```

### Klien HTTP yang dapat dikonfigurasi
<a name="examples-ec2-IMDS-features-http"></a>

Builder untuk setiap klien metadata memiliki `httpClient` metode yang dapat Anda gunakan untuk menyediakan klien HTTP yang disesuaikan. 

Contoh berikut menunjukkan kode untuk `UrlConnectionHttpClient` contoh kustom.

```
SdkHttpClient httpClient =
    UrlConnectionHttpClient.builder()
                           .socketTimeout(Duration.ofMinutes(5))
                           .proxyConfiguration(proxy -> proxy.endpoint(URI.create("http://proxy.example.net:8888"))))
                           .build();
Ec2MetadataClient metaDataClient =
    Ec2MetadataClient.builder()
                     .httpClient(httpClient)
                     .build();
// Use the metaDataClient instance.
metaDataClient.close();   // Close the instance when no longer needed.
```

Contoh berikut menunjukkan kode untuk `NettyNioAsyncHttpClient` instance kustom dengan klien metadata asinkron.

```
SdkAsyncHttpClient httpAsyncClient = 
    NettyNioAsyncHttpClient.builder()
                           .connectionTimeout(Duration.ofMinutes(5))
                           .maxConcurrency(100)
                           .build();
Ec2MetadataAsyncClient asyncMetaDataClient =
    Ec2MetadataAsyncClient.builder()
                          .httpClient(httpAsyncClient)
                          .build();
// Use the asyncMetaDataClient instance.
asyncMetaDataClient.close();   // Close the instance when no longer needed.
```

[Konfigurasikan klien HTTP di AWS SDK for Java 2.x](http-configuration.md)Topik dalam panduan ini memberikan rincian tentang cara mengkonfigurasi klien HTTP yang tersedia di SDK for Java.

### Caching token
<a name="examples-ec2-IMDS-features-token"></a>

Karena klien metadata menggunakan IMDSv2, semua permintaan dikaitkan dengan sesi. Sesi ditentukan oleh token yang memiliki kedaluwarsa, yang dikelola klien metadata untuk Anda. Setiap permintaan metadata secara otomatis menggunakan kembali token hingga kedaluwarsa. 

Secara default, token berlangsung selama enam jam (21.600 detik). Kami menyarankan Anda untuk mempertahankan time-to-live nilai default, kecuali kasus penggunaan khusus Anda memerlukan konfigurasi lanjutan. 

Jika diperlukan, konfigurasikan durasinya dengan menggunakan metode `tokenTtl` builder. Misalnya, kode dalam cuplikan berikut membuat klien dengan durasi sesi lima menit. 

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .tokenTtl(Duration.ofMinutes(5))
                     .build();
```

Jika Anda menghilangkan pemanggilan `tokenTtl` metode pada builder, durasi default 21.600 digunakan sebagai gantinya. 

# Bekerja dengan IAM
<a name="examples-iam"></a>

Bagian ini memberikan contoh pemrograman AWS Identity and Access Management (IAM) dengan menggunakan AWS SDK untuk Java 2.x.

 AWS Identity and Access Management (IAM) memungkinkan Anda untuk mengontrol akses ke AWS layanan dan sumber daya untuk pengguna Anda dengan aman. Dengan menggunakan IAM, Anda dapat membuat dan mengelola AWS pengguna dan grup, serta menggunakan izin untuk mengizinkan dan menolak akses mereka ke AWS sumber daya. Untuk panduan lengkap IAM, kunjungi [Panduan IAM Pengguna](https://docs.aws.amazon.com//IAM/latest/UserGuide/introduction.html).

Contoh berikut hanya mencakup kode yang diperlukan untuk mendemonstrasikan setiap teknik. [Kode contoh lengkap tersedia di GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Dari sana, Anda dapat mengunduh satu file sumber atau mengkloning repositori secara lokal untuk mendapatkan semua contoh untuk dibangun dan dijalankan.

**Topics**
+ [Kelola kunci IAM akses](examples-iam-access-keys.md)
+ [Kelola IAM Pengguna](examples-iam-users.md)
+ [Buat kebijakan IAM](feature-iam-policy-builder.md)
+ [Bekerja dengan IAM kebijakan](examples-iam-policies.md)
+ [Bekerja dengan sertifikat IAM server](examples-iam-server-certificates.md)

# Kelola kunci IAM akses
<a name="examples-iam-access-keys"></a>

## Buat kunci akses
<a name="create-an-access-key"></a>

Untuk membuat kunci IAM akses, panggil `IamClient’s` `createAccessKey` metode dengan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreateAccessKeyRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreateAccessKeyRequest.html)objek.

**catatan**  
Anda harus mengatur wilayah **AWS\$1GLOBAL**agar `IamClient` panggilan berfungsi karena IAM merupakan layanan global.

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.CreateAccessKeyRequest;
import software.amazon.awssdk.services.iam.model.CreateAccessKeyResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static String createIAMAccessKey(IamClient iam,String user) {

        try {
            CreateAccessKeyRequest request = CreateAccessKeyRequest.builder()
                .userName(user).build();

            CreateAccessKeyResponse response = iam.createAccessKey(request);
           String keyId = response.accessKey().accessKeyId();
           return keyId;

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/CreateAccessKey.java) di GitHub.

## Daftar kunci akses
<a name="list-access-keys"></a>

Untuk membuat daftar kunci akses untuk pengguna tertentu, buat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAccessKeysRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAccessKeysRequest.html)objek yang berisi nama pengguna untuk mencantumkan kunci, dan meneruskannya ke `IamClient’s` `listAccessKeys` metode.

**catatan**  
Jika Anda tidak memberikan nama pengguna ke`listAccessKeys`, itu akan mencoba untuk daftar kunci akses yang terkait dengan Akun AWS yang menandatangani permintaan.

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.AccessKeyMetadata;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.ListAccessKeysRequest;
import software.amazon.awssdk.services.iam.model.ListAccessKeysResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
```

 **Kode** 

```
    public static void listKeys( IamClient iam,String userName ){

        try {
            boolean done = false;
            String newMarker = null;

            while (!done) {
                ListAccessKeysResponse response;

            if(newMarker == null) {
                ListAccessKeysRequest request = ListAccessKeysRequest.builder()
                        .userName(userName).build();
                response = iam.listAccessKeys(request);
            } else {
                ListAccessKeysRequest request = ListAccessKeysRequest.builder()
                        .userName(userName)
                        .marker(newMarker).build();
                response = iam.listAccessKeys(request);
            }

            for (AccessKeyMetadata metadata :
                    response.accessKeyMetadata()) {
                System.out.format("Retrieved access key %s",
                        metadata.accessKeyId());
            }

            if (!response.isTruncated()) {
                done = true;
            } else {
                newMarker = response.marker();
            }
        }

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Hasil `listAccessKeys` paged (dengan maksimum default 100 record per panggilan). Anda dapat memanggil `isTruncated` [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAccessKeysResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAccessKeysResponse.html)objek yang dikembalikan untuk melihat apakah kueri mengembalikan hasil yang lebih sedikit kemudian tersedia. Jika demikian, maka panggil `marker` `ListAccessKeysResponse` dan gunakan saat membuat permintaan baru. Gunakan permintaan baru itu dalam pemanggilan berikutnya. `listAccessKeys`

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/ListAccessKeys.java) di GitHub.

## Mengambil waktu terakhir yang digunakan kunci akses
<a name="retrieve-an-access-key-s-last-used-time"></a>

Untuk mendapatkan waktu kunci akses terakhir digunakan, panggil `IamClient’s` `getAccessKeyLastUsed` metode dengan ID kunci akses (yang dapat diteruskan menggunakan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetAccessKeyLastUsedRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetAccessKeyLastUsedRequest.html)objek.

Anda kemudian dapat menggunakan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetAccessKeyLastUsedResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetAccessKeyLastUsedResponse.html)objek yang dikembalikan untuk mengambil waktu terakhir kunci yang digunakan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.GetAccessKeyLastUsedRequest;
import software.amazon.awssdk.services.iam.model.GetAccessKeyLastUsedResponse;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void getAccessKeyLastUsed(IamClient iam, String accessId ){

        try {
            GetAccessKeyLastUsedRequest request = GetAccessKeyLastUsedRequest.builder()
                    .accessKeyId(accessId).build();

            GetAccessKeyLastUsedResponse response = iam.getAccessKeyLastUsed(request);

            System.out.println("Access key was last used at: " +
                    response.accessKeyLastUsed().lastUsedDate());

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        System.out.println("Done");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/AccessKeyLastUsed.java) di GitHub.

## Aktifkan atau nonaktifkan tombol akses
<a name="iam-access-keys-update"></a>

Anda dapat mengaktifkan atau menonaktifkan kunci akses dengan membuat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateAccessKeyRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateAccessKeyRequest.html)objek, memberikan ID kunci akses, opsional nama pengguna, dan yang diinginkan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/StatusType.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/StatusType.html), lalu meneruskan objek permintaan ke metode. `IamClient’s` `updateAccessKey`

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.StatusType;
import software.amazon.awssdk.services.iam.model.UpdateAccessKeyRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
```

 **Kode** 

```
       public static void updateKey(IamClient iam, String username, String accessId, String status ) {

          try {
              if (status.toLowerCase().equalsIgnoreCase("active")) {
                  statusType = StatusType.ACTIVE;
              } else if (status.toLowerCase().equalsIgnoreCase("inactive")) {
                  statusType = StatusType.INACTIVE;
              } else {
                  statusType = StatusType.UNKNOWN_TO_SDK_VERSION;
              }
              UpdateAccessKeyRequest request = UpdateAccessKeyRequest.builder()
                .accessKeyId(accessId)
                .userName(username)
                .status(statusType)
                .build();

              iam.updateAccessKey(request);

              System.out.printf(
                "Successfully updated the status of access key %s to" +
                        "status %s for user %s", accessId, status, username);

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/UpdateAccessKey.java) di GitHub.

## Hapus kunci akses
<a name="delete-an-access-key"></a>

Untuk menghapus kunci akses secara permanen, panggil `IamClient’s` `deleteKey` metode, berikan dengan ID dan nama pengguna kunci akses yang [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DeleteAccessKeyRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DeleteAccessKeyRequest.html)berisi.

**catatan**  
Setelah dihapus, kunci tidak dapat lagi diambil atau digunakan. Untuk menonaktifkan sementara kunci sehingga dapat diaktifkan lagi nanti, gunakan [`updateAccessKey`](#iam-access-keys-update)metode sebagai gantinya.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.DeleteAccessKeyRequest;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void deleteKey(IamClient iam ,String username, String accessKey ) {

        try {
            DeleteAccessKeyRequest request = DeleteAccessKeyRequest.builder()
                    .accessKeyId(accessKey)
                    .userName(username)
                    .build();

            iam.deleteAccessKey(request);
            System.out.println("Successfully deleted access key " + accessKey +
                " from user " + username);

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/DeleteAccessKey.java) di GitHub.

## Informasi lain
<a name="more-information"></a>
+  [CreateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html)di Referensi IAM API
+  [ListAccessKeys](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html)di Referensi IAM API
+  [GetAccessKeyLastUsed](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccessKeyLastUsed.html)di Referensi IAM API
+  [UpdateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html)di Referensi IAM API
+  [DeleteAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html)di Referensi IAM API

# Kelola IAM Pengguna
<a name="examples-iam-users"></a>

## Buat Pengguna
<a name="creating-a-user"></a>

Buat IAM pengguna baru dengan memberikan nama pengguna ke IamClient `createUser` metode menggunakan [CreateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreateUserRequest.html)objek yang berisi nama pengguna.

 **Impor** 

```
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.services.iam.model.CreateUserRequest;
import software.amazon.awssdk.services.iam.model.CreateUserResponse;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.waiters.IamWaiter;
import software.amazon.awssdk.services.iam.model.GetUserRequest;
import software.amazon.awssdk.services.iam.model.GetUserResponse;
```

 **Kode** 

```
    public static String createIAMUser(IamClient iam, String username ) {

        try {
            // Create an IamWaiter object
            IamWaiter iamWaiter = iam.waiter();

            CreateUserRequest request = CreateUserRequest.builder()
                    .userName(username)
                    .build();

            CreateUserResponse response = iam.createUser(request);

            // Wait until the user is created
            GetUserRequest userRequest = GetUserRequest.builder()
                    .userName(response.user().userName())
                    .build();

            WaiterResponse<GetUserResponse> waitUntilUserExists = iamWaiter.waitUntilUserExists(userRequest);
            waitUntilUserExists.matched().response().ifPresent(System.out::println);
            return response.user().userName();

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
       return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/CreateUser.java) di GitHub.

## Daftar Pengguna
<a name="listing-users"></a>

Untuk membuat daftar IAM pengguna untuk akun Anda, buat yang baru [ListUsersRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersRequest.html)dan teruskan ke IamClient `listUsers` metode ini. Anda dapat mengambil daftar pengguna dengan memanggil [ListUsersResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersResponse.html)objek `users` yang dikembalikan.

Daftar pengguna yang dikembalikan `listUsers` oleh halaman. Anda dapat memeriksa untuk melihat ada lebih banyak hasil untuk diambil dengan memanggil `isTruncated` metode objek respons. Jika kembali`true`, maka panggil `marker()` metode objek respon. Gunakan nilai penanda untuk membuat objek permintaan baru. Kemudian panggil `listUsers` metode lagi dengan permintaan baru.

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.ListUsersRequest;
import software.amazon.awssdk.services.iam.model.ListUsersResponse;
import software.amazon.awssdk.services.iam.model.User;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
```

 **Kode** 

```
    public static void listAllUsers(IamClient iam ) {

        try {

             boolean done = false;
             String newMarker = null;

             while(!done) {
                ListUsersResponse response;

                if (newMarker == null) {
                    ListUsersRequest request = ListUsersRequest.builder().build();
                    response = iam.listUsers(request);
                } else {
                    ListUsersRequest request = ListUsersRequest.builder()
                        .marker(newMarker).build();
                    response = iam.listUsers(request);
                }

                for(User user : response.users()) {
                 System.out.format("\n Retrieved user %s", user.userName());
                }

                if(!response.isTruncated()) {
                  done = true;
                } else {
                    newMarker = response.marker();
                }
            }
        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/ListUsers.java) di GitHub.

## Memperbarui Pengguna
<a name="updating-a-user"></a>

Untuk memperbarui pengguna, panggil `updateUser` metode IamClient objek, yang mengambil [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)objek yang dapat Anda gunakan untuk mengubah *nama* atau *jalur* pengguna.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.UpdateUserRequest;
```

 **Kode** 

```
    public static void updateIAMUser(IamClient iam, String curName,String newName ) {

        try {
            UpdateUserRequest request = UpdateUserRequest.builder()
                    .userName(curName)
                    .newUserName(newName)
                    .build();

            iam.updateUser(request);
            System.out.printf("Successfully updated user to username %s",
                newName);
        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
      }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/UpdateUser.java) di GitHub.

## Menghapus Pengguna
<a name="deleting-a-user"></a>

Untuk menghapus pengguna, panggil IamClient `deleteUser` permintaan dengan [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)objek yang ditetapkan dengan nama pengguna untuk dihapus.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.DeleteUserRequest;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void deleteIAMUser(IamClient iam, String userName) {

        try {
            DeleteUserRequest request = DeleteUserRequest.builder()
                    .userName(userName)
                    .build();

            iam.deleteUser(request);
            System.out.println("Successfully deleted IAM user " + userName);
        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DeleteUser.java) di GitHub.

## Informasi Selengkapnya
<a name="more-information"></a>
+  [IAM Pengguna](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) di Panduan IAM Pengguna
+  [Mengelola IAM Pengguna](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_manage.html) di Panduan IAM Pengguna
+  [CreateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html)di Referensi IAM API
+  [ListUsers](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html)di Referensi IAM API
+  [UpdateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html)di Referensi IAM API
+  [DeleteUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUser.html)di Referensi IAM API

# Buat kebijakan IAM dengan AWS SDK for Java 2.x
<a name="feature-iam-policy-builder"></a>

[API Pembuat Kebijakan IAM](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/package-summary.html) adalah pustaka yang dapat Anda gunakan untuk membangun [kebijakan IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) di Java dan mengunggahnya ke AWS Identity and Access Management (IAM). 

Alih-alih membangun kebijakan IAM dengan merakit string JSON secara manual atau dengan membaca file, API menyediakan pendekatan berorientasi objek sisi klien untuk menghasilkan string JSON. Saat Anda membaca kebijakan IAM yang ada dalam format JSON, API mengonversinya menjadi [IamPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.html)instance untuk ditangani.

API Pembuat Kebijakan IAM tersedia dengan SDK versi 2.20.105, jadi gunakan versi tersebut atau yang lebih baru di file build Maven Anda. Nomor versi terbaru SDK [terdaftar di pusat Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/iam-policy-builder).

Cuplikan berikut menunjukkan contoh blok ketergantungan untuk file Maven. `pom.xml` Ini memungkinkan Anda untuk menggunakan IAM Policy Builder API dalam proyek Anda. 

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>iam-policy-builder</artifactId>
    <version>2.27.21</version>
</dependency>
```

## Buat `IamPolicy`
<a name="iam-policy-builder-create"></a>

Bagian ini menunjukkan beberapa contoh cara membuat kebijakan dengan menggunakan IAM Policy Builder API.

Dalam setiap contoh berikut, mulailah dengan `[IamPolicy.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.Builder.html)` dan tambahkan satu atau lebih pernyataan dengan menggunakan `addStatement` metode. Mengikuti pola ini, [IamStatement.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamStatement.Builder.html) memiliki metode untuk menambahkan efek, tindakan, sumber daya, dan kondisi ke pernyataan.

### Contoh: Membuat kebijakan berbasis waktu
<a name="iam-policy-builder-create-ex-time-based"></a>

Contoh berikut membuat kebijakan berbasis identitas yang mengizinkan tindakan Amazon DynamoDB antara dua titik waktu`GetItem`.

```
    public String timeBasedPolicyExample() {
        IamPolicy policy = IamPolicy.builder()
                .addStatement(b -> b
                        .effect(IamEffect.ALLOW)
                        .addAction("dynamodb:GetItem")
                        .addResource(IamResource.ALL)
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.DATE_GREATER_THAN)
                                .key("aws:CurrentTime")
                                .value("2020-04-01T00:00:00Z"))
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.DATE_LESS_THAN)
                                .key("aws:CurrentTime")
                                .value("2020-06-30T23:59:59Z")))
                .build();

        // Use an IamPolicyWriter to write out the JSON string to a more readable format.
        return policy.toJson(IamPolicyWriter.builder()
                        .prettyPrint(true)
                        .build());
    }
```

#### Keluaran JSON
<a name="iam-builder-ex-json-date"></a>

Pernyataan terakhir dalam contoh sebelumnya mengembalikan string JSON berikut. 

Baca lebih lanjut tentang [contoh](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws-dates.html) ini di *Panduan AWS Identity and Access Management Pengguna*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": {
        "Effect": "Allow",
        "Action": "dynamodb:GetItem",
        "Resource": "*",
        "Condition": {
            "DateGreaterThan": {
                "aws:CurrentTime": "2020-04-01T00:00:00Z"
            },
            "DateLessThan": {
                "aws:CurrentTime": "2020-06-30T23:59:59Z"
            }
        }
    }
}
```

------

### Contoh: Tentukan beberapa kondisi
<a name="iam-policy-builder-create-ex-multi-conditions"></a>

Contoh berikut menunjukkan bagaimana Anda dapat membuat kebijakan berbasis identitas yang memungkinkan akses ke atribut DynamoDB tertentu. Kebijakan tersebut berisi dua syarat.

```
    public String multipleConditionsExample() {
        IamPolicy policy = IamPolicy.builder()
                .addStatement(b -> b
                        .effect(IamEffect.ALLOW)
                        .addAction("dynamodb:GetItem")
                        .addAction("dynamodb:BatchGetItem")
                        .addAction("dynamodb:Query")
                        .addAction("dynamodb:PutItem")
                        .addAction("dynamodb:UpdateItem")
                        .addAction("dynamodb:DeleteItem")
                        .addAction("dynamodb:BatchWriteItem")
                        .addResource("arn:aws:dynamodb:*:*:table/table-name")
                        .addConditions(IamConditionOperator.STRING_EQUALS.addPrefix("ForAllValues:"),
                                "dynamodb:Attributes",
                                List.of("column-name1", "column-name2", "column-name3"))
                        .addCondition(b1 -> b1.operator(IamConditionOperator.STRING_EQUALS.addSuffix("IfExists"))
                                .key("dynamodb:Select")
                                .value("SPECIFIC_ATTRIBUTES")))
                .build();

        return policy.toJson(IamPolicyWriter.builder()
                .prettyPrint(true).build());
    }
```

#### Keluaran JSON
<a name="iam-builder-ex-json-multi-cond"></a>

Pernyataan terakhir dalam contoh sebelumnya mengembalikan string JSON berikut. 

Baca lebih lanjut tentang [contoh](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_dynamodb_attributes.html) ini di *Panduan AWS Identity and Access Management Pengguna*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "dynamodb:GetItem",
            "dynamodb:BatchGetItem",
            "dynamodb:Query",
            "dynamodb:PutItem",
            "dynamodb:UpdateItem",
            "dynamodb:DeleteItem",
            "dynamodb:BatchWriteItem"
        ],
        "Resource": "arn:aws:dynamodb:*:*:table/table-name",
        "Condition": {
            "ForAllValues:StringEquals": {
                "dynamodb:Attributes": [
                    "column-name1",
                    "column-name2",
                    "column-name3"
                ]
            },
            "StringEqualsIfExists": {
                "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
            }
        }
    }
}
```

------

### Contoh: Tentukan prinsipal
<a name="iam-policy-builder-create-ex-principals"></a>

Contoh berikut menunjukkan cara membuat kebijakan berbasis sumber daya yang menolak akses ke bucket untuk semua prinsipal kecuali yang ditentukan dalam kondisi.

```
    public String specifyPrincipalsExample() {
        IamPolicy policy = IamPolicy.builder()
                .addStatement(b -> b
                        .effect(IamEffect.DENY)
                        .addAction("s3:*")
                        .addPrincipal(IamPrincipal.ALL)
                        .addResource("arn:aws:s3:::BUCKETNAME/*")
                        .addResource("arn:aws:s3:::BUCKETNAME")
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.ARN_NOT_EQUALS)
                                .key("aws:PrincipalArn")
                                .value("arn:aws:iam::444455556666:user/user-name")))
                .build();
        return policy.toJson(IamPolicyWriter.builder()
                .prettyPrint(true).build());
    }
```

#### Keluaran JSON
<a name="iam-policy-builder-create-json-ex-principals"></a>

Pernyataan terakhir dalam contoh sebelumnya mengembalikan string JSON berikut. 

Baca lebih lanjut tentang [contoh](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-anonymous) ini di *Panduan AWS Identity and Access Management Pengguna*.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement" : {
    "Effect" : "Deny",
    "Principal" : "*",
    "Action" : "s3:*",
    "Resource" : [ "arn:aws:s3:::BUCKETNAME/*", "arn:aws:s3:::BUCKETNAME" ],
    "Condition" : {
      "ArnNotEquals" : {
        "aws:PrincipalArn" : "arn:aws:iam::444455556666:user/user-name"
      }
    }
  }
}
```

------

### Contoh: Izinkan akses lintas akun
<a name="iam-policy-builder-create-ex-cross-account"></a>

Contoh berikut menunjukkan cara mengizinkan orang lain Akun AWS mengunggah objek ke bucket Anda sambil mempertahankan kontrol pemilik penuh atas objek yang diunggah. 

```
    public String allowCrossAccountAccessExample() {
        IamPolicy policy = IamPolicy.builder()
                .addStatement(b -> b
                        .effect(IamEffect.ALLOW)
                        .addPrincipal(IamPrincipalType.AWS, "111122223333")
                        .addAction("s3:PutObject")
                        .addResource("arn:aws:s3:::amzn-s3-demo-bucket/*")
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.STRING_EQUALS)
                                .key("s3:x-amz-acl")
                                .value("bucket-owner-full-control")))
                .build();
        return policy.toJson(IamPolicyWriter.builder()
                .prettyPrint(true).build());
    }
```

#### Keluaran JSON
<a name="iam-policy-builder-create-ex-json-cross-account"></a>

Pernyataan terakhir dalam contoh sebelumnya mengembalikan string JSON berikut. 

Baca lebih lanjut tentang [contoh](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-acl-2) ini di *Panduan Pengguna Layanan Penyimpanan Sederhana Amazon*.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement" : {
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "111122223333"
    },
    "Action" : "s3:PutObject",
    "Resource" : "arn:aws:s3:::amzn-s3-demo-bucket/*",
    "Condition" : {
      "StringEquals" : {
        "s3:x-amz-acl" : "bucket-owner-full-control"
      }
    }
  }
}
```

------

## Gunakan `IamPolicy` dengan IAM
<a name="iam-policy-builder-work-with-service"></a>

Setelah Anda membuat `IamPolicy` instance, Anda menggunakan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/IamClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/IamClient.html)untuk bekerja dengan layanan IAM. 

Contoh berikut membangun kebijakan yang memungkinkan [identitas IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html) untuk menulis item ke tabel DynamoDB di akun yang ditentukan dengan parameter. `accountID` Kebijakan tersebut kemudian diunggah ke IAM sebagai string JSON.

```
    public String createAndUploadPolicyExample(IamClient iam, String accountID, String policyName) {
        // Build the policy.
        IamPolicy policy =
                IamPolicy.builder() // 'version' defaults to "2012-10-17".
                        .addStatement(IamStatement.builder()
                                .effect(IamEffect.ALLOW)
                                .addAction("dynamodb:PutItem")
                                .addResource("arn:aws:dynamodb:us-east-1:" + accountID + ":table/exampleTableName")
                                .build())
                        .build();
        // Upload the policy.
        iam.createPolicy(r -> r.policyName(policyName).policyDocument(policy.toJson()));
        return policy.toJson(IamPolicyWriter.builder().prettyPrint(true).build());
    }
```

Contoh berikutnya dibangun di atas contoh sebelumnya. Kode mengunduh kebijakan dan menggunakannya sebagai dasar untuk kebijakan baru dengan menyalin dan mengubah pernyataan. Kebijakan baru kemudian diunggah.

```
    public String createNewBasedOnExistingPolicyExample(IamClient iam, String accountID, String policyName, String newPolicyName) {

        String policyArn = "arn:aws:iam::" + accountID + ":policy/" + policyName;
        GetPolicyResponse getPolicyResponse = iam.getPolicy(r -> r.policyArn(policyArn));

        String policyVersion = getPolicyResponse.policy().defaultVersionId();
        GetPolicyVersionResponse getPolicyVersionResponse =
                iam.getPolicyVersion(r -> r.policyArn(policyArn).versionId(policyVersion));

        // Create an IamPolicy instance from the JSON string returned from IAM.
        String decodedPolicy = URLDecoder.decode(getPolicyVersionResponse.policyVersion().document(), StandardCharsets.UTF_8);
        IamPolicy policy = IamPolicy.fromJson(decodedPolicy);

            /*
             All IamPolicy components are immutable, so use the copy method that creates a new instance that
             can be altered in the same method call.

             Add the ability to get an item from DynamoDB as an additional action.
            */
        IamStatement newStatement = policy.statements().get(0).copy(s -> s.addAction("dynamodb:GetItem"));

        // Create a new statement that replaces the original statement.
        IamPolicy newPolicy = policy.copy(p -> p.statements(Arrays.asList(newStatement)));

        // Upload the new policy. IAM now has both policies.
        iam.createPolicy(r -> r.policyName(newPolicyName)
                .policyDocument(newPolicy.toJson()));

        return newPolicy.toJson(IamPolicyWriter.builder().prettyPrint(true).build());
    }
```

### IamClient
<a name="iam-policy-builder-work-with-serivce-create-client"></a>

Contoh sebelumnya menggunakan `IamClient` argumen yang dibuat seperti yang ditunjukkan pada cuplikan berikut.

```
IamClient iam = IamClient.builder().region(Region.AWS_GLOBAL).build();
```

### Kebijakan di JSON
<a name="iam-policy-builder-work-with-serivce-json"></a>

Contoh mengembalikan string JSON berikut.

```
First example
{
  "Version": "2012-10-17",		 	 	 
  "Statement" : {
    "Effect" : "Allow",
    "Action" : "dynamodb:PutItem",
    "Resource" : "arn:aws:dynamodb:us-east-1:111122223333:table/exampleTableName"
  }
}

Second example
{
  "Version": "2012-10-17",		 	 	 
  "Statement" : {
    "Effect" : "Allow",
    "Action" : [ "dynamodb:PutItem", "dynamodb:GetItem" ],
    "Resource" : "arn:aws:dynamodb:us-east-1:111122223333:table/exampleTableName"
  }
}
```

# Bekerja dengan IAM kebijakan
<a name="examples-iam-policies"></a>

## Buat kebijakan
<a name="create-a-policy"></a>

Untuk membuat kebijakan baru, berikan nama kebijakan dan dokumen kebijakan berformat JSON dalam metode [CreatePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreatePolicyRequest.html)to the's. IamClient `createPolicy`

 **Impor** 

```
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.services.iam.model.CreatePolicyRequest;
import software.amazon.awssdk.services.iam.model.CreatePolicyResponse;
import software.amazon.awssdk.services.iam.model.GetPolicyRequest;
import software.amazon.awssdk.services.iam.model.GetPolicyResponse;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.waiters.IamWaiter;
```

 **Kode** 

```
    public static String createIAMPolicy(IamClient iam, String policyName ) {

        try {
            // Create an IamWaiter object
            IamWaiter iamWaiter = iam.waiter();

            CreatePolicyRequest request = CreatePolicyRequest.builder()
                .policyName(policyName)
                .policyDocument(PolicyDocument).build();

            CreatePolicyResponse response = iam.createPolicy(request);

            // Wait until the policy is created
            GetPolicyRequest polRequest = GetPolicyRequest.builder()
                    .policyArn(response.policy().arn())
                    .build();

            WaiterResponse<GetPolicyResponse> waitUntilPolicyExists = iamWaiter.waitUntilPolicyExists(polRequest);
            waitUntilPolicyExists.matched().response().ifPresent(System.out::println);
            return response.policy().arn();

         } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return "" ;
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/e41bacfd5e671e7ef1a9f73e972540dc6a434664/javav2/example_code/iam/src/main/java/com/example/iam/CreatePolicy.java) di GitHub.

## Dapatkan kebijakan
<a name="get-a-policy"></a>

Untuk mengambil kebijakan yang ada, panggil `getPolicy` metode, yang menyediakan ARN kebijakan dalam [GetPolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetPolicyRequest.html)objek. IamClient

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.GetPolicyRequest;
import software.amazon.awssdk.services.iam.model.GetPolicyResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void getIAMPolicy(IamClient iam, String policyArn) {

        try {
            GetPolicyRequest request = GetPolicyRequest.builder()
                .policyArn(policyArn).build();

            GetPolicyResponse response = iam.getPolicy(request);
            System.out.format("Successfully retrieved policy %s",
                response.policy().policyName());

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/GetPolicy.java) di GitHub.

## Lampirkan kebijakan peran
<a name="attach-a-role-policy"></a>

Anda dapat melampirkan kebijakan ke IAM [peran](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) dengan memanggil `attachRolePolicy` metode, memberikannya nama peran dan kebijakan ARN di. IamClient [AttachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/AttachRolePolicyRequest.html)

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.AttachRolePolicyRequest;
import software.amazon.awssdk.services.iam.model.AttachedPolicy;
import software.amazon.awssdk.services.iam.model.ListAttachedRolePoliciesRequest;
import software.amazon.awssdk.services.iam.model.ListAttachedRolePoliciesResponse;
import java.util.List;
```

 **Kode** 

```
    public static void attachIAMRolePolicy(IamClient iam, String roleName, String policyArn ) {

        try {

             ListAttachedRolePoliciesRequest request = ListAttachedRolePoliciesRequest.builder()
                    .roleName(roleName)
                    .build();

            ListAttachedRolePoliciesResponse  response = iam.listAttachedRolePolicies(request);
            List<AttachedPolicy> attachedPolicies = response.attachedPolicies();

            // Ensure that the policy is not attached to this role
            String polArn = "";
            for (AttachedPolicy policy: attachedPolicies) {
                polArn = policy.policyArn();
                if (polArn.compareTo(policyArn)==0) {
                   System.out.println(roleName +
                            " policy is already attached to this role.");
                    return;
                }
          }

            AttachRolePolicyRequest attachRequest =
                AttachRolePolicyRequest.builder()
                        .roleName(roleName)
                        .policyArn(policyArn)
                        .build();

            iam.attachRolePolicy(attachRequest);

            System.out.println("Successfully attached policy " + policyArn +
                " to role " + roleName);

         } catch (IamException e) {
                System.err.println(e.awsErrorDetails().errorMessage());
                System.exit(1);
          }

     System.out.println("Done");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) di GitHub.

## Daftar kebijakan peran terlampir
<a name="list-attached-role-policies"></a>

Buat daftar kebijakan terlampir pada peran dengan memanggil `listAttachedRolePolicies` metode ini. IamClient Dibutuhkan [ListAttachedRolePoliciesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesRequest.html)objek yang berisi nama peran untuk mencantumkan kebijakan.

Panggil `getAttachedPolicies` [ListAttachedRolePoliciesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesResponse.html)objek yang dikembalikan untuk mendapatkan daftar kebijakan terlampir. Hasil dapat terpotong; jika `isTruncated` metode `ListAttachedRolePoliciesResponse` objek kembali`true`, panggil metode `ListAttachedRolePoliciesResponse` objek. `marker` Gunakan penanda yang dikembalikan untuk membuat permintaan baru dan menggunakannya untuk memanggil `listAttachedRolePolicies` lagi untuk mendapatkan kumpulan hasil berikutnya.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.AttachRolePolicyRequest;
import software.amazon.awssdk.services.iam.model.AttachedPolicy;
import software.amazon.awssdk.services.iam.model.ListAttachedRolePoliciesRequest;
import software.amazon.awssdk.services.iam.model.ListAttachedRolePoliciesResponse;
import java.util.List;
```

 **Kode** 

```
    public static void attachIAMRolePolicy(IamClient iam, String roleName, String policyArn ) {

        try {

             ListAttachedRolePoliciesRequest request = ListAttachedRolePoliciesRequest.builder()
                    .roleName(roleName)
                    .build();

            ListAttachedRolePoliciesResponse  response = iam.listAttachedRolePolicies(request);
            List<AttachedPolicy> attachedPolicies = response.attachedPolicies();

            // Ensure that the policy is not attached to this role
            String polArn = "";
            for (AttachedPolicy policy: attachedPolicies) {
                polArn = policy.policyArn();
                if (polArn.compareTo(policyArn)==0) {
                   System.out.println(roleName +
                            " policy is already attached to this role.");
                    return;
                }
          }

            AttachRolePolicyRequest attachRequest =
                AttachRolePolicyRequest.builder()
                        .roleName(roleName)
                        .policyArn(policyArn)
                        .build();

            iam.attachRolePolicy(attachRequest);

            System.out.println("Successfully attached policy " + policyArn +
                " to role " + roleName);

         } catch (IamException e) {
                System.err.println(e.awsErrorDetails().errorMessage());
                System.exit(1);
          }

     System.out.println("Done");
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) di GitHub.

## Lepaskan kebijakan peran
<a name="detach-a-role-policy"></a>

Untuk melepaskan kebijakan dari peran, panggil `detachRolePolicy` metode IamClient ini, berikan nama peran dan kebijakan ARN dalam file. [DetachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DetachRolePolicyRequest.html)

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.DetachRolePolicyRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void detachPolicy(IamClient iam, String roleName, String policyArn ) {

        try {
            DetachRolePolicyRequest request = DetachRolePolicyRequest.builder()
                    .roleName(roleName)
                    .policyArn(policyArn)
                    .build();

            iam.detachRolePolicy(request);
            System.out.println("Successfully detached policy " + policyArn +
                " from role " + roleName);

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DetachRolePolicy.java) di GitHub.

## Informasi lain
<a name="more-information"></a>
+  [Ikhtisar IAM Kebijakan](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) dalam Panduan IAM Pengguna.
+ [AWS Referensi Kebijakan IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) dalam Panduan IAM Pengguna.
+  [CreatePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html)di Referensi IAM API
+  [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html)di Referensi IAM API
+  [AttachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachRolePolicy.html)di Referensi IAM API
+  [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)di Referensi IAM API
+  [DetachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html)di Referensi IAM API

# Bekerja dengan sertifikat IAM server
<a name="examples-iam-server-certificates"></a>

Untuk mengaktifkan koneksi HTTPS ke situs web atau aplikasi Anda AWS, Anda memerlukan *sertifikat SSL/TLS server*. Anda dapat menggunakan sertifikat server yang disediakan oleh AWS Certificate Manager atau yang Anda peroleh dari penyedia eksternal.

Sebaiknya gunakan ACM untuk menyediakan, mengelola, dan menyebarkan sertifikat server Anda. Dengan ACM Anda dapat meminta sertifikat, menyebarkannya ke AWS sumber daya Anda, dan membiarkan ACM menangani perpanjangan sertifikat untuk Anda. Sertifikat yang ACM disediakan oleh gratis. Untuk informasi selengkapnya ACM, lihat [Panduan AWS Certificate Manager Pengguna](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html).

## Dapatkan sertifikat server
<a name="get-a-server-certificate"></a>

Anda dapat mengambil sertifikat server dengan memanggil `getServerCertificate` metode, meneruskannya [GetServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetServerCertificateRequest.html)dengan nama sertifikat. IamClient

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.GetServerCertificateRequest;
import software.amazon.awssdk.services.iam.model.GetServerCertificateResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void getCertificate(IamClient iam,String certName ) {

        try {
            GetServerCertificateRequest request = GetServerCertificateRequest.builder()
                    .serverCertificateName(certName)
                    .build();

            GetServerCertificateResponse response = iam.getServerCertificate(request);
            System.out.format("Successfully retrieved certificate with body %s",
                response.serverCertificate().certificateBody());

         } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/GetServerCertificate.java) di GitHub.

## Daftar sertifikat server
<a name="list-server-certificates"></a>

Untuk mencantumkan sertifikat server Anda, panggil `listServerCertificates` metode ini dengan file [ListServerCertificatesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesRequest.html). IamClient Ini mengembalikan a [ListServerCertificatesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesResponse.html).

Panggil `serverCertificateMetadataList` metode `ListServerCertificateResponse` objek yang dikembalikan untuk mendapatkan daftar [ServerCertificateMetadata](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ServerCertificateMetadata.html)objek yang dapat Anda gunakan untuk mendapatkan informasi tentang setiap sertifikat.

Hasil dapat terpotong; jika `isTruncated` metode `ListServerCertificateResponse` objek kembali`true`, panggil `marker` metode `ListServerCertificatesResponse` objek dan gunakan penanda untuk membuat permintaan baru. Gunakan permintaan baru untuk menelepon `listServerCertificates` lagi untuk mendapatkan kumpulan hasil berikutnya.

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.ListServerCertificatesRequest;
import software.amazon.awssdk.services.iam.model.ListServerCertificatesResponse;
import software.amazon.awssdk.services.iam.model.ServerCertificateMetadata;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
```

 **Kode** 

```
    public static void listCertificates(IamClient iam) {

        try {
            boolean done = false;
            String newMarker = null;

            while(!done) {
              ListServerCertificatesResponse response;

            if (newMarker == null) {
                ListServerCertificatesRequest request =
                        ListServerCertificatesRequest.builder().build();
                response = iam.listServerCertificates(request);
            } else {
                ListServerCertificatesRequest request =
                        ListServerCertificatesRequest.builder()
                                .marker(newMarker).build();
                response = iam.listServerCertificates(request);
            }

            for(ServerCertificateMetadata metadata :
                    response.serverCertificateMetadataList()) {
                System.out.printf("Retrieved server certificate %s",
                        metadata.serverCertificateName());
            }

            if(!response.isTruncated()) {
                done = true;
            } else {
                newMarker = response.marker();
            }
        }

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/ListServerCertificates.java) di GitHub.

## Memperbarui sertifikat server
<a name="update-a-server-certificate"></a>

Anda dapat memperbarui nama atau jalur sertifikat server dengan memanggil `updateServerCertificate` metode ini. IamClient Dibutuhkan [UpdateServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateServerCertificateRequest.html)objek yang ditetapkan dengan nama sertifikat server saat ini dan baik nama baru atau jalur baru untuk digunakan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
import software.amazon.awssdk.services.iam.model.UpdateServerCertificateRequest;
import software.amazon.awssdk.services.iam.model.UpdateServerCertificateResponse;
```

 **Kode** 

```
    public static void updateCertificate(IamClient iam, String curName, String newName) {

        try {
            UpdateServerCertificateRequest request =
                UpdateServerCertificateRequest.builder()
                        .serverCertificateName(curName)
                        .newServerCertificateName(newName)
                        .build();

            UpdateServerCertificateResponse response =
                iam.updateServerCertificate(request);


            System.out.printf("Successfully updated server certificate to name %s",
                newName);

        } catch (IamException e) {
             System.err.println(e.awsErrorDetails().errorMessage());
             System.exit(1);
        }
     }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/UpdateServerCertificate.java) di GitHub.

## Hapus sertifikat server
<a name="delete-a-server-certificate"></a>

Untuk menghapus sertifikat server, panggil `deleteServerCertificate` metode dengan [DeleteServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DeleteServerCertificateRequest.html)berisi nama sertifikat. IamClient

 **Impor** 

```
import software.amazon.awssdk.services.iam.model.DeleteServerCertificateRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;
import software.amazon.awssdk.services.iam.model.IamException;
```

 **Kode** 

```
    public static void deleteCert(IamClient iam,String certName ) {

        try {
            DeleteServerCertificateRequest request =
                DeleteServerCertificateRequest.builder()
                        .serverCertificateName(certName)
                        .build();

            iam.deleteServerCertificate(request);
            System.out.println("Successfully deleted server certificate " +
                    certName);

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/DeleteServerCertificate.java) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [Bekerja dengan Sertifikat Server](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_server-certs.html) di Panduan IAM Pengguna
+  [GetServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServerCertificate.html)di Referensi IAM API
+  [ListServerCertificates](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListServerCertificates.html)di Referensi IAM API
+  [UpdateServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateServerCertificate.html)di Referensi IAM API
+  [DeleteServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteServerCertificate.html)di Referensi IAM API
+  [AWS Certificate Manager Panduan Pengguna](https://docs.aws.amazon.com/acm/latest/userguide/) 

# Bekerja dengan Kinesis
<a name="examples-kinesis"></a>

Bagian ini memberikan contoh pemrograman [Amazon Kinesis](https://docs.aws.amazon.com/kinesis/)menggunakan AWS SDK untuk Java 2.x.

Untuk informasi selengkapnya Kinesis, lihat [Panduan Amazon Kinesis Pengembang](https://docs.aws.amazon.com/streams/latest/dev/introduction.html).

Contoh berikut hanya mencakup kode yang diperlukan untuk mendemonstrasikan setiap teknik. [Kode contoh lengkap tersedia di GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Dari sana, Anda dapat mengunduh satu file sumber atau mengkloning repositori secara lokal untuk mendapatkan semua contoh untuk dibangun dan dijalankan.

**Topics**
+ [Berlangganan Amazon Kinesis Data Streams](examples-kinesis-stream.md)

# Berlangganan Amazon Kinesis Data Streams
<a name="examples-kinesis-stream"></a>

Contoh berikut menunjukkan cara mengambil dan memproses data dari Amazon Kinesis Data Streams menggunakan metode ini`subscribeToShard`. Kinesis Data Streams sekarang menggunakan fitur fanout yang disempurnakan dan API pengambilan data HTTP/2 latensi rendah, sehingga memudahkan pengembang untuk menjalankan beberapa aplikasi latensi rendah dan berkinerja tinggi pada Data Stream yang sama. Kinesis 

## Penyiapan
<a name="set-up"></a>

Pertama, buat Kinesis klien asinkron dan objek. [SubscribeToShardRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardRequest.html) Objek-objek ini digunakan dalam masing-masing contoh berikut untuk berlangganan Kinesis acara.

 **Impor** 

```
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import software.amazon.awssdk.core.async.SdkPublisher;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisAsyncClient;
import software.amazon.awssdk.services.kinesis.model.ShardIteratorType;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardEvent;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardEventStream;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardRequest;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardResponse;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardResponseHandler;
```

 **Kode** 

```
        Region region = Region.US_EAST_1;
        KinesisAsyncClient client = KinesisAsyncClient.builder()
        .region(region)
        .build();

        SubscribeToShardRequest request = SubscribeToShardRequest.builder()
                .consumerARN(CONSUMER_ARN)
                .shardId("arn:aws:kinesis:us-east-1:111122223333:stream/StockTradeStream")
                .startingPosition(s -> s.type(ShardIteratorType.LATEST)).build();
```

## Gunakan antarmuka pembangun
<a name="use-the-builder-interface"></a>

Anda dapat menggunakan `builder` metode ini untuk menyederhanakan pembuatan. [SubscribeToShardResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.html)

Dengan menggunakan builder, Anda dapat mengatur setiap panggilan balik siklus hidup dengan panggilan metode alih-alih mengimplementasikan antarmuka lengkap.

 **Kode** 

```
    private static CompletableFuture<Void> responseHandlerBuilder(KinesisAsyncClient client, SubscribeToShardRequest request) {
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
                .builder()
                .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
                .onComplete(() -> System.out.println("All records stream successfully"))
                // Must supply some type of subscriber
                .subscriber(e -> System.out.println("Received event - " + e))
                .build();
        return client.subscribeToShard(request, responseHandler);
    }
```

Untuk kontrol lebih lanjut dari penerbit, Anda dapat menggunakan `publisherTransformer` metode untuk menyesuaikan penerbit.

 **Kode** 

```
    private static CompletableFuture<Void> responseHandlerBuilderPublisherTransformer(KinesisAsyncClient client, SubscribeToShardRequest request) {
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
                .builder()
                .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
                .publisherTransformer(p -> p.filter(e -> e instanceof SubscribeToShardEvent).limit(100))
                .subscriber(e -> System.out.println("Received event - " + e))
                .build();
        return client.subscribeToShard(request, responseHandler);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) di GitHub.

## Gunakan handler respon kustom
<a name="use-a-custom-response-handler"></a>

Untuk kontrol penuh pelanggan dan penerbit, terapkan antarmuka. `SubscribeToShardResponseHandler`

Dalam contoh ini, Anda menerapkan `onEventStream` metode, yang memungkinkan Anda akses penuh ke penerbit. Ini menunjukkan bagaimana mengubah penerbit menjadi catatan peristiwa untuk dicetak oleh pelanggan.

 **Kode** 

```
    private static CompletableFuture<Void> responseHandlerBuilderClassic(KinesisAsyncClient client, SubscribeToShardRequest request) {
        SubscribeToShardResponseHandler responseHandler = new SubscribeToShardResponseHandler() {

            @Override
            public void responseReceived(SubscribeToShardResponse response) {
                System.out.println("Receieved initial response");
            }

            @Override
            public void onEventStream(SdkPublisher<SubscribeToShardEventStream> publisher) {
                publisher
                        // Filter to only SubscribeToShardEvents
                        .filter(SubscribeToShardEvent.class)
                        // Flat map into a publisher of just records
                        .flatMapIterable(SubscribeToShardEvent::records)
                        // Limit to 1000 total records
                        .limit(1000)
                        // Batch records into lists of 25
                        .buffer(25)
                        // Print out each record batch
                        .subscribe(batch -> System.out.println("Record Batch - " + batch));
            }

            @Override
            public void complete() {
                System.out.println("All records stream successfully");
            }

            @Override
            public void exceptionOccurred(Throwable throwable) {
                System.err.println("Error during stream - " + throwable.getMessage());
            }
        };
        return client.subscribeToShard(request, responseHandler);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) di GitHub.

## Gunakan antarmuka pengunjung
<a name="use-the-visitor-interface"></a>

Anda dapat menggunakan objek [Pengunjung](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.Visitor.html) untuk berlangganan acara tertentu yang ingin Anda tonton.

 **Kode** 

```
    private static CompletableFuture<Void> responseHandlerBuilderVisitorBuilder(KinesisAsyncClient client, SubscribeToShardRequest request) {
        SubscribeToShardResponseHandler.Visitor visitor = SubscribeToShardResponseHandler.Visitor
                .builder()
                .onSubscribeToShardEvent(e -> System.out.println("Received subscribe to shard event " + e))
                .build();
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
                .builder()
                .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
                .subscriber(visitor)
                .build();
        return client.subscribeToShard(request, responseHandler);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) di GitHub.

## Gunakan pelanggan khusus
<a name="use-a-custom-subscriber"></a>

Anda juga dapat menerapkan pelanggan khusus Anda sendiri untuk berlangganan streaming.

Cuplikan kode ini menunjukkan contoh pelanggan.

 **Kode** 

```
    private static class MySubscriber implements Subscriber<SubscribeToShardEventStream> {

        private Subscription subscription;
        private AtomicInteger eventCount = new AtomicInteger(0);

        @Override
        public void onSubscribe(Subscription subscription) {
            this.subscription = subscription;
            this.subscription.request(1);
        }

        @Override
        public void onNext(SubscribeToShardEventStream shardSubscriptionEventStream) {
            System.out.println("Received event " + shardSubscriptionEventStream);
            if (eventCount.incrementAndGet() >= 100) {
                // You can cancel the subscription at any time if you wish to stop receiving events.
                subscription.cancel();
            }
            subscription.request(1);
        }

        @Override
        public void onError(Throwable throwable) {
            System.err.println("Error occurred while stream - " + throwable.getMessage());
        }

        @Override
        public void onComplete() {
            System.out.println("Finished streaming all events");
        }
    }
```

Anda dapat meneruskan pelanggan kustom ke `subscribe` metode seperti yang ditunjukkan pada cuplikan kode berikut.

 **Kode** 

```
    private static CompletableFuture<Void> responseHandlerBuilderSubscriber(KinesisAsyncClient client, SubscribeToShardRequest request) {
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
                .builder()
                .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
                .subscriber(MySubscriber::new)
                .build();
        return client.subscribeToShard(request, responseHandler);
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) di GitHub.

## Menulis catatan data ke dalam aliran Kinesis data
<a name="write-data-records-into-a-kinesis-data-stream"></a>

Anda dapat menggunakan [KinesisClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/KinesisClient.html)objek untuk menulis catatan data ke dalam aliran Kinesis data dengan menggunakan `putRecords` metode ini. Untuk berhasil memanggil metode ini, buat [PutRecordsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/PutRecordsRequest.html)objek. Anda meneruskan nama aliran data ke `streamName` metode. Anda juga harus meneruskan data dengan menggunakan `putRecords` metode (seperti yang ditunjukkan pada contoh kode berikut).

 **Impor** 

```
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisClient;
import software.amazon.awssdk.services.kinesis.model.PutRecordRequest;
import software.amazon.awssdk.services.kinesis.model.KinesisException;
import software.amazon.awssdk.services.kinesis.model.DescribeStreamRequest;
import software.amazon.awssdk.services.kinesis.model.DescribeStreamResponse;
```

Dalam contoh kode Java berikut, perhatikan bahwa **StockTrade**objek digunakan sebagai data untuk menulis ke aliran Kinesis data. Sebelum menjalankan contoh ini, pastikan Anda telah membuat aliran data.

 **Kode** 

```
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisClient;
import software.amazon.awssdk.services.kinesis.model.PutRecordRequest;
import software.amazon.awssdk.services.kinesis.model.KinesisException;
import software.amazon.awssdk.services.kinesis.model.DescribeStreamRequest;
import software.amazon.awssdk.services.kinesis.model.DescribeStreamResponse;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class StockTradesWriter {
    public static void main(String[] args) {
        final String usage = """

                Usage:
                    <streamName>

                Where:
                    streamName - The Amazon Kinesis data stream to which records are written (for example, StockTradeStream)
                """;

        if (args.length != 1) {
            System.out.println(usage);
            System.exit(1);
        }

        String streamName = args[0];
        Region region = Region.US_EAST_1;
        KinesisClient kinesisClient = KinesisClient.builder()
                .region(region)
                .build();

        // Ensure that the Kinesis Stream is valid.
        validateStream(kinesisClient, streamName);
        setStockData(kinesisClient, streamName);
        kinesisClient.close();
    }

    public static void setStockData(KinesisClient kinesisClient, String streamName) {
        try {
            // Repeatedly send stock trades with a 100 milliseconds wait in between.
            StockTradeGenerator stockTradeGenerator = new StockTradeGenerator();

            // Put in 50 Records for this example.
            int index = 50;
            for (int x = 0; x < index; x++) {
                StockTrade trade = stockTradeGenerator.getRandomTrade();
                sendStockTrade(trade, kinesisClient, streamName);
                Thread.sleep(100);
            }

        } catch (KinesisException | InterruptedException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println("Done");
    }

    private static void sendStockTrade(StockTrade trade, KinesisClient kinesisClient,
            String streamName) {
        byte[] bytes = trade.toJsonAsBytes();

        // The bytes could be null if there is an issue with the JSON serialization by
        // the Jackson JSON library.
        if (bytes == null) {
            System.out.println("Could not get JSON bytes for stock trade");
            return;
        }

        System.out.println("Putting trade: " + trade);
        PutRecordRequest request = PutRecordRequest.builder()
                .partitionKey(trade.getTickerSymbol()) // We use the ticker symbol as the partition key, explained in
                                                       // the Supplemental Information section below.
                .streamName(streamName)
                .data(SdkBytes.fromByteArray(bytes))
                .build();

        try {
            kinesisClient.putRecord(request);
        } catch (KinesisException e) {
            System.err.println(e.getMessage());
        }
    }

    private static void validateStream(KinesisClient kinesisClient, String streamName) {
        try {
            DescribeStreamRequest describeStreamRequest = DescribeStreamRequest.builder()
                    .streamName(streamName)
                    .build();

            DescribeStreamResponse describeStreamResponse = kinesisClient.describeStream(describeStreamRequest);

            if (!describeStreamResponse.streamDescription().streamStatus().toString().equals("ACTIVE")) {
                System.err.println("Stream " + streamName + " is not active. Please wait a few moments and try again.");
                System.exit(1);
            }

        } catch (KinesisException e) {
            System.err.println("Error found while describing the stream " + streamName);
            System.err.println(e);
            System.exit(1);
        }
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/kinesis/src/main/java/com/example/kinesis/StockTradesWriter.java) di GitHub.

## Gunakan pustaka pihak ketiga
<a name="use-a-third-party-library"></a>

Anda dapat menggunakan pustaka pihak ketiga lainnya alih-alih menerapkan pelanggan khusus. Contoh ini menunjukkan penggunaan RxJava implementasi, tetapi Anda dapat menggunakan pustaka apa pun yang mengimplementasikan antarmuka Reactive Streams. Lihat [halaman RxJava wiki di Github](https://github.com/ReactiveX/RxJava/wiki) untuk informasi lebih lanjut tentang perpustakaan itu.

Untuk menggunakan perpustakaan, tambahkan sebagai dependensi. Jika Anda menggunakan Maven, contoh menunjukkan cuplikan POM untuk digunakan.

 **Entri POM** 

```
<dependency>
 <groupId>io.reactivex.rxjava2</groupId>
 <artifactId>rxjava</artifactId>
 <version>2.2.21</version>
</dependency>
```

 **Impor** 

```
import java.net.URI;
import java.util.concurrent.CompletableFuture;

import io.reactivex.Flowable;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.async.SdkPublisher;
import software.amazon.awssdk.http.Protocol;
import software.amazon.awssdk.http.SdkHttpConfigurationOption;
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisAsyncClient;
import software.amazon.awssdk.services.kinesis.model.ShardIteratorType;
import software.amazon.awssdk.services.kinesis.model.StartingPosition;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardEvent;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardRequest;
import software.amazon.awssdk.services.kinesis.model.SubscribeToShardResponseHandler;
import software.amazon.awssdk.utils.AttributeMap;
```

Contoh ini digunakan RxJava dalam metode `onEventStream` siklus hidup. Ini memberi Anda akses penuh ke penerbit, yang dapat digunakan untuk membuat Rx Flowable.

 **Kode** 

```
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
            .builder()
            .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
            .onEventStream(p -> Flowable.fromPublisher(p)
                                        .ofType(SubscribeToShardEvent.class)
                                        .flatMapIterable(SubscribeToShardEvent::records)
                                        .limit(1000)
                                        .buffer(25)
                                        .subscribe(e -> System.out.println("Record batch = " + e)))
            .build();
```

Anda juga dapat menggunakan `publisherTransformer` metode ini dengan `Flowable` penerbit. Anda harus menyesuaikan `Flowable` penerbit dengan *SdkPublisher*, seperti yang ditunjukkan pada contoh berikut.

 **Kode** 

```
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
            .builder()
            .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
            .publisherTransformer(p -> SdkPublisher.adapt(Flowable.fromPublisher(p).limit(100)))
            .build();
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamRxJavaEx.java) di GitHub.

## Informasi lain
<a name="more-information"></a>
+  [SubscribeToShardEvent](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShardEvent.html)di Referensi Amazon Kinesis API
+  [SubscribeToShard](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShard.html)di Referensi Amazon Kinesis API

# Memanggil, membuat daftar, dan menghapus fungsi AWS Lambda
<a name="examples-lambda"></a>

Bagian ini memberikan contoh pemrograman dengan klien Lambda layanan dengan menggunakan AWS SDK untuk Java 2.x.

**Topics**
+ [Memanggil fungsi Lambda](#invoke-function)
+ [Daftar fungsi Lambda](#list-function)
+ [Hapus fungsi Lambda](#delete-function)

## Memanggil fungsi Lambda
<a name="invoke-function"></a>

Anda dapat memanggil Lambda fungsi dengan membuat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html)objek dan menjalankan metodenya`invoke`. Buat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/InvokeRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/InvokeRequest.html)objek untuk menentukan informasi tambahan seperti nama fungsi dan payload untuk diteruskan ke Lambda fungsi. Nama fungsi muncul sebagai *arn:aws:lambda:us-east* - 1:123456789012: function:. HelloFunction Anda dapat mengambil nilai dengan melihat fungsi di. Konsol Manajemen AWS

Untuk meneruskan data payload ke suatu fungsi, buat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/SdkBytes.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/SdkBytes.html)objek yang berisi informasi. Misalnya, dalam contoh kode berikut, perhatikan data JSON diteruskan ke Lambda fungsi.

 **Impor** 

```
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.model.InvokeRequest;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.lambda.model.InvokeResponse;
import software.amazon.awssdk.services.lambda.model.LambdaException;
```

 **Kode** 

Contoh kode berikut menunjukkan bagaimana untuk memanggil fungsi. Lambda 

```
    public static void invokeFunction(LambdaClient awsLambda, String functionName) {

         InvokeResponse res = null ;
        try {
            //Need a SdkBytes instance for the payload
            String json = "{\"Hello \":\"Paris\"}";
            SdkBytes payload = SdkBytes.fromUtf8String(json) ;

            //Setup an InvokeRequest
            InvokeRequest request = InvokeRequest.builder()
                    .functionName(functionName)
                    .payload(payload)
                    .build();

            res = awsLambda.invoke(request);
            String value = res.payload().asUtf8String() ;
            System.out.println(value);

        } catch(LambdaException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/LambdaInvoke.java) di GitHub.

## Daftar fungsi Lambda
<a name="list-function"></a>

Bangun `[Lambda Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html)` objek dan panggil `listFunctions` metodenya. Metode ini mengembalikan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/ListFunctionsResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/ListFunctionsResponse.html)objek. Anda dapat memanggil `functions` metode objek ini untuk mengembalikan daftar [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/FunctionConfiguration.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/FunctionConfiguration.html)objek. Anda dapat mengulangi melalui daftar untuk mengambil informasi tentang fungsi. Misalnya, contoh kode Java berikut menunjukkan cara mendapatkan setiap nama fungsi.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.services.lambda.model.LambdaException;
import software.amazon.awssdk.services.lambda.model.ListFunctionsResponse;
import software.amazon.awssdk.services.lambda.model.FunctionConfiguration;
import java.util.List;
```

 **Kode** 

Contoh kode Java berikut menunjukkan bagaimana untuk mengambil daftar nama fungsi.

```
    public static void listFunctions(LambdaClient awsLambda) {

        try {
            ListFunctionsResponse functionResult = awsLambda.listFunctions();
            List<FunctionConfiguration> list = functionResult.functions();

            for (FunctionConfiguration config: list) {
                System.out.println("The function name is "+config.functionName());
            }

        } catch(LambdaException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/ListLambdaFunctions.java) di GitHub.

## Hapus fungsi Lambda
<a name="delete-function"></a>

Bangun [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html)objek dan panggil `deleteFunction` metodenya. Buat [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/DeleteFunctionRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/model/DeleteFunctionRequest.html)objek dan berikan ke `deleteFunction` metode. Objek ini berisi informasi seperti nama fungsi yang akan dihapus. Nama fungsi muncul sebagai *arn:aws:lambda:us-east* - 1:123456789012: function:. HelloFunction Anda dapat mengambil nilai dengan melihat fungsi di. Konsol Manajemen AWS

 **Impor** 

```
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest;
import software.amazon.awssdk.services.lambda.model.LambdaException;
```

 **Kode** 

Kode Java berikut menunjukkan cara menghapus Lambda fungsi.

```
    public static void deleteLambdaFunction(LambdaClient awsLambda, String functionName ) {
        try {
            DeleteFunctionRequest request = DeleteFunctionRequest.builder()
                    .functionName(functionName)
                    .build();

            awsLambda.deleteFunction(request);
            System.out.println("The "+functionName +" function was deleted");

        } catch(LambdaException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/DeleteFunction.java) di GitHub.

# Bekerja dengan Amazon S3
<a name="examples-s3"></a>

Bagian ini memberikan informasi latar belakang untuk bekerja dengan Amazon S3 dengan menggunakan file. AWS SDK for Java 2.x Bagian ini melengkapi contoh [Amazon S3 Java v2](java_s3_code_examples.md) yang disajikan di *bagian Contoh kode* panduan ini.

## Klien S3 di AWS SDK for Java 2.x
<a name="s3-clients"></a>

 AWS SDK for Java 2.x Menyediakan berbagai jenis klien S3. Tabel berikut menunjukkan perbedaan dan dapat membantu Anda memutuskan apa yang terbaik untuk kasus penggunaan Anda.


**Rasa yang berbeda dari klien Amazon S3**  

| Klien S3 | Deskripsi singkat | Kapan harus digunakan | Batasan/kelemahan | 
| --- | --- | --- | --- | 
|  **AWS Klien S3 berbasis CRT** Antarmuka: [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Pembangun: [S3 CrtAsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html) Lihat [Gunakan klien S3 berkinerja: klien S3 berbasis AWS CRT](crt-based-s3-client.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  | 
|  ***Klien asinkron S3 berbasis Java dengan multipart diaktifkan*** Antarmuka: [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Pembangun: [S3 AsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html) Lihat [Konfigurasikan klien async S3 berbasis Java untuk menggunakan transfer paralel](s3-async-client-multipart.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  | Kinerja kurang dari klien S3 AWS berbasis CRT. | 
|  ***Klien asinkron S3 berbasis Java tanpa multipart diaktifkan*** Antarmuka: [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Pembangun: [S3 AsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Tidak ada optimasi kinerja.  | 
|  **Klien sinkronisasi S3 berbasis Java** Antarmuka: [S3Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) Pembangun: [S3 ClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3ClientBuilder.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Tidak ada optimasi kinerja.  | 

**catatan**  
Dari versi 2.18.x dan seterusnya, AWS SDK for Java 2.x menggunakan [pengalamatan bergaya host virtual saat menyertakan penggantian titik akhir](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access). Ini berlaku selama nama bucket adalah label DNS yang valid.   
Panggil [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3BaseClientBuilder.html#forcePathStyle(java.lang.Boolean](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3BaseClientBuilder.html#forcePathStyle(java.lang.Boolean)metode dengan `true` pembuat klien Anda untuk memaksa klien menggunakan pengalamatan gaya jalur untuk bucket.  
Contoh berikut menunjukkan klien layanan yang dikonfigurasi dengan penggantian titik akhir dan menggunakan pengalamatan gaya jalur.  

```
S3Client client = S3Client.builder()
                          .region(Region.US_WEST_2)
                          .endpointOverride(URI.create("https://s3.us-west-2.amazonaws.com"))
                          .forcePathStyle(true)
                          .build();
```

**Topics**
+ [Klien S3 di SDK](#s3-clients)
+ [Mengunggah stream ke S3](best-practices-s3-uploads.md)
+ [Pra-ditandatangani URLs](examples-s3-presign.md)
+ [Akses Lintas Wilayah](s3-cross-region.md)
+ [Perlindungan integritas data dengan checksum](s3-checksums.md)
+ [Gunakan klien S3 yang berkinerja](crt-based-s3-client.md)
+ [Konfigurasikan dukungan transfer paralel](s3-async-client-multipart.md)
+ [Transfer file dan direktori](transfer-manager.md)
+ [Notifikasi Peristiwa S3](examples-s3-event-notifications.md)

# Mengunggah streaming ke Amazon S3 menggunakan AWS SDK for Java 2.x
<a name="best-practices-s3-uploads"></a>

Saat Anda menggunakan streaming untuk mengunggah konten ke S3 menggunakan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest,software.amazon.awssdk.core.sync.RequestBody)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest,software.amazon.awssdk.core.sync.RequestBody))atau [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest,software.amazon.awssdk.core.sync.RequestBody)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest,software.amazon.awssdk.core.sync.RequestBody)), Anda menggunakan kelas `RequestBody` pabrik untuk API sinkron untuk memasok aliran. Untuk API asinkron, `AsyncRequestBody` ini adalah kelas pabrik yang setara.

## Metode mana yang mengunggah aliran?
<a name="s3-stream-upload-methods"></a>

Untuk API sinkron, Anda dapat menggunakan metode pabrik berikut `RequestBody` untuk memasok aliran:
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromInputStream(java.io.InputStream,long))(InputStream inputStream, long contentLength)`

  `[fromContentProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromContentProvider(software.amazon.awssdk.http.ContentStreamProvider,long,java.lang.String))(ContentStreamProvider provider, long contentLength, String mimeType)`
  + `ContentStreamProvider`Memiliki metode `fromInputStream(InputStream inputStream)` pabrik
+ `[fromContentProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromContentProvider(software.amazon.awssdk.http.ContentStreamProvider,java.lang.String))(ContentStreamProvider provider, String mimeType)`

Untuk API asinkron, Anda dapat menggunakan metode pabrik berikut: `AsyncRequestBody`
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(java.io.InputStream,java.lang.Long,java.util.concurrent.ExecutorService))(InputStream inputStream, Long contentLength, ExecutorService executor)` 
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(software.amazon.awssdk.core.async.AsyncRequestBodyFromInputStreamConfiguration))(AsyncRequestBodyFromInputStreamConfiguration configuration)`
  + Anda menggunakan AsyncRequestBodyFromInputStreamConfiguration .Builder untuk memasok aliran
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(java.util.function.Consumer))(Consumer<AsyncRequestBodyFromInputStreamConfiguration.Builder> configuration)`
+ `[forBlockingInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#forBlockingInputStream(java.lang.Long))(Long contentLength)`
  + Hasilnya `[BlockingInputStreamAsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.html)` berisi metode `writeInputStream(InputStream inputStream)` yang dapat Anda gunakan untuk menyediakan aliran

## Melakukan upload
<a name="s3-upload-stream-perform"></a>

### Jika Anda tahu panjang aliran
<a name="s3-stream-upload-supply-content-length"></a>

Seperti yang Anda lihat dari tanda tangan metode yang ditunjukkan sebelumnya, sebagian besar metode menerima parameter panjang konten. 

Jika Anda mengetahui panjang konten dalam byte, berikan nilai yang tepat:

```
// Always provide the exact content length when it's available.
long contentLength = 1024; // Exact size in bytes.
s3Client.putObject(req -> req
    .bucket("amzn-s3-demo-bucket")
    .key("my-key"),
RequestBody.fromInputStream(inputStream, contentLength));
```

**Awas**  
 Saat mengunggah dari aliran input, jika panjang konten yang ditentukan tidak sesuai dengan jumlah byte yang sebenarnya, Anda mungkin mengalami:  
Objek terpotong jika panjang yang Anda tentukan terlalu kecil
Gagal mengunggah atau menggantung koneksi jika panjang yang Anda tentukan terlalu besar

### Jika Anda tidak tahu panjang aliran
<a name="s3-stream-upload-unknown-length"></a>

#### Menggunakan API sinkron
<a name="s3-upload-unknown-sync-client"></a>

Gunakan`fromContentProvider(ContentStreamProvider provider, String mimeType)`:

```
public PutObjectResponse syncClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3Client s3Client = S3Client.create();

    RequestBody body = RequestBody.fromContentProvider(ContentStreamProvider.fromInputStream(inputStream), "text/plain");
    PutObjectResponse putObjectResponse = s3Client.putObject(b -> b.bucket(BUCKET_NAME).key(KEY_NAME), body);
    return putObjectResponse;
}
```

Karena SDK menyangga seluruh aliran dalam memori untuk menghitung panjang konten, Anda dapat mengalami masalah memori dengan aliran besar. Jika Anda perlu mengunggah aliran besar dengan klien sinkron, pertimbangkan untuk menggunakan API multibagian:

##### Unggah aliran menggunakan API klien sinkron dan API multibagian
<a name="sync-multipart-upload-stream"></a>

```
public static void uploadStreamToS3(String bucketName, String key, InputStream inputStream) {
    // Create S3 client
    S3Client s3Client = S3Client.create();
    try {
        // Step 1: Initiate the multipart upload
        CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();

        CreateMultipartUploadResponse createResponse = s3Client.createMultipartUpload(createMultipartUploadRequest);
        String uploadId = createResponse.uploadId();
        System.out.println("Started multipart upload with ID: " + uploadId);

        // Step 2: Upload parts
        List<CompletedPart> completedParts = new ArrayList<>();
        int partNumber = 1;
        byte[] buffer = new byte[PART_SIZE];
        int bytesRead;

        try {
            while ((bytesRead = readFullyOrToEnd(inputStream, buffer)) > 0) {
                // Create request to upload a part
                UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
                        .bucket(bucketName)
                        .key(key)
                        .uploadId(uploadId)
                        .partNumber(partNumber)
                        .build();

                // If we didn't read a full buffer, create a properly sized byte array
                RequestBody requestBody;
                if (bytesRead < PART_SIZE) {
                    byte[] lastPartBuffer = new byte[bytesRead];
                    System.arraycopy(buffer, 0, lastPartBuffer, 0, bytesRead);
                    requestBody = RequestBody.fromBytes(lastPartBuffer);
                } else {
                    requestBody = RequestBody.fromBytes(buffer);
                }

                // Upload the part and save the response's ETag
                UploadPartResponse uploadPartResponse = s3Client.uploadPart(uploadPartRequest, requestBody);
                CompletedPart part = CompletedPart.builder()
                        .partNumber(partNumber)
                        .eTag(uploadPartResponse.eTag())
                        .build();
                completedParts.add(part);

                System.out.println("Uploaded part " + partNumber + " with size " + bytesRead + " bytes");
                partNumber++;
            }

            // Step 3: Complete the multipart upload
            CompletedMultipartUpload completedMultipartUpload = CompletedMultipartUpload.builder()
                    .parts(completedParts)
                    .build();

            CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .multipartUpload(completedMultipartUpload)
                    .build();

            CompleteMultipartUploadResponse completeResponse = s3Client.completeMultipartUpload(completeRequest);
            System.out.println("Multipart upload completed. Object URL: " + completeResponse.location());

        } catch (Exception e) {
            // If an error occurs, abort the multipart upload
            System.err.println("Error during multipart upload: " + e.getMessage());
            AbortMultipartUploadRequest abortRequest = AbortMultipartUploadRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .build();
            s3Client.abortMultipartUpload(abortRequest);
            System.err.println("Multipart upload aborted");
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                System.err.println("Error closing input stream: " + e.getMessage());
            }
        }
    } finally {
        s3Client.close();
    }
}

/**
 * Reads from the input stream into the buffer, attempting to fill the buffer completely
 * or until the end of the stream is reached.
 *
 * @param inputStream the input stream to read from
 * @param buffer      the buffer to fill
 * @return the number of bytes read, or -1 if the end of the stream is reached before any bytes are read
 * @throws IOException if an I/O error occurs
 */
private static int readFullyOrToEnd(InputStream inputStream, byte[] buffer) throws IOException {
    int totalBytesRead = 0;
    int bytesRead;

    while (totalBytesRead < buffer.length) {
        bytesRead = inputStream.read(buffer, totalBytesRead, buffer.length - totalBytesRead);
        if (bytesRead == -1) {
            break; // End of stream
        }
        totalBytesRead += bytesRead;
    }

    return totalBytesRead > 0 ? totalBytesRead : -1;
}
```

**catatan**  
Untuk sebagian besar kasus penggunaan, sebaiknya gunakan API klien asinkron untuk aliran dengan ukuran yang tidak diketahui. Pendekatan ini memungkinkan transfer paralel dan menawarkan antarmuka pemrograman yang lebih sederhana, karena SDK menangani segmentasi aliran menjadi potongan multibagian jika alirannya besar.   
Baik klien asinkron S3 standar dengan multipart diaktifkan dan klien S3 berbasis AWS CRT menerapkan pendekatan ini. Kami menunjukkan contoh pendekatan ini di bagian berikut.

#### Menggunakan API asinkron
<a name="s3-stream-upload-unknown-async-client"></a>

Anda dapat memberikan `null` `contentLength` argumen untuk `fromInputStream(InputStream inputStream, Long contentLength, ExecutorService executor)`

**Example menggunakan klien AWS asinkron berbasis CRT:**  

```
public PutObjectResponse crtClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor);  // 'null' indicates that the
                                                                                            // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null){
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

**Example menggunakan klien asinkron standar dengan multipart diaktifkan:**  

```
public PutObjectResponse asyncClient_multipart_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.builder().multipartEnabled(true).build();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); // 'null' indicates that the
                                                                                           // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null) {
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

# Bekerja dengan Amazon S3 pra-ditandatangani URLs
<a name="examples-s3-presign"></a>

Pra-ditandatangani URLs menyediakan akses sementara ke objek S3 pribadi tanpa mengharuskan pengguna memiliki AWS kredensi atau izin. 

Misalnya, asumsikan Alice memiliki akses ke objek S3, dan dia ingin sementara berbagi akses ke objek itu dengan Bob. Alice dapat membuat permintaan GET yang telah ditandatangani sebelumnya untuk dibagikan dengan Bob sehingga ia dapat mengunduh objek tanpa memerlukan akses ke kredensi Alice. Anda dapat membuat pra-ditandatangani URLs untuk HTTP GET dan untuk permintaan HTTP PUT.

## Buat URL yang telah ditandatangani sebelumnya untuk suatu objek, lalu unduh (GET request)
<a name="get-presignedobject"></a>

Contoh berikut terdiri dari dua bagian.
+ Bagian 1: Alice menghasilkan URL yang telah ditandatangani sebelumnya untuk suatu objek.
+ Bagian 2: Bob mengunduh objek dengan menggunakan URL yang telah ditandatangani sebelumnya.

### Bagian 1: Menghasilkan URL
<a name="get-presigned-object-part1"></a>

Alice sudah memiliki objek di ember S3. Dia menggunakan kode berikut untuk menghasilkan string URL yang dapat digunakan Bob dalam permintaan GET berikutnya.

#### Impor
<a name="get-presigned-example-imports"></a>

```
import com.example.s3.util.PresignUrlUtils;
import org.slf4j.Logger;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
import software.amazon.awssdk.utils.IoUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.UUID;
```

```
    /* Create a pre-signed URL to download an object in a subsequent GET request. */
    public String createPresignedGetUrl(String bucketName, String keyName) {
        try (S3Presigner presigner = S3Presigner.create()) {

            GetObjectRequest objectRequest = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(keyName)
                    .build();

            GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofMinutes(10))  // The URL will expire in 10 minutes.
                    .getObjectRequest(objectRequest)
                    .build();

            PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest);
            logger.info("Presigned URL: [{}]", presignedRequest.url().toString());
            logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method());

            return presignedRequest.url().toExternalForm();
        }
    }
```

### Bagian 2: Unduh objek
<a name="get-presigned-object-part2"></a>

Bob menggunakan salah satu dari tiga opsi kode berikut untuk mengunduh objek. Atau, dia bisa menggunakan browser untuk melakukan permintaan GET.

#### Gunakan JDK `HttpURLConnection` (sejak v1.1)
<a name="get-presigned-example-useHttpUrlConnection"></a>

```
    /* Use the JDK HttpURLConnection (since v1.1) class to do the download. */
    public byte[] useHttpUrlConnectionToGet(String presignedUrlString) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.

        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection();
            connection.setRequestMethod("GET");
            // Download the result of executing the request.
            try (InputStream content = connection.getInputStream()) {
                IoUtils.copy(content, byteArrayOutputStream);
            }
            logger.info("HTTP response code is " + connection.getResponseCode());

        } catch (S3Exception | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

#### Gunakan JDK `HttpClient` (sejak v11)
<a name="get-presigned-example-useHttpClient"></a>

```
    /* Use the JDK HttpClient (since v11) class to do the download. */
    public byte[] useHttpClientToGet(String presignedUrlString) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
        HttpClient httpClient = HttpClient.newHttpClient();
        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpResponse<InputStream> response = httpClient.send(requestBuilder
                            .uri(presignedUrl.toURI())
                            .GET()
                            .build(),
                    HttpResponse.BodyHandlers.ofInputStream());

            IoUtils.copy(response.body(), byteArrayOutputStream);

            logger.info("HTTP response code is " + response.statusCode());

        } catch (URISyntaxException | InterruptedException | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

#### Gunakan `SdkHttpClient` dari SDK for Java
<a name="get-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java SdkHttpClient class to do the download. */
    public byte[] useSdkHttpClientToGet(String presignedUrlString) {

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.
        try {
            URL presignedUrl = new URL(presignedUrlString);
            SdkHttpRequest request = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.GET)
                    .uri(presignedUrl.toURI())
                    .build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                response.responseBody().ifPresentOrElse(
                        abortableInputStream -> {
                            try {
                                IoUtils.copy(abortableInputStream, byteArrayOutputStream);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        },
                        () -> logger.error("No response body."));

                logger.info("HTTP Response code is {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedGetUrlAndRetrieve.java) dan [uji](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedGetUrlTests.java) GitHub.

## Buat URL yang telah ditandatangani sebelumnya untuk unggahan, lalu unggah file (permintaan PUT)
<a name="put-presignedobject"></a>

Contoh berikut terdiri dari dua bagian.
+ Bagian 1: Alice menghasilkan URL yang telah ditandatangani sebelumnya untuk mengunggah objek.
+ Bagian 2: Bob mengunggah file dengan menggunakan URL yang telah ditandatangani sebelumnya.

### Bagian 1: Menghasilkan URL
<a name="put-presigned-object-part1"></a>

Alice sudah memiliki ember S3. Dia menggunakan kode berikut untuk menghasilkan string URL yang dapat digunakan Bob dalam permintaan PUT berikutnya.

#### Impor
<a name="put-presigned-example-imports"></a>

```
import com.example.s3.util.PresignUrlUtils;
import org.slf4j.Logger;
import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
```

```
    /* Create a presigned URL to use in a subsequent PUT request */
    public String createPresignedUrl(String bucketName, String keyName, Map<String, String> metadata) {
        try (S3Presigner presigner = S3Presigner.create()) {

            PutObjectRequest objectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(keyName)
                    .metadata(metadata)
                    .build();

            PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofMinutes(10))  // The URL expires in 10 minutes.
                    .putObjectRequest(objectRequest)
                    .build();


            PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);
            String myURL = presignedRequest.url().toString();
            logger.info("Presigned URL to upload a file to: [{}]", myURL);
            logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method());

            return presignedRequest.url().toExternalForm();
        }
    }
```

### Bagian 2: Unggah objek file
<a name="put-presigned-object-part2"></a>

Bob menggunakan salah satu dari tiga opsi kode berikut untuk mengunggah file.

#### Gunakan JDK `HttpURLConnection` (sejak v1.1)
<a name="put-presigned-example-useHttpUrlConnection"></a>

```
    /* Use the JDK HttpURLConnection (since v1.1) class to do the upload. */
    public void useHttpUrlConnectionToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());
        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection();
            connection.setDoOutput(true);
            metadata.forEach((k, v) -> connection.setRequestProperty("x-amz-meta-" + k, v));
            connection.setRequestMethod("PUT");
            OutputStream out = connection.getOutputStream();

            try (RandomAccessFile file = new RandomAccessFile(fileToPut, "r");
                 FileChannel inChannel = file.getChannel()) {
                ByteBuffer buffer = ByteBuffer.allocate(8192); //Buffer size is 8k

                while (inChannel.read(buffer) > 0) {
                    buffer.flip();
                    for (int i = 0; i < buffer.limit(); i++) {
                        out.write(buffer.get());
                    }
                    buffer.clear();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }

            out.close();
            connection.getResponseCode();
            logger.info("HTTP response code is " + connection.getResponseCode());

        } catch (S3Exception | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

#### Gunakan JDK `HttpClient` (sejak v11)
<a name="put-presigned-example-useHttpClient"></a>

```
    /* Use the JDK HttpClient (since v11) class to do the upload. */
    public void useHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
        metadata.forEach((k, v) -> requestBuilder.header("x-amz-meta-" + k, v));

        HttpClient httpClient = HttpClient.newHttpClient();
        try {
            final HttpResponse<Void> response = httpClient.send(requestBuilder
                            .uri(new URL(presignedUrlString).toURI())
                            .PUT(HttpRequest.BodyPublishers.ofFile(Path.of(fileToPut.toURI())))
                            .build(),
                    HttpResponse.BodyHandlers.discarding());

            logger.info("HTTP response code is " + response.statusCode());

        } catch (URISyntaxException | InterruptedException | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

#### Gunakan `SdkHttpClient` dari SDK for Java
<a name="put-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java V2 SdkHttpClient class to do the upload. */
    public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());

        try {
            URL presignedUrl = new URL(presignedUrlString);

            SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.PUT)
                    .uri(presignedUrl.toURI());
            // Add headers
            metadata.forEach((k, v) -> requestBuilder.putHeader("x-amz-meta-" + k, v));
            // Finish building the request.
            SdkHttpRequest request = requestBuilder.build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath()))
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                logger.info("Response code: {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java) dan [uji](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedPutUrlTests.java) GitHub.

# Akses Lintas Wilayah untuk Amazon S3
<a name="s3-cross-region"></a>

Saat Anda bekerja dengan bucket Amazon Simple Storage Service (Amazon S3), Anda biasanya tahu Wilayah AWS bucket tersebut. Wilayah tempat Anda bekerja ditentukan saat Anda membuat klien S3. 

Namun, terkadang Anda mungkin perlu bekerja dengan bucket tertentu, tetapi Anda tidak tahu apakah itu terletak di Wilayah yang sama yang ditetapkan untuk klien S3. 

Alih-alih melakukan lebih banyak panggilan untuk menentukan Wilayah bucket, Anda dapat menggunakan SDK untuk mengaktifkan akses ke bucket S3 di berbagai Wilayah.

## Pengaturan
<a name="s3-cross-region-setup"></a>

Support untuk akses lintas wilayah tersedia dengan `2.20.111` versi SDK. Gunakan versi ini atau yang lebih baru di file build Maven Anda untuk `s3` ketergantungan seperti yang ditunjukkan pada cuplikan berikut.

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
```

Selanjutnya, saat Anda membuat klien S3, aktifkan akses lintas wilayah seperti yang ditunjukkan pada cuplikan. Secara default, akses tidak diaktifkan.

```
S3AsyncClient client = S3AsyncClient.builder()
                                    .crossRegionAccessEnabled(true)
                                    .build();
```

## Bagaimana SDK menyediakan akses Lintas wilayah
<a name="s3-cross-region-routing"></a>

Saat Anda mereferensikan bucket yang ada dalam permintaan, seperti saat Anda menggunakan `putObject` metode, SDK akan memulai permintaan ke Wilayah yang dikonfigurasi untuk klien. 

Jika bucket tidak ada di Region tertentu, respons kesalahan menyertakan Region sebenarnya tempat bucket berada. SDK kemudian menggunakan Region yang benar dalam permintaan kedua.

Untuk mengoptimalkan permintaan future ke bucket yang sama, SDK menyimpan pemetaan Region ini di klien.

## Pertimbangan
<a name="s3-cross-region-considerations"></a>

Saat Anda mengaktifkan akses bucket lintas wilayah, ketahuilah bahwa panggilan API pertama dapat meningkatkan latensi jika bucket tidak berada di Region yang dikonfigurasi klien. Namun, panggilan berikutnya mendapat manfaat dari informasi Wilayah yang di-cache, menghasilkan peningkatan kinerja.

Saat Anda mengaktifkan akses lintas wilayah, akses ke bucket tidak terpengaruh. Pengguna harus diberi wewenang untuk mengakses bucket di Wilayah mana pun tempat tinggalnya.

# Perlindungan integritas data dengan checksum
<a name="s3-checksums"></a>

Amazon Simple Storage Service (Amazon S3) menyediakan kemampuan untuk menentukan checksum saat Anda mengunggah objek. Ketika Anda menentukan checksum, itu disimpan dengan objek dan dapat divalidasi ketika objek diunduh.

Checksum menyediakan lapisan integritas data tambahan saat Anda mentransfer file. Dengan checksum, Anda dapat memverifikasi konsistensi data dengan mengonfirmasi bahwa file yang diterima cocok dengan file asli. [Untuk informasi selengkapnya tentang checksum dengan Amazon S3, lihat Panduan [Pengguna Layanan Penyimpanan Sederhana Amazon](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html) termasuk algoritme yang didukung.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#using-additional-checksums)

Anda memiliki fleksibilitas untuk memilih algoritma yang paling sesuai dengan kebutuhan Anda dan membiarkan SDK menghitung checksum. Atau, Anda dapat memberikan nilai checksum yang telah dihitung sebelumnya dengan menggunakan salah satu algoritme yang didukung. 

**catatan**  
Dimulai dengan versi 2.30.0 AWS SDK for Java 2.x, SDK menyediakan perlindungan integritas default dengan menghitung checksum secara otomatis untuk unggahan. `CRC32` SDK menghitung checksum ini jika Anda tidak memberikan nilai checksum yang telah dihitung sebelumnya atau jika Anda tidak menentukan algoritme yang harus digunakan SDK untuk menghitung checksum.   
SDK juga menyediakan pengaturan global untuk perlindungan integritas data yang dapat Anda atur secara eksternal, yang dapat Anda baca di Panduan Referensi Alat [AWS SDKs dan](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html) Alat.

Kami membahas checksum dalam dua fase permintaan: mengunggah objek dan mengunduh objek. 

## Mengunggah objek
<a name="use-service-S3-checksum-upload"></a>

 Saat Anda mengunggah objek dengan `putObject` metode dan menyediakan algoritma checksum, SDK menghitung checksum untuk algoritme yang ditentukan. 

Cuplikan kode berikut menunjukkan permintaan untuk mengunggah objek dengan checksum. `SHA256` Ketika SDK mengirim permintaan, ia menghitung `SHA256` checksum dan mengunggah objek. Amazon S3 memvalidasi integritas konten dengan menghitung checksum dan membandingkannya dengan checksum yang disediakan oleh SDK. Amazon S3 kemudian menyimpan checksum dengan objek.

```
public void putObjectWithChecksum() {
        s3Client.putObject(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA256),
            RequestBody.fromString("This is a test"));
}
```

Jika Anda tidak menyediakan algoritma checksum dengan permintaan, perilaku checksum bervariasi tergantung pada versi SDK yang Anda gunakan seperti yang ditunjukkan pada tabel berikut.

**Perilaku checksum ketika tidak ada algoritma checksum yang disediakan**


| Versi Java SDK | Perilaku checksum | 
| --- | --- | 
| lebih awal dari 2.30.0 | SDK tidak secara otomatis menghitung checksum berbasis CRC dan menyediakannya dalam permintaan. | 
| 2.30.0 atau yang lebih baru | SDK menggunakan `CRC32` algoritma untuk menghitung checksum dan menyediakannya dalam permintaan. Amazon S3 memvalidasi integritas transfer dengan menghitung checksumnya sendiri dan membandingkannya dengan `CRC32` checksum yang disediakan oleh SDK. Jika checksum cocok, checksum disimpan dengan objek. | 

### Gunakan nilai checksum yang telah dihitung sebelumnya
<a name="use-service-S3-checksum-upload-pre"></a>

Nilai checksum yang telah dihitung sebelumnya yang disertakan dengan permintaan menonaktifkan komputasi otomatis oleh SDK dan menggunakan nilai yang disediakan sebagai gantinya.

Contoh berikut menunjukkan permintaan dengan SHA256 checksum yang telah dihitung sebelumnya.

```
    public void putObjectWithPrecalculatedChecksum(String filePath) {
        String checksum = calculateChecksum(filePath, "SHA-256");

        s3Client.putObject((b -> b
                .bucket(bucketName)
                .key(key)
                .checksumSHA256(checksum)),
            RequestBody.fromFile(Paths.get(filePath)));
    }
```

Jika Amazon S3 menentukan nilai checksum salah untuk algoritme yang ditentukan, layanan akan mengembalikan respons kesalahan.

### Unggahan multipart
<a name="use-service-S3-checksum-upload-multi"></a>

Anda juga dapat menggunakan checksum dengan unggahan multipart.

 SDK for Java 2.x menyediakan dua opsi untuk menggunakan checksum dengan unggahan multipart. Opsi pertama menggunakan`S3TransferManager`. 

Contoh manajer transfer berikut menentukan SHA1 algoritma untuk upload.

```
    public void multipartUploadWithChecksumTm(String filePath) {
        S3TransferManager transferManager = S3TransferManager.create();
        UploadFileRequest uploadFileRequest = UploadFileRequest.builder()
            .putObjectRequest(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA1))
            .source(Paths.get(filePath))
            .build();
        FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);
        fileUpload.completionFuture().join();
        transferManager.close();
    }
```

Jika Anda tidak menyediakan algoritma checksum saat menggunakan manajer transfer untuk upload, SDK secara otomatis menghitung dan checksum berdasarkan algoritma. `CRC32` SDK melakukan perhitungan ini untuk semua versi SDK.

Opsi kedua menggunakan [`S3Client`API (atau [`S3AsyncClient`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html)) untuk melakukan pengunggahan multibagian. Jika Anda menentukan checksum dengan pendekatan ini, Anda harus menentukan algoritma yang akan digunakan pada inisiasi unggahan. Anda juga harus menentukan algoritma untuk setiap permintaan bagian dan memberikan checksum yang dihitung untuk setiap bagian setelah diunggah.

```
    public void multipartUploadWithChecksumS3Client(String filePath) {
        ChecksumAlgorithm algorithm = ChecksumAlgorithm.CRC32;

        // Initiate the multipart upload.
        CreateMultipartUploadResponse createMultipartUploadResponse = s3Client.createMultipartUpload(b -> b
            .bucket(bucketName)
            .key(key)
            .checksumAlgorithm(algorithm)); // Checksum specified on initiation.
        String uploadId = createMultipartUploadResponse.uploadId();

        // Upload the parts of the file.
        int partNumber = 1;
        List<CompletedPart> completedParts = new ArrayList<>();
        ByteBuffer bb = ByteBuffer.allocate(1024 * 1024 * 5); // 5 MB byte buffer

        try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
            long fileSize = file.length();
            long position = 0;
            while (position < fileSize) {
                file.seek(position);
                long read = file.getChannel().read(bb);

                bb.flip(); // Swap position and limit before reading from the buffer.
                UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .checksumAlgorithm(algorithm) // Checksum specified on each part.
                    .partNumber(partNumber)
                    .build();

                UploadPartResponse partResponse = s3Client.uploadPart(
                    uploadPartRequest,
                    RequestBody.fromByteBuffer(bb));

                CompletedPart part = CompletedPart.builder()
                    .partNumber(partNumber)
                    .checksumCRC32(partResponse.checksumCRC32()) // Provide the calculated checksum.
                    .eTag(partResponse.eTag())
                    .build();
                completedParts.add(part);

                bb.clear();
                position += read;
                partNumber++;
            }
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }

        // Complete the multipart upload.
        s3Client.completeMultipartUpload(b -> b
            .bucket(bucketName)
            .key(key)
            .uploadId(uploadId)
            .multipartUpload(CompletedMultipartUpload.builder().parts(completedParts).build()));
    }
```

[Kode untuk contoh dan [tes](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/test/java/com/example/s3/PerformMultiPartUploadTests.java) lengkap](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PerformMultiPartUpload.java) ada di repositori contoh GitHub kode.

## Unduh objek
<a name="use-service-S3-checksum-download"></a>

Saat Anda menggunakan metode [getObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest)) untuk mengunduh objek, SDK secara otomatis memvalidasi checksum nilai kuncinya. `ChecksumMode` `enabled` ketika `checksumMode` metode pembangun untuk `GetObjectRequest` diatur ke`ChecksumMode.ENABLED`. 

Permintaan dalam cuplikan berikut mengarahkan SDK untuk memvalidasi checksum dalam respons dengan menghitung checksum dan membandingkan nilainya.

```
    public GetObjectResponse getObjectWithChecksum() {
        return s3Client.getObject(b -> b
                        .bucket(bucketName)
                        .key(key)
                        .checksumMode(ChecksumMode.ENABLED))
                .response();
    }
```

**catatan**  
Jika objek tidak diunggah dengan checksum, tidak ada validasi yang terjadi. 

## Opsi perhitungan checksum lainnya
<a name="S3-checsum-calculation-options"></a>

**catatan**  
Untuk memverifikasi integritas data data yang ditransmisikan dan untuk mengidentifikasi kesalahan transmisi, kami mendorong pengguna untuk menjaga pengaturan default SDK untuk opsi perhitungan checksum. Secara default, SDK menambahkan pemeriksaan penting ini untuk banyak operasi S3 termasuk `PutObject` dan. `GetObject`

Namun, jika penggunaan Amazon S3 memerlukan validasi checksum minimal, Anda dapat menonaktifkan banyak pemeriksaan dengan mengubah pengaturan konfigurasi default. 

### Nonaktifkan perhitungan checksum otomatis kecuali diperlukan
<a name="S3-minimize-checksum-calc-global"></a>

Anda dapat menonaktifkan perhitungan checksum otomatis oleh SDK untuk operasi yang mendukungnya, misalnya `PutObject` dan. `GetObject` Beberapa operasi S3, bagaimanapun, memerlukan perhitungan checksum; Anda tidak dapat menonaktifkan perhitungan checksum untuk operasi ini.

SDK menyediakan pengaturan terpisah untuk perhitungan checksum untuk muatan permintaan dan untuk muatan respons.

Daftar berikut menjelaskan pengaturan yang dapat Anda gunakan untuk meminimalkan perhitungan checksum pada cakupan yang berbeda.
+ **Semua ruang lingkup aplikasi** —Dengan mengubah pengaturan dalam variabel lingkungan atau dalam profil di bersama AWS `config` dan `credentials` file, semua aplikasi dapat menggunakan pengaturan ini. Pengaturan ini memengaruhi semua klien layanan di semua aplikasi AWS SDK kecuali diganti pada cakupan klien aplikasi atau layanan.
  + Tambahkan pengaturan di profil:

    ```
    [default]
    request_checksum_calculation = WHEN_REQUIRED
    response_checksum_validation = WHEN_REQUIRED
    ```
  + Tambahkan variabel lingkungan:

    ```
    AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
    AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED
    ```
+ **Lingkup aplikasi saat ini** —Anda dapat mengatur properti sistem Java `aws.requestChecksumCalculation` `WHEN_REQUIRED` untuk membatasi perhitungan checksum. Properti sistem yang sesuai untuk tanggapan adalah`aws.responseChecksumValidation`.

  Pengaturan ini memengaruhi semua klien layanan SDK dalam aplikasi kecuali diganti selama pembuatan klien layanan.

  Mengatur properti sistem di awal aplikasi Anda:

  ```
  import software.amazon.awssdk.core.SdkSystemSetting;
  import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
  import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
  import software.amazon.awssdk.services.s3.S3Client;
  
  class DemoClass {
      public static void main(String[] args) {
  
          System.setProperty(SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.property(), // Resolves to "aws.requestChecksumCalculation".
                  "WHEN_REQUIRED");
          System.setProperty(SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.property(), // Resolves to "aws.responseChecksumValidation".
                  "WHEN_REQUIRED");
  
          S3Client s3Client = S3Client.builder().build();
  
          // Use s3Client.
      }
  }
  ```
+ **Lingkup klien layanan S3 tunggal** —Anda dapat mengonfigurasi satu klien layanan S3 untuk menghitung jumlah minimum checksum menggunakan metode pembangun:

  ```
  import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
  import software.amazon.awssdk.services.s3.S3Client;
  
  public class RequiredChecksums {
      public static void main(String[] args) {
          S3Client s3 = S3Client.builder()
                  .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
                  .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
                  .build();
  
          // Use s3Client. 
      }
  // ...
  }
  ```

### Gunakan `LegacyMd5Plugin` untuk MD5 kompatibilitas yang disederhanakan
<a name="S3-checksum-legacy-md5"></a>

Seiring dengan rilis perilaku CRC32 checksum dengan versi 2.30.0, SDK berhenti menghitung MD5 checksum pada operasi yang diperlukan.

Jika Anda memerlukan perilaku MD5 checksum lama untuk operasi S3, Anda dapat menggunakan`LegacyMd5Plugin`, yang dirilis dengan SDK versi 2.31.32.

`LegacyMd5Plugin`Ini sangat berguna ketika Anda perlu mempertahankan kompatibilitas dengan aplikasi yang bergantung pada perilaku MD5 checksum lama, terutama ketika bekerja dengan penyedia penyimpanan pihak ketiga yang kompatibel dengan S3 seperti yang digunakan dengan konektor sistem file S3A (Apache Spark, Iceberg).

Untuk menggunakan`LegacyMd5Plugin`, tambahkan ke pembuat klien S3 Anda:

```
// For synchronous S3 client.
S3Client s3Client = S3Client.builder()
                           .addPlugin(LegacyMd5Plugin.create())
                           .build();

// For asynchronous S3 client.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .build();
```

Jika Anda ingin menambahkan MD5 checksum ke operasi yang memerlukan checksum dan ingin melewatkan penambahan checksum default SDK untuk operasi yang mendukung checksum tetapi tidak diperlukan, Anda dapat mengaktifkan opsi dan as. `ClientBuilder` `requestChecksumCalculation` `responseChecksumValidation` `WHEN_REQUIRED` Ini akan menambahkan checksum default SDK hanya untuk operasi yang memerlukan checksum:

```
// Use the `LegacyMd5Plugin` with `requestChecksumCalculation` and `responseChecksumValidation` set to WHEN_REQUIRED.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
                                       .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
                                       .build();
```

Konfigurasi ini sangat berguna ketika bekerja dengan sistem penyimpanan pihak ketiga yang kompatibel dengan S3 yang mungkin tidak sepenuhnya mendukung algoritma checksum yang lebih baru tetapi masih memerlukan MD5 checksum untuk operasi tertentu.

# Gunakan klien S3 berkinerja: klien S3 berbasis AWS CRT
<a name="crt-based-s3-client"></a>

Klien S3 AWS berbasis CRT — dibangun di atas [AWS Common Runtime (CRT) — adalah klien asinkron](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html) S3 alternatif. [Ini mentransfer objek ke dan dari Amazon Simple Storage Service (Amazon S3) Simple Storage Service (Amazon S3) dengan peningkatan kinerja dan keandalan dengan secara otomatis menggunakan API unggahan [multipart Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) dan pengambilan rentang byte.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range) 

Klien S3 AWS berbasis CRT meningkatkan keandalan transfer jika ada kegagalan jaringan. Keandalan ditingkatkan dengan mencoba kembali bagian-bagian individual yang gagal dari transfer file tanpa memulai ulang transfer dari awal.

Selain itu, klien S3 AWS berbasis CRT menawarkan penyatuan koneksi yang ditingkatkan dan penyeimbangan beban Sistem Nama Domain (DNS), yang juga meningkatkan throughput.

Anda dapat menggunakan klien S3 AWS berbasis CRT sebagai pengganti klien asinkron S3 standar SDK dan segera memanfaatkan throughputnya yang ditingkatkan.

**penting**  
Klien S3 AWS berbasis CRT saat ini tidak mendukung [pengumpulan metrik SDK](metrics.md) di tingkat klien maupun di tingkat permintaan.

**AWS Komponen berbasis CRT di SDK**

Klien *S3 AWS * berbasis CRT, dijelaskan dalam topik ini, dan klien *HTTP AWS * berbasis CRT adalah komponen yang berbeda dalam SDK. 

**Klien S3 AWS berbasis CRT** adalah implementasi AsyncClient antarmuka [S3](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) dan digunakan untuk bekerja dengan layanan Amazon S3. Ini adalah alternatif untuk implementasi `S3AsyncClient` antarmuka berbasis Java dan menawarkan beberapa manfaat.

[Client HTTP AWS berbasis CRT](http-configuration-crt.md) adalah implementasi [SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)antarmuka dan digunakan untuk komunikasi HTTP umum. Ini adalah alternatif untuk implementasi `SdkAsyncHttpClient` antarmuka Netty dan menawarkan beberapa keuntungan.

Meskipun kedua komponen menggunakan pustaka dari [AWS Common Runtime](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html), klien S3 AWS berbasis CRT menggunakan [pustaka aws-c-s 3](https://github.com/awslabs/aws-c-s3) dan mendukung fitur API unggahan multipart [S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html). Karena klien HTTP AWS berbasis CRT dimaksudkan untuk penggunaan tujuan umum, itu tidak mendukung fitur API unggahan multibagian S3.

## Tambahkan dependensi untuk menggunakan klien S3 berbasis AWS CRT
<a name="crt-based-s3-client-depend"></a>

Untuk menggunakan klien S3 AWS berbasis CRT, tambahkan dua dependensi berikut ke file proyek Maven Anda. Contoh menunjukkan versi minimum yang akan digunakan. [Cari repositori pusat Maven untuk versi terbaru dari artefak [s3](https://central.sonatype.com/artifact/software.amazon.awssdk/s3) dan aws-crt.](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt)

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
<dependency>
  <groupId>software.amazon.awssdk.crt</groupId>
  <artifactId>aws-crt</artifactId>
  <version>0.30.11</version>
</dependency>
```

## Buat instance klien S3 AWS berbasis CRT
<a name="crt-based-s3-client-create"></a>

 Buat instance klien S3 AWS berbasis CRT dengan pengaturan default seperti yang ditunjukkan pada cuplikan kode berikut.

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
```

Untuk mengkonfigurasi klien, gunakan pembuat klien AWS CRT. Anda dapat beralih dari klien asinkron S3 standar ke klien AWS berbasis CRT dengan mengubah metode pembangun.

```
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;


S3AsyncClient s3AsyncClient = 
        S3AsyncClient.crtBuilder()
                     .credentialsProvider(DefaultCredentialsProvider.create())
                     .region(Region.US_WEST_2)
                     .targetThroughputInGbps(20.0)
                     .minimumPartSizeInBytes(8 * 1025 * 1024L)
                     .build();
```

**catatan**  
Beberapa pengaturan di pembuat standar mungkin saat ini tidak didukung di pembuat klien AWS CRT. Dapatkan pembangun standar dengan menelepon`S3AsyncClient#builder()`.

## Gunakan klien AWS S3 berbasis CRT
<a name="crt-based-s3-client-use"></a>

Gunakan klien S3 AWS berbasis CRT untuk memanggil operasi API Amazon S3. Contoh berikut menunjukkan [PutObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html#putObject(java.util.function.Consumer,software.amazon.awssdk.core.async.AsyncRequestBody))dan [GetObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html#getObject(java.util.function.Consumer,software.amazon.awssdk.core.async.AsyncResponseTransformer))operasi yang tersedia melalui. AWS SDK untuk Java

```
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;


S3AsyncClient s3Client = S3AsyncClient.crtCreate();

// Upload a local file to Amazon S3.
PutObjectResponse putObjectResponse = 
      s3Client.putObject(req -> req.bucket(<BUCKET_NAME>)
                                   .key(<KEY_NAME>),
                        AsyncRequestBody.fromFile(Paths.get(<FILE_NAME>)))
              .join();

// Download an object from Amazon S3 to a local file.
GetObjectResponse getObjectResponse = 
      s3Client.getObject(req -> req.bucket(<BUCKET_NAME>)
                                   .key(<KEY_NAME>),
                        AsyncResponseTransformer.toFile(Paths.get(<FILE_NAME>)))
              .join();
```

## Mengunggah aliran dengan ukuran yang tidak diketahui
<a name="crt-stream-unknown-size"></a>

Salah satu keuntungan signifikan dari klien S3 AWS AWS berbasis CRT adalah kemampuannya untuk menangani aliran input dengan ukuran yang tidak diketahui secara efisien. Ini sangat berguna ketika Anda perlu mengunggah data dari sumber di mana ukuran totalnya tidak dapat ditentukan sebelumnya.

```
public PutObjectResponse crtClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor);  // 'null' indicates that the
                                                                                            // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null){
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

Kemampuan ini membantu menghindari masalah umum dengan unggahan tradisional di mana spesifikasi panjang konten yang salah dapat menyebabkan objek terpotong atau unggahan gagal.

## Batasan konfigurasi
<a name="crt-based-s3-client-limitations"></a>

Klien S3 AWS berbasis CRT dan klien async S3 berbasis Java [menyediakan fitur yang sebanding](examples-s3.md#s3-clients), dengan klien S3 berbasis CRT yang menawarkan keunggulan kinerja. AWS Namun, klien S3 AWS berbasis CRT tidak memiliki pengaturan konfigurasi yang dimiliki klien async S3 berbasis Java. Pengaturan ini meliputi:
+ *Konfigurasi tingkat klien:* Batas waktu upaya panggilan API, pencegat eksekusi kompresi, penerbit metrik, atribut eksekusi kustom, opsi lanjutan khusus, layanan pelaksana terjadwal khusus, header khusus
+ *Konfigurasi tingkat permintaan:* penandatangan khusus, batas waktu upaya panggilan API

Untuk daftar lengkap perbedaan konfigurasi, lihat referensi API.


| Klien asinkron S3 berbasis Java | AWS Klien S3 berbasis CRT | 
| --- | --- | 
| Konfigurasi tingkat klien[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Konfigurasi tingkat permintaan[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | Konfigurasi tingkat klien[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Konfigurasi tingkat permintaan[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/id_id/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | 

# Konfigurasikan klien async S3 berbasis Java untuk menggunakan transfer paralel
<a name="s3-async-client-multipart"></a>

Sejak versi 2.27.5, klien async S3 berbasis Java standar mendukung transfer paralel otomatis (unggahan dan unduhan multipart). Anda mengonfigurasi dukungan untuk transfer paralel saat membuat klien asinkron S3 berbasis Java. 

Bagian ini menunjukkan cara mengaktifkan transfer paralel dan cara menyesuaikan konfigurasi.

## Buat sebuah instance dari `S3AsyncClient`
<a name="s3-async-client-multipart-create"></a>

Saat Anda membuat `S3AsyncClient` instance tanpa memanggil `multipart*` metode apa pun di [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html), transfer paralel tidak diaktifkan. Setiap pernyataan berikut membuat klien asinkron S3 berbasis Java tanpa dukungan untuk unggahan dan unduhan multibagian.

### Buat *tanpa dukungan* multipart
<a name="s3-async-client-mp-off"></a>

**Example**  

```
import software.amazon.awssdk.auth.credentials.ProcessCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;


S3AsyncClient s3Client = S3AsyncClient.create();

S3AsyncClient s3Client2 = S3AsyncClient.builder().build();

S3AsyncClient s3Client3 = S3AsyncClient.builder()
        .credentialsProvider(ProcessCredentialsProvider.builder().build())
        .region(Region.EU_NORTH_1)
        .build();
```

### Buat *dengan dukungan* multipart
<a name="s3-async-client-mp-on"></a>

Untuk mengaktifkan transfer paralel dengan pengaturan default, panggil `multipartEnabled` pembangun dan teruskan `true` seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartEnabled(true)
        .build();
```

Nilai default adalah 8 MiB untuk `thresholdInBytes` dan `minimumPartSizeInBytes` pengaturan.

Jika Anda menyesuaikan pengaturan multipart, transfer paralel secara otomatis diaktifkan seperti yang ditunjukkan pada berikut ini.

**Example**  

```
import software.amazon.awssdk.services.s3.S3AsyncClient;
import static software.amazon.awssdk.transfer.s3.SizeConstant.MB;


S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartConfiguration(b -> b
                .thresholdInBytes(16 * MB)
                .minimumPartSizeInBytes(10 * MB))
        .build();
```

## Mengunggah aliran dengan ukuran yang tidak diketahui
<a name="java-async-client-stream-unknown-size"></a>

Klien asinkron S3 berbasis Java dengan multipart diaktifkan dapat secara efisien menangani aliran input di mana ukuran total tidak diketahui sebelumnya:

```
public PutObjectResponse asyncClient_multipart_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.builder().multipartEnabled(true).build();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); // 'null' indicates that the
                                                                                           // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null) {
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

Pendekatan ini mencegah masalah yang dapat terjadi saat menentukan panjang konten yang salah secara manual, seperti objek terpotong atau unggahan yang gagal.

# Transfer file dan direktori dengan Amazon S3 Transfer Manager
<a name="transfer-manager"></a>

Amazon S3 Transfer Manager adalah sumber terbuka, utilitas transfer file tingkat tinggi untuk file. AWS SDK for Java 2.x Gunakan untuk mentransfer file dan direktori ke dan dari Amazon Simple Storage Service (Amazon S3). 

[https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) 

Dengan S3 Transfer Manager, Anda juga dapat memantau kemajuan transfer secara real time dan menjeda transfer untuk eksekusi nanti.

## Memulai
<a name="transfer-manager-prerequisites"></a>

### Tambahkan dependensi ke file build
<a name="transfer-manager-add-dependency"></a>

Untuk menggunakan S3 Transfer Manager dengan performa multipart yang disempurnakan, konfigurasikan file build Anda dengan dependensi yang diperlukan.

------
#### [ Use the AWS CRT-based S3 client ]

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.27.211</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-transfer-manager</artifactId>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk.crt</groupId>
        <artifactId>aws-crt</artifactId>
        <version>0.29.1432</version>
    </dependency>
</dependencies>
```

1 [Versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom). 2 [Versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt).

------
#### [ Use the Java-based S3 async client ]

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.27.211</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-transfer-manager</artifactId>
    </dependency>
</dependencies>
```

1 [Versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

------

### Buat instance dari S3 Transfer Manager
<a name="transfer-manager-create"></a>

Untuk mengaktifkan transfer paralel, Anda harus meneruskan klien S3 AWS berbasis CRT ATAU klien async S3 berbasis Java dengan multipart diaktifkan. Contoh berikut menunjukkan cara mengkonfigurasi Manajer Transfer S3 dengan pengaturan khusus. 

------
#### [ Use the AWS CRT-based S3 client ]

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .targetThroughputInGbps(20.0)
                .minimumPartSizeInBytes(8 * MB)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

------
#### [ Use the Java-based S3 async client ]

Jika `aws-crt` dependensi tidak disertakan dalam file build, S3 Transfer Manager dibangun di atas klien async S3 berbasis Java standar yang digunakan dalam SDK for Java 2.x. 

**Konfigurasi kustom klien S3 - memerlukan multipart diaktifkan**

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
                .multipartEnabled(true)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

**Tidak ada konfigurasi klien S3 - dukungan multipart diaktifkan secara otomatis**

```
S3TransferManager transferManager = S3TransferManager.create();
```

------

## Unggah file ke bucket S3
<a name="transfer-manager-upload"></a>

Contoh berikut menunjukkan contoh upload file bersama dengan penggunaan opsional dari [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), yang mencatat kemajuan upload.

[Untuk mengunggah file ke Amazon S3 menggunakan S3 Transfer Manager, teruskan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadFileRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadFileRequest.html)objek ke metode UploadFile. `S3TransferManager`](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadFile(software.amazon.awssdk.transfer.s3.model.UploadFileRequest))

[FileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileUpload.html)Objek yang dikembalikan dari `uploadFile` metode mewakili proses upload. Setelah permintaan selesai, [CompletedFileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileUpload.html)objek berisi informasi tentang unggahan.

```
    public void trackUploadFile(S3TransferManager transferManager, String bucketName,
                             String key, URI filePathURI) {
        UploadFileRequest uploadFileRequest = UploadFileRequest.builder()
                .putObjectRequest(b -> b.bucket(bucketName).key(key))
                .addTransferListener(LoggingTransferListener.create())  // Add listener.
                .source(Paths.get(filePathURI))
                .build();

        FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);

        fileUpload.completionFuture().join();
        /*
            The SDK provides a LoggingTransferListener implementation of the TransferListener interface.
            You can also implement the interface to provide your own logic.

            Configure log4J2 with settings such as the following.
                <Configuration status="WARN">
                    <Appenders>
                        <Console name="AlignedConsoleAppender" target="SYSTEM_OUT">
                            <PatternLayout pattern="%m%n"/>
                        </Console>
                    </Appenders>

                    <Loggers>
                        <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false">
                            <AppenderRef ref="AlignedConsoleAppender"/>
                        </logger>
                    </Loggers>
                </Configuration>

            Log4J2 logs the progress. The following is example output for a 21.3 MB file upload.
                Transfer initiated...
                |                    | 0.0%
                |====                | 21.1%
                |============        | 60.5%
                |====================| 100.0%
                Transfer complete!
        */
    }
```

### Impor
<a name="transfer-manager-upload-imports"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload;
import software.amazon.awssdk.transfer.s3.model.FileUpload;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.UUID;
```

## Unduh file dari ember S3
<a name="transfer-manager-download"></a>

Contoh berikut menunjukkan contoh download bersama dengan penggunaan opsional dari [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), yang mencatat kemajuan download.

Untuk mengunduh objek dari bucket S3 menggunakan S3 Transfer Manager, buat [DownloadFileRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadFileRequest.html)objek dan teruskan ke metode [DownloadFile](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadFile(software.amazon.awssdk.transfer.s3.model.DownloadFileRequest)).

[FileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileDownload.html)Objek yang `S3TransferManager` dikembalikan oleh `downloadFile` metode ini mewakili transfer file. Setelah unduhan selesai, [CompletedFileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileDownload.html)berisi akses ke informasi tentang unduhan.

```
    public void trackDownloadFile(S3TransferManager transferManager, String bucketName,
                             String key, String downloadedFileWithPath) {
        DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder()
                .getObjectRequest(b -> b.bucket(bucketName).key(key))
                .addTransferListener(LoggingTransferListener.create())  // Add listener.
                .destination(Paths.get(downloadedFileWithPath))
                .build();

        FileDownload downloadFile = transferManager.downloadFile(downloadFileRequest);

        CompletedFileDownload downloadResult = downloadFile.completionFuture().join();
        /*
            The SDK provides a LoggingTransferListener implementation of the TransferListener interface.
            You can also implement the interface to provide your own logic.

            Configure log4J2 with settings such as the following.
                <Configuration status="WARN">
                    <Appenders>
                        <Console name="AlignedConsoleAppender" target="SYSTEM_OUT">
                            <PatternLayout pattern="%m%n"/>
                        </Console>
                    </Appenders>

                    <Loggers>
                        <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false">
                            <AppenderRef ref="AlignedConsoleAppender"/>
                        </logger>
                    </Loggers>
                </Configuration>

            Log4J2 logs the progress. The following is example output for a 21.3 MB file download.
                Transfer initiated...
                |=======             | 39.4%
                |===============     | 78.8%
                |====================| 100.0%
                Transfer complete!
        */
    }
```

### Impor
<a name="transfer-manager-download-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.exception.SdkException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload;
import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest;
import software.amazon.awssdk.transfer.s3.model.FileDownload;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
```

## Salin objek Amazon S3 ke ember lain
<a name="transfer-manager-copy"></a>

Contoh berikut menunjukkan cara menyalin objek dengan S3 Transfer Manager.

Untuk memulai salinan objek dari bucket S3 ke bucket lain, buat [CopyObjectRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/CopyObjectRequest.html)instance dasar.

Selanjutnya, bungkus dasar `CopyObjectRequest` dalam [CopyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CopyRequest.html)yang dapat digunakan oleh S3 Transfer Manager. 

`Copy`Objek yang dikembalikan oleh `copy` metode ini mewakili proses penyalinan. `S3TransferManager` Setelah proses penyalinan selesai, [CompletedCopy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedCopy.html)objek berisi detail tentang respons.

```
    public String copyObject(S3TransferManager transferManager, String bucketName,
            String key, String destinationBucket, String destinationKey) {
        CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
                .sourceBucket(bucketName)
                .sourceKey(key)
                .destinationBucket(destinationBucket)
                .destinationKey(destinationKey)
                .build();

        CopyRequest copyRequest = CopyRequest.builder()
                .copyObjectRequest(copyObjectRequest)
                .build();

        Copy copy = transferManager.copy(copyRequest);

        CompletedCopy completedCopy = copy.completionFuture().join();
        return completedCopy.response().copyObjectResult().eTag();
    }
```

**catatan**  
Untuk melakukan salinan Lintas wilayah dengan S3 Transfer Manager, aktifkan `crossRegionAccessEnabled` pada pembuat klien S3 AWS berbasis CRT seperti yang ditunjukkan pada cuplikan berikut.  

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .crossRegionAccessEnabled(true)
                .build();

S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

### Impor
<a name="transfer-manager-copy-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedCopy;
import software.amazon.awssdk.transfer.s3.model.Copy;
import software.amazon.awssdk.transfer.s3.model.CopyRequest;

import java.util.UUID;
```

## Unggah direktori lokal ke bucket S3
<a name="transfer-manager-upload_directory"></a>

Contoh berikut menunjukkan bagaimana Anda dapat meng-upload direktori lokal ke S3.

Mulailah dengan memanggil metode [uploadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadDirectory(software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest)) dari `S3TransferManager` instance, meneruskan file. [UploadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadDirectoryRequest.html)

[DirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryUpload.html)Objek mewakili proses upload, yang menghasilkan [CompletedDirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryUpload.html)ketika permintaan selesai. `CompleteDirectoryUpload`Objek berisi informasi tentang hasil transfer, termasuk file mana yang gagal ditransfer.

```
    public Integer uploadDirectory(S3TransferManager transferManager,
            URI sourceDirectory, String bucketName) {
        DirectoryUpload directoryUpload = transferManager.uploadDirectory(UploadDirectoryRequest.builder()
                .source(Paths.get(sourceDirectory))
                .bucket(bucketName)
                .build());

        CompletedDirectoryUpload completedDirectoryUpload = directoryUpload.completionFuture().join();
        completedDirectoryUpload.failedTransfers()
                .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString()));
        return completedDirectoryUpload.failedTransfers().size();
    }
```

### Impor
<a name="transfer-manager-upload_directory-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryUpload;
import software.amazon.awssdk.transfer.s3.model.DirectoryUpload;
import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.UUID;
```

## Unduh objek bucket S3 ke direktori lokal
<a name="transfer-manager-download_directory"></a>

Anda dapat mengunduh objek dalam bucket S3 ke direktori lokal seperti yang ditunjukkan pada contoh berikut.

Untuk mengunduh objek dalam bucket S3 ke direktori lokal, mulailah dengan memanggil metode [DownloadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadDirectory(software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest)) dari Transfer Manager, meneruskan file. [DownloadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadDirectoryRequest.html)

[DirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryDownload.html)Objek mewakili proses download, yang menghasilkan [CompletedDirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryDownload.html)ketika permintaan selesai. `CompleteDirectoryDownload`Objek berisi informasi tentang hasil transfer, termasuk file mana yang gagal ditransfer.

```
    public Integer downloadObjectsToDirectory(S3TransferManager transferManager,
            URI destinationPathURI, String bucketName) {
        DirectoryDownload directoryDownload = transferManager.downloadDirectory(DownloadDirectoryRequest.builder()
                .destination(Paths.get(destinationPathURI))
                .bucket(bucketName)
                .build());
        CompletedDirectoryDownload completedDirectoryDownload = directoryDownload.completionFuture().join();

        completedDirectoryDownload.failedTransfers()
                .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString()));
        return completedDirectoryDownload.failedTransfers().size();
    }
```

### Impor
<a name="transfer-manager-download_directory-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryDownload;
import software.amazon.awssdk.transfer.s3.model.DirectoryDownload;
import software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
```

## Lihat contoh lengkap
<a name="transfer-manager-example-location"></a>

[GitHub berisi kode lengkap](https://github.com/awsdocs/aws-doc-sdk-examples/tree/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/transfermanager) untuk semua contoh di halaman ini.

# Bekerja dengan Pemberitahuan Acara S3
<a name="examples-s3-event-notifications"></a>

Untuk membantu Anda memantau aktivitas di bucket, Amazon S3 dapat mengirim notifikasi saat peristiwa tertentu terjadi. Panduan Pengguna Amazon S3 memberikan informasi tentang [notifikasi yang dapat dikirimkan bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html#notification-how-to-overview). 

Anda dapat menyiapkan bucket untuk mengirim peristiwa ke empat kemungkinan tujuan menggunakan SDK for Java: 
+ Topik Amazon Simple Notification Service
+ Antrean Amazon Simple Queue Service
+ AWS Lambda fungsi
+ Amazon EventBridge

Saat menyiapkan bucket untuk mengirim acara EventBridge, Anda memiliki kemampuan untuk mengonfigurasi EventBridge aturan untuk meng-fanout acara yang sama ke beberapa tujuan. Saat Anda mengonfigurasi bucket untuk dikirim langsung ke salah satu dari tiga tujuan pertama, hanya satu jenis tujuan yang dapat ditentukan untuk setiap acara.

Di bagian selanjutnya, Anda akan melihat cara mengonfigurasi bucket menggunakan SDK for Java untuk mengirim Pemberitahuan Acara S3 dengan dua cara: langsung ke antrian Amazon SQS dan ke. EventBridge

Bagian terakhir menunjukkan cara menggunakan S3 Event Notifications API untuk bekerja dengan notifikasi dengan cara berorientasi objek.

## Konfigurasikan bucket untuk mengirim langsung ke tujuan
<a name="s3-event-conf-bucket-direct"></a>

Contoh berikut mengonfigurasi bucket untuk mengirim notifikasi saat peristiwa *pembuatan objek* atau peristiwa *penandaan objek* terjadi terhadap bucket.

```
static void processS3Events(String bucketName, String queueArn) {
    // Configure the bucket to send Object Created and Object Tagging notifications to an existing SQS queue.
    s3Client.putBucketNotificationConfiguration(b -> b
            .notificationConfiguration(ncb -> ncb
                    .queueConfigurations(qcb -> qcb
                            .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                            .queueArn(queueArn)))
                    .bucket(bucketName)
    );
}
```

Kode yang ditunjukkan di atas mengatur satu antrian untuk menerima dua jenis acara. Dengan mudah, `queueConfigurations` metode ini memungkinkan Anda untuk mengatur beberapa tujuan antrian jika diperlukan. Selain itu, dalam `notificationConfiguration` metode ini Anda dapat mengatur tujuan tambahan, seperti satu atau beberapa topik Amazon SNS atau satu atau lebih fungsi Lambda. Cuplikan berikut menunjukkan contoh dengan dua antrian dan tiga jenis tujuan.

```
s3Client.putBucketNotificationConfiguration(b -> b
                .notificationConfiguration(ncb -> ncb
                        .queueConfigurations(qcb -> qcb
                                .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                                .queueArn(queueArn), 
                                qcb2 -> qcb2.<...>)
                        .topicConfigurations(tcb -> tcb.<...>)
                        .lambdaFunctionConfigurations(lfcb -> lfcb.<...>))
                        .bucket(bucketName)
        );
```

 GitHub Repositori Contoh Kode berisi [contoh lengkap](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java) untuk mengirim pemberitahuan acara S3 langsung ke antrian.

## Konfigurasikan bucket untuk dikirim EventBridge
<a name="s3-event-conf-bucket-eventbridge"></a>

Contoh berikut mengonfigurasi bucket untuk mengirim notifikasi. EventBridge

```
public static String setBucketNotificationToEventBridge(String bucketName) {
    // Enable bucket to emit S3 Event notifications to EventBridge.
    s3Client.putBucketNotificationConfiguration(b -> b
            .bucket(bucketName)
            .notificationConfiguration(b1 -> b1
                    .eventBridgeConfiguration(SdkBuilder::build))
    .build());
```

Saat Anda mengonfigurasi bucket untuk mengirim acara EventBridge, Anda cukup menunjukkan EventBridge tujuan, bukan jenis acara atau tujuan akhir yang EventBridge akan dikirim. Anda mengonfigurasi target akhir dan jenis acara dengan menggunakan EventBridge klien Java SDK.

Kode berikut menunjukkan cara mengkonfigurasi EventBridge untuk menyebarkan peristiwa yang *dibuat objek* ke topik dan antrian.

```
   public static String configureEventBridge(String topicArn, String queueArn) {
        try {
            // Create an EventBridge rule to route Object Created notifications.
            PutRuleRequest putRuleRequest = PutRuleRequest.builder()
                    .name(RULE_NAME)
                    .eventPattern("""
                            {
                              "source": ["aws.s3"],
                              "detail-type": ["Object Created"],
                              "detail": {
                                "bucket": {
                                  "name": ["%s"]
                                }
                              }
                            }
                            """.formatted(bucketName))
                    .build();

            // Add the rule to the default event bus.
            PutRuleResponse putRuleResponse = eventBridgeClient.putRule(putRuleRequest)
                    .whenComplete((r, t) -> {
                        if (t != null) {
                            logger.error("Error creating event bus rule: " + t.getMessage(), t);
                            throw new RuntimeException(t.getCause().getMessage(), t);
                        }
                        logger.info("Event bus rule creation request sent successfully. ARN is: {}", r.ruleArn());
                    }).join();

            // Add the existing SNS topic and SQS queue as targets to the rule.
            eventBridgeClient.putTargets(b -> b
                    .eventBusName("default")
                    .rule(RULE_NAME)
                    .targets(List.of (
                            Target.builder()
                                    .arn(queueArn)
                                    .id("Queue")
                                    .build(),
                            Target.builder()
                                    .arn(topicArn)
                                    .id("Topic")
                                    .build())
                            )
                    ).join();
            return putRuleResponse.ruleArn();
        } catch (S3Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return null;
    }
```

Untuk bekerja dengan EventBridge kode Java Anda, tambahkan ketergantungan pada `eventbridge` artefak ke file `pom.xml` Maven Anda.

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>eventbridge</artifactId>
</dependency>
```

 GitHub Repositori Contoh Kode berisi [contoh lengkap](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PutBucketS3EventNotificationEventBridge.java) untuk mengirim pemberitahuan acara S3 ke EventBridge dan kemudian ke topik dan antrian.

## Gunakan API Pemberitahuan Acara S3 untuk memproses peristiwa
<a name="s3-event-notification-read"></a>

Setelah tujuan menerima peristiwa notifikasi S3, Anda dapat memprosesnya dengan cara berorientasi objek dengan menggunakan S3 Event Notifications API. Anda dapat menggunakan S3 Event Notifications API untuk bekerja dengan pemberitahuan peristiwa yang dikirim langsung ke target (seperti yang ditunjukkan pada [contoh pertama](#s3-event-conf-bucket-direct)), tetapi tidak dengan notifikasi yang diarahkan. EventBridge Pemberitahuan peristiwa S3 dikirim oleh bucket untuk EventBridge berisi [struktur berbeda](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ev-events.html#ev-events-list) yang saat ini tidak ditangani oleh API Pemberitahuan Acara S3.

### Tambahkan ketergantungan
<a name="s3-event-notifications-dep"></a>

S3 Event Notifications API dirilis dengan SDK for Java 2.x versi 2.25.11.

Untuk menggunakan S3 Event Notifications API, tambahkan elemen dependensi yang diperlukan ke Maven Anda `pom.xml` seperti yang ditunjukkan pada cuplikan berikut.

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.X.X1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-event-notifications</artifactId>
    </dependency>
</dependencies>
```

1 [Versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

### Gunakan `S3EventNotification` kelas
<a name="s3-event-notifications-use"></a>

#### Buat `S3EventNotification` instance dari string JSON
<a name="s3-event-notifications-use-from-json"></a>

Untuk mengkonversi string JSON menjadi `S3EventNotification` objek, menggunakan metode statis `S3EventNotification` kelas seperti yang ditunjukkan pada contoh berikut.

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord
import software.amazon.awssdk.services.sqs.model.Message; 

public class S3EventNotificationExample {
    ...
    
    void receiveMessage(Message message) {
       // Message received from SQSClient.
       String sqsEventBody = message.body();
       S3EventNotification s3EventNotification = S3EventNotification.fromJson(sqsEventBody);
    
       // Use getRecords() to access all the records in the notification.                                                                                                       
       List<S3EventNotificationRecord> records = s3EventNotification.getRecords();   
    
        S3EventNotificationRecord record = records.stream().findFirst();
        // Use getters on the record to access individual attributes.
        String awsRegion = record.getAwsRegion();
        String eventName = record.getEventName();
        String eventSource = record.getEventSource();                                                                                                   
    }
}
```

Dalam contoh ini, `fromJson` metode mengubah string JSON menjadi objek`S3EventNotification`. Bidang yang hilang dalam string JSON akan menghasilkan `null` nilai di bidang objek Java yang sesuai dan bidang tambahan apa pun di JSON akan diabaikan.

Lainnya APIs untuk catatan pemberitahuan peristiwa dapat ditemukan di referensi API untuk`[S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html)`.

#### Mengkonversi `S3EventNotification` instance ke string JSON
<a name="s3-event-notifications-use-to-json"></a>

Gunakan metode `toJson` (or`toJsonPretty`) untuk mengubah `S3EventNotification` objek menjadi string JSON seperti yang ditunjukkan pada contoh berikut.

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification

public class S3EventNotificationExample {
    ...

    void toJsonString(S3EventNotification event) {

        String json = event.toJson();
        String jsonPretty = event.toJsonPretty();

        System.out.println("JSON: " + json);
        System.out.println("Pretty JSON: " + jsonPretty);
    }
}
```

Bidang untuk `GlacierEventData``ReplicationEventData`,`IntelligentTieringEventData`,, dan `LifecycleEventData` dikecualikan dari JSON jika memang `null` demikian. `null`Bidang lainnya akan diserialkan sebagai`null`.

Berikut ini menunjukkan contoh output dari `toJsonPretty` metode untuk peristiwa penandaan objek S3.

```
{
  "Records" : [ {
    "eventVersion" : "2.3",
    "eventSource" : "aws:s3",
    "awsRegion" : "us-east-1",
    "eventTime" : "2024-07-19T20:09:18.551Z",
    "eventName" : "ObjectTagging:Put",
    "userIdentity" : {
      "principalId" : "AWS:XXXXXXXXXXX"
    },
    "requestParameters" : {
      "sourceIPAddress" : "XXX.XX.XX.XX"
    },
    "responseElements" : {
      "x-amz-request-id" : "XXXXXXXXXXXX",
      "x-amz-id-2" : "XXXXXXXXXXXXX"
    },
    "s3" : {
      "s3SchemaVersion" : "1.0",
      "configurationId" : "XXXXXXXXXXXXX",
      "bucket" : {
        "name" : "amzn-s3-demo-bucket",
        "ownerIdentity" : {
          "principalId" : "XXXXXXXXXXX"
        },
        "arn" : "arn:aws:s3:::XXXXXXXXXX"
      },
      "object" : {
        "key" : "akey",
        "size" : null,
        "eTag" : "XXXXXXXXXX",
        "versionId" : null,
        "sequencer" : null
      }
    }
  } ]
}
```

[Contoh lengkap](https://github.com/awsdocs/aws-doc-sdk-examples/blob/75c3daadf750406156fc87fa30ee499a206b4a36/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java#L117) tersedia GitHub yang menunjukkan cara menggunakan API untuk bekerja dengan notifikasi yang diterima oleh antrean Amazon SQS.

## Proses Acara S3 di Lambda dengan Perpustakaan Java: dan AWS SDK for Java 2.x `aws-lambda-java-events`
<a name="s3-event-notif-processing-options"></a>

Alih-alih menggunakan SDK for Java 2.x untuk memproses notifikasi peristiwa Amazon S3 dalam fungsi Lambda, Anda dapat menggunakan pustaka pada versi 3.xx. `[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)` AWS memelihara `aws-lambda-java-events` perpustakaan secara independen, dan memiliki persyaratan ketergantungan sendiri. `aws-lambda-java-events`Pustaka hanya berfungsi dengan peristiwa S3 dalam fungsi Lambda, sedangkan SDK for Java 2.x berfungsi dengan peristiwa S3 di fungsi Lambda, Amazon SNS, dan Amazon SQS.

Kedua pendekatan memodelkan payload notifikasi acara JSON dengan cara yang berorientasi objek dengan yang serupa. APIs Tabel berikut menunjukkan perbedaan mencolok antara menggunakan dua pendekatan.


****  

|  | AWS SDK untuk Java | aws-lambda-java-events perpustakaan | 
| --- | --- | --- | 
| Penamaan Package |  `software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification`  | com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification | 
| RequestHandlerparameter |  Tulis `RequestHandler` implementasi fungsi Lambda Anda untuk menerima String JSON: <pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;<br /><br />public class Handler implements RequestHandler<String, String> {<br /><br />    @Override<br />        public String handleRequest(String jsonS3Event, Context context) {<br />            S3EventNotification s3Event = S3EventNotification<br />                                             .fromJson(jsonS3Event);<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre>  | Tulis RequestHandler implementasi fungsi Lambda Anda untuk menerima objekS3Event:<pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import com.amazonaws.services.lambda.runtime.events.S3Event;<br /><br />public class Handler implements RequestHandler<S3Event, String> {<br /><br />    @Override<br />        public String handleRequest(S3Event s3event, Context context) {<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre> | 
| Ketergantungan Maven |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3-event-notifications</artifactId><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <!-- The following two dependencies are for the <br />         aws-lambda-java-events library. --><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-core</artifactId><br />        <version>1.2.3</version>     <br />    </dependency><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-events</artifactId><br />        <version>3.15.0</version><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  | 

# Bekerja dengan Amazon Simple Notification Service
<a name="examples-simple-notification-service"></a>

Dengan Amazon Simple Notification Service, Anda dapat dengan mudah mendorong pesan notifikasi real-time dari aplikasi Anda ke pelanggan melalui beberapa saluran komunikasi. Topik ini menjelaskan bagaimana melakukan beberapa fungsi dasar Amazon SNS.

## Buat topik
<a name="sns-create-topic"></a>

**Topik** adalah pengelompokan logis saluran komunikasi yang mendefinisikan sistem mana yang akan mengirim pesan, misalnya, mengipasi pesan AWS Lambda dan webhook HTTP. Anda mengirim pesan ke Amazon SNS, lalu mereka didistribusikan ke saluran yang ditentukan dalam topik. Ini membuat pesan tersedia untuk pelanggan.

Untuk membuat topik, pertama-tama buat [CreateTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicRequest.html)objek, dengan nama set topik menggunakan `name()` metode di pembuat. Kemudian, kirim objek permintaan ke Amazon SNS dengan menggunakan `createTopic()` metode [SnsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/SnsClient.html). Anda dapat menangkap hasil permintaan ini sebagai [CreateTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicResponse.html)objek, seperti yang ditunjukkan dalam cuplikan kode berikut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.CreateTopicRequest;
import software.amazon.awssdk.services.sns.model.CreateTopicResponse;
import software.amazon.awssdk.services.sns.model.SnsException;
```

 **Kode** 

```
    public static String createSNSTopic(SnsClient snsClient, String topicName ) {

        CreateTopicResponse result = null;
        try {
            CreateTopicRequest request = CreateTopicRequest.builder()
                    .name(topicName)
                    .build();

            result = snsClient.createTopic(request);
            return result.topicArn();
        } catch (SnsException e) {

            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return "";
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/CreateTopic.java) di GitHub.

## Buat daftar Amazon SNS topik Anda
<a name="sns-crelistate-topics"></a>

Untuk mengambil daftar Amazon SNS topik yang ada, buat [ListTopicsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsRequest.html)objek. Kemudian, kirim objek permintaan ke Amazon SNS dengan menggunakan `listTopics()` metode`SnsClient`. Anda dapat menangkap hasil permintaan ini sebagai [ListTopicsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsResponse.html)objek.

Cuplikan kode berikut mencetak kode status HTTP permintaan dan daftar Amazon Resource Names (ARNs) untuk topik Anda Amazon SNS .

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.ListTopicsRequest;
import software.amazon.awssdk.services.sns.model.ListTopicsResponse;
import software.amazon.awssdk.services.sns.model.SnsException;
```

 **Kode** 

```
    public static void listSNSTopics(SnsClient snsClient) {

        try {
            ListTopicsRequest request = ListTopicsRequest.builder()
                   .build();

            ListTopicsResponse result = snsClient.listTopics(request);
            System.out.println("Status was " + result.sdkHttpResponse().statusCode() + "\n\nTopics\n\n" + result.topics());

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/ListTopics.java) di GitHub.

## Berlangganan titik akhir ke suatu topik
<a name="sns-subscribe-endpoint-topic"></a>

Setelah Anda membuat topik, Anda dapat mengonfigurasi saluran komunikasi mana yang akan menjadi titik akhir untuk topik tersebut. Pesan didistribusikan ke titik akhir ini setelah Amazon SNS menerimanya.

Untuk mengonfigurasi saluran komunikasi sebagai titik akhir untuk suatu topik, berlangganan titik akhir tersebut ke topik tersebut. Untuk memulai, buat [SubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html)objek. Tentukan saluran komunikasi (misalnya, `lambda` atau`email`) sebagai`protocol()`. Atur `endpoint()` ke lokasi keluaran yang relevan (misalnya, ARN Lambda fungsi atau alamat email), lalu atur ARN dari topik yang ingin Anda berlangganan sebagai. `topicArn()` Kirim objek permintaan ke Amazon SNS dengan menggunakan `subscribe()` metode`SnsClient`. Anda dapat menangkap hasil permintaan ini sebagai [SubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeResponse.html)objek.

Cuplikan kode berikut menunjukkan cara berlangganan alamat email ke suatu topik.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.SnsException;
import software.amazon.awssdk.services.sns.model.SubscribeRequest;
import software.amazon.awssdk.services.sns.model.SubscribeResponse;
```

 **Kode** 

```
    public static void subEmail(SnsClient snsClient, String topicArn, String email) {

        try {
            SubscribeRequest request = SubscribeRequest.builder()
                .protocol("email")
                .endpoint(email)
                .returnSubscriptionArn(true)
                .topicArn(topicArn)
                .build();

            SubscribeResponse result = snsClient.subscribe(request);
            System.out.println("Subscription ARN: " + result.subscriptionArn() + "\n\n Status is " + result.sdkHttpResponse().statusCode());

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/SubscribeEmail.java) di GitHub.

## Publikasikan pesan ke suatu topik
<a name="sns-publish-message-topic"></a>

Setelah Anda memiliki topik dan satu atau beberapa titik akhir yang dikonfigurasi untuk itu, Anda dapat mempublikasikan pesan ke sana. Untuk memulai, buat [PublishRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishRequest.html)objek. Tentukan `message()` yang akan dikirim, dan ARN dari topik (`topicArn()`) untuk mengirimkannya. Kemudian, kirim objek permintaan ke Amazon SNS dengan menggunakan `publish()` metode`SnsClient`. Anda dapat menangkap hasil permintaan ini sebagai [PublishResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishResponse.html)objek.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.PublishRequest;
import software.amazon.awssdk.services.sns.model.PublishResponse;
import software.amazon.awssdk.services.sns.model.SnsException;
```

 **Kode** 

```
    public static void pubTopic(SnsClient snsClient, String message, String topicArn) {

        try {
            PublishRequest request = PublishRequest.builder()
                .message(message)
                .topicArn(topicArn)
                .build();

            PublishResponse result = snsClient.publish(request);
            System.out.println(result.messageId() + " Message sent. Status is " + result.sdkHttpResponse().statusCode());

         } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
         }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/PublishTopic.java) di GitHub.

## Berhenti berlangganan titik akhir dari suatu topik
<a name="sns-unsubscribe-endpoint-topic"></a>

Anda dapat menghapus saluran komunikasi yang dikonfigurasi sebagai titik akhir untuk suatu topik. Setelah melakukan itu, topik itu sendiri terus ada dan mendistribusikan pesan ke titik akhir lain yang dikonfigurasi untuk topik itu.

Untuk menghapus saluran komunikasi sebagai titik akhir topik, berhenti berlangganan titik akhir tersebut dari topik tersebut. Untuk memulai, buat [UnsubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeRequest.html)objek dan atur ARN dari topik yang ingin Anda berhenti berlangganan sebagai. `subscriptionArn()` Kemudian kirim objek permintaan ke SNS dengan menggunakan `unsubscribe()` metode. `SnsClient` Anda dapat menangkap hasil permintaan ini sebagai [UnsubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeResponse.html)objek.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.SnsException;
import software.amazon.awssdk.services.sns.model.UnsubscribeRequest;
import software.amazon.awssdk.services.sns.model.UnsubscribeResponse;
```

 **Kode** 

```
    public static void unSub(SnsClient snsClient, String subscriptionArn) {

        try {
            UnsubscribeRequest request = UnsubscribeRequest.builder()
                .subscriptionArn(subscriptionArn)
                .build();

            UnsubscribeResponse result = snsClient.unsubscribe(request);

            System.out.println("\n\nStatus was " + result.sdkHttpResponse().statusCode()
                + "\n\nSubscription was removed for " + request.subscriptionArn());

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/Unsubscribe.java) di GitHub.

## Hapus topik
<a name="sns-delete-topic"></a>

Untuk menghapus Amazon SNS topik, pertama-tama buat [DeleteTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicRequest.html)objek dengan ARN dari set topik sebagai `topicArn()` metode di pembuat. Kemudian kirim objek permintaan ke Amazon SNS dengan menggunakan `deleteTopic()` metode`SnsClient`. Anda dapat menangkap hasil permintaan ini sebagai [DeleteTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicResponse.html)objek, seperti yang ditunjukkan dalam cuplikan kode berikut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.DeleteTopicRequest;
import software.amazon.awssdk.services.sns.model.DeleteTopicResponse;
import software.amazon.awssdk.services.sns.model.SnsException;
```

 **Kode** 

```
    public static void deleteSNSTopic(SnsClient snsClient, String topicArn ) {

        try {
            DeleteTopicRequest request = DeleteTopicRequest.builder()
                .topicArn(topicArn)
                .build();

            DeleteTopicResponse result = snsClient.deleteTopic(request);
            System.out.println("\n\nStatus was " + result.sdkHttpResponse().statusCode());

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/DeleteTopic.java) di GitHub.

Untuk informasi selengkapnya, lihat [Panduan Developer Amazon Simple Notification Service](https://docs.aws.amazon.com/sns/latest/dg/).

# Bekerja dengan Amazon Simple Queue Service
<a name="examples-sqs"></a>

Bagian ini memberikan contoh pemrograman [Amazon Simple Queue Service](https://docs.aws.amazon.com/sqs/)menggunakan AWS SDK untuk Java 2.x.

Contoh berikut hanya mencakup kode yang diperlukan untuk mendemonstrasikan setiap teknik. [Kode contoh lengkap tersedia di GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Dari sana, Anda dapat mengunduh satu file sumber atau mengkloning repositori secara lokal untuk mendapatkan semua contoh untuk dibangun dan dijalankan.

**Topics**
+ [Gunakan batching permintaan otomatis](sqs-auto-batch.md)
+ [Operasi antrian](examples-sqs-message-queues.md)
+ [Operasi pesan](examples-sqs-messages.md)

# Gunakan batching permintaan otomatis untuk Amazon SQS dengan AWS SDK for Java 2.x
<a name="sqs-auto-batch"></a>

Automatic Request Batching API untuk Amazon SQS adalah pustaka tingkat tinggi yang menyediakan cara efisien untuk mengumpulkan dan menyangga permintaan untuk operasi SQS. Dengan menggunakan API batching, Anda mengurangi jumlah permintaan ke SQS, yang meningkatkan throughput dan meminimalkan biaya. 

Karena metode API batch cocok dengan `[SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)` metode—`sendMessage`,, `changeMessageVisibility``deleteMessage`, `receiveMessage` —Anda dapat menggunakan API batch sebagai pengganti drop-in dengan sedikit perubahan. 

Topik ini memberi Anda gambaran umum tentang cara mengonfigurasi dan bekerja dengan Automatic Request Batching API untuk Amazon SQS.

## Periksa prasyarat
<a name="sqs-auto-batch-requirements"></a>

Anda perlu menggunakan SDK for Java *2.x versi 2.28.0* atau yang lebih baru untuk memiliki akses ke API batching. Maven Anda setidaknya `pom.xml` harus mengandung elemen-elemen berikut.

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.28.231</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>sqs</artifactId>
    </dependency>
</dependencies>
```

1 [Versi terbaru](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)

## Buat pengelola batch
<a name="sqs-auto-batch-create"></a>

API batching permintaan otomatis diimplementasikan oleh [SqsAsyncBatchManager](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html)antarmuka. Anda dapat membuat contoh manajer beberapa cara.

### Konfigurasi default dengan menggunakan `SqsAsyncClient`
<a name="sqs-batch-manager-create-default"></a>

Cara paling sederhana Anda dapat membuat pengelola batch adalah dengan memanggil metode `batchManager` pabrik pada [SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)instance yang ada. Pendekatan sederhana ditunjukkan dalam cuplikan berikut. 

```
SqsAsyncClient asyncClient = SqsAsyncClient.create();
SqsAsyncBatchManager sqsAsyncBatchManager = asyncClient.batchManager();
```

Bila Anda menggunakan pendekatan ini, `SqsAsyncBatchManager` instance menggunakan nilai default yang ditampilkan dalam tabel di [Ganti pengaturan konfigurasi untuk `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) bagian. Selain itu, `SqsAsyncBatchManager` instance menggunakan `SqsAsyncClient` instance dari mana ia dibuat. `ExecutorService`

### Konfigurasi kustom dengan menggunakan `SqsAsyncBatchManager.Builder`
<a name="sqs-batch-manager-create-custom"></a>

Untuk kasus penggunaan yang lebih lanjut, Anda dapat menyesuaikan pengelola batch menggunakan file [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.Builder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.Builder.html). Dengan menggunakan pendekatan ini untuk membuat `SqsAsyncBatchManager` instance, Anda dapat menyempurnakan perilaku batching. Cuplikan berikut menunjukkan contoh cara menggunakan builder untuk menyesuaikan perilaku batching.

```
SqsAsyncBatchManager batchManager = SqsAsyncBatchManager.builder()
    .client(SqsAsyncClient.create())
    .scheduledExecutor(Executors.newScheduledThreadPool(5))
    .overrideConfiguration(b -> b
        .receiveMessageMinWaitDuration(Duration.ofSeconds(10))
        .receiveMessageVisibilityTimeout(Duration.ofSeconds(1))
        .receiveMessageAttributeNames(Collections.singletonList("*"))
        .receiveMessageSystemAttributeNames(Collections.singletonList(MessageSystemAttributeName.ALL)))
    .build();
```

Bila Anda menggunakan pendekatan ini, Anda dapat menyesuaikan pengaturan pada `BatchOverrideConfiguration` objek yang ditunjukkan pada tabel di [Ganti pengaturan konfigurasi untuk `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) bagian. Anda juga dapat memberikan kustom [https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html)untuk pengelola batch dengan menggunakan pendekatan ini.

## Kirim pesan
<a name="sqs-auto-batch-send"></a>

Untuk mengirim pesan dengan pengelola batch, gunakan `[SqsAsyncBatchManager\$1sendMessage](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#sendMessage(software.amazon.awssdk.services.sqs.model.SendMessageRequest))` metode ini. Buffer SDK meminta dan mengirimkannya sebagai batch saat `sendRequestFrequency` nilai `maxBatchSize` atau tercapai.

Contoh berikut menunjukkan `sendMessage` permintaan segera diikuti oleh permintaan lain. Dalam hal ini, SDK mengirim kedua pesan dalam satu batch.

```
// Sending the first message
CompletableFuture<SendMessageResponse> futureOne = 
    sqsAsyncBatchManager.sendMessage(r -> r.messageBody("One").queueUrl("queue"));

// Sending the second message
CompletableFuture<SendMessageResponse> futureTwo = 
    sqsAsyncBatchManager.sendMessage(r -> r.messageBody("Two").queueUrl("queue"));

// Waiting for both futures to complete and retrieving the responses
SendMessageResponse messageOne = futureOne.join();
SendMessageResponse messageTwo = futureTwo.join();
```

## Mengubah batas waktu visibilitas pesan
<a name="sqs-auto-batch-change-vis"></a>

Anda dapat mengubah batas waktu visibilitas pesan dalam batch dengan menggunakan metode ini [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#changeMessageVisibility(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#changeMessageVisibility(java.util.function.Consumer)). Buffer SDK meminta dan mengirimkannya sebagai batch saat `sendRequestFrequency` nilai `maxBatchSize` atau tercapai.

Contoh berikut menunjukkan cara memanggil `changeMessageVisibility` metode.

```
CompletableFuture<ChangeMessageVisibilityResponse> futureOne =
    sqsAsyncBatchManager.changeMessageVisibility(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
ChangeMessageVisibilityResponse response = futureOne.join();
```

## Hapus pesan
<a name="sqs-auto-batch-delete"></a>

Anda dapat menghapus pesan dalam batch menggunakan [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#deleteMessage(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#deleteMessage(java.util.function.Consumer))metode ini. Buffer SDK meminta dan mengirimkannya sebagai batch saat `sendRequestFrequency` nilai `maxBatchSize` atau tercapai.

Contoh berikut menunjukkan bagaimana Anda dapat memanggil `deleteMessage` metode.

```
CompletableFuture<DeleteMessageResponse> futureOne = 
    sqsAsyncBatchManager.deleteMessage(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
DeleteMessageResponse response = futureOne.join();
```

## Menerima pesan
<a name="sqs-auto-batch-receive"></a>

### Gunakan pengaturan default
<a name="sqs-auto-batch-receive-default-settings"></a>

Saat Anda melakukan polling `[SqsAsyncBatchManager\$1receiveMessage](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#receiveMessage(java.util.function.Consumer))` metode dalam aplikasi Anda, pengelola batch mengambil pesan dari buffer internalnya, yang diperbarui secara otomatis oleh SDK di latar belakang.

Contoh berikut menunjukkan cara memanggil `receiveMessage` metode.

```
CompletableFuture<ReceiveMessageResponse> responseFuture = 
    sqsAsyncBatchManager.receiveMessage(r -> r.queueUrl("queueUrl"));
```

### Gunakan pengaturan khusus
<a name="sqs-auto-batch-receive-custom-settings"></a>

Jika Anda ingin menyesuaikan permintaan lebih lanjut, misalnya dengan menyetel waktu tunggu khusus dan menentukan jumlah pesan yang akan diambil, Anda dapat menyesuaikan permintaan seperti yang ditunjukkan pada contoh berikut.

```
CompletableFuture<ReceiveMessageResponse> response = 
    sqsAsyncBatchManager.receiveMessage(r -> 
        r.queueUrl("queueUrl")
         .waitTimeSeconds(5)
         .visibilityTimeout(20));
```

**catatan**  
Jika Anda memanggil `receiveMessage` dengan `[ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)` yang menyertakan salah satu parameter berikut, SDK melewati pengelola batch dan mengirimkan permintaan `receiveMessage` asinkron reguler:  
`messageAttributeNames`
`messageSystemAttributeNames`
`messageSystemAttributeNamesWithStrings`
`overrideConfiguration`

## Ganti pengaturan konfigurasi untuk `SqsAsyncBatchManager`
<a name="sqs-auto-batch-config-settings"></a>

Anda dapat menyesuaikan pengaturan berikut saat membuat `SqsAsyncBatchManager` instance. Daftar pengaturan berikut tersedia di [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/BatchOverrideConfiguration.Builder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/BatchOverrideConfiguration.Builder.html).


| Pengaturan | Deskripsi | Nilai default | 
| --- | --- | --- | 
| maxBatchSize | Jumlah maksimum permintaan per batch untuk masing-masingSendMessageBatchRequest,ChangeMessageVisibilityBatchRequest, atauDeleteMessageBatchRequest. Nilai maksimumnya adalah 10. | 10 | 
| sendRequestFrequency |  Waktu sebelum mengirim batch, kecuali `maxBatchSize` tercapai lebih awal. Nilai yang lebih tinggi dapat mengurangi permintaan tetapi meningkatkan latensi.  | 200ms | 
| receiveMessageVisibilityTimeout | Batas waktu visibilitas untuk pesan. Jika tidak disetel, default antrian digunakan. | Antrian default | 
| receiveMessageMinWaitDuration | Waktu tunggu minimum untuk receiveMessage permintaan. Hindari pengaturan ke 0 untuk mencegah pemborosan CPU. | 50ms | 
| receiveMessageSystemAttributeNames | Daftar [nama atribut sistem](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/MessageSystemAttributeName.html) untuk meminta receiveMessage panggilan. | Tidak ada | 
| receiveMessageAttributeNames | Daftar [nama atribut](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-message-attributes) untuk meminta receiveMessage panggilan. | Tidak ada | 

# Bekerja dengan Amazon Simple Queue Service antrian pesan
<a name="examples-sqs-message-queues"></a>

*Antrian pesan* adalah wadah logis yang digunakan untuk mengirim pesan dengan andal. Amazon Simple Queue Service Ada dua jenis antrian: *standar* dan *first-in, first-out* (FIFO). Untuk mempelajari lebih lanjut tentang antrian dan perbedaan di antara jenis-jenis ini, lihat Panduan [Amazon Simple Queue Service Pengembang](https://docs.aws.amazon.com//AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html).

Topik ini menjelaskan cara membuat, membuat daftar, menghapus, dan mendapatkan URL Amazon Simple Queue Service antrian dengan menggunakan. AWS SDK untuk Java

`sqsClient`Variabel yang digunakan dalam contoh berikut dapat dibuat dari cuplikan berikut.

```
SqsClient sqsClient = SqsClient.create();
```

Bila Anda membuat `SqsClient` dengan menggunakan `create()` metode statis, SDK akan mengonfigurasi Region menggunakan [rantai penyedia wilayah default dan kredensialnya menggunakan rantai penyedia](region-selection.md#default-region-provider-chain) kredensial [default](credentials-chain.md).

## Membuat antrean
<a name="sqs-create-queue"></a>

Gunakan `SqsClient’s` `createQueue` metode ini, dan berikan `[CreateQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/CreateQueueRequest.html)` objek yang menjelaskan parameter antrian seperti yang ditunjukkan pada cuplikan kode berikut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
            CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
                .queueName(queueName)
                .build();

            sqsClient.createQueue(createQueueRequest);
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L52) di GitHub.

## Daftar antrian
<a name="sqs-list-queues"></a>

Untuk membuat daftar Amazon Simple Queue Service antrian untuk akun Anda, panggil `SqsClient’s` `listQueues` metode dengan `[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)` objek.

Bila Anda menggunakan bentuk [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsClient.html#listQueues()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsClient.html#listQueues())metode yang tidak mengambil parameter, layanan mengembalikan *semua antrian hingga 1.000* antrian. 

Anda dapat memberikan awalan nama antrian ke `[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)` objek untuk membatasi hasil ke antrian yang cocok dengan awalan seperti yang ditunjukkan dalam kode berikut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
        String prefix = "que";

        try {
            ListQueuesRequest listQueuesRequest = ListQueuesRequest.builder().queueNamePrefix(prefix).build();
            ListQueuesResponse listQueuesResponse = sqsClient.listQueues(listQueuesRequest);

            for (String url : listQueuesResponse.queueUrls()) {
                System.out.println(url);
            }

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L79) di GitHub.

## Dapatkan URL untuk antrian
<a name="sqs-get-queue-url"></a>

Kode berikut menunjukkan cara mendapatkan URL untuk antrian dengan memanggil `SqsClient’s` `getQueueUrl` metode dengan `[GetQueueUrlRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/GetQueueUrlRequest.html)` objek.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
            GetQueueUrlResponse getQueueUrlResponse =
                sqsClient.getQueueUrl(GetQueueUrlRequest.builder().queueName(queueName).build());
            String queueUrl = getQueueUrlResponse.queueUrl();
            return queueUrl;
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L70) di GitHub.

## Hapus antrian
<a name="sqs-delete-queue"></a>

Berikan [URL](#sqs-get-queue-url) antrian ke `[DeleteQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/DeleteQueueRequest.html)` objek. Kemudian panggil `SqsClient’s` `deleteQueue` metode untuk menghapus antrian seperti yang ditunjukkan pada kode berikut.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
    public static void deleteSQSQueue(SqsClient sqsClient, String queueName) {

        try {

            GetQueueUrlRequest getQueueRequest = GetQueueUrlRequest.builder()
                    .queueName(queueName)
                    .build();

            String queueUrl = sqsClient.getQueueUrl(getQueueRequest).queueUrl();

            DeleteQueueRequest deleteQueueRequest = DeleteQueueRequest.builder()
                    .queueUrl(queueUrl)
                    .build();

            sqsClient.deleteQueue(deleteQueueRequest);

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/6240df86c5f17eae1e23d1139d1435c7dc4b2a11/javav2/example_code/sqs/src/main/java/com/example/sqs/DeleteQueue.java#L48) di GitHub.

## Informasi selengkapnya
<a name="more-information"></a>
+  [CreateQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html)di Referensi Amazon Simple Queue Service API
+  [GetQueueUrl](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueUrl.html)di Referensi Amazon Simple Queue Service API
+  [ListQueues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html)di Referensi Amazon Simple Queue Service API
+  [DeleteQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html)di Referensi Amazon Simple Queue Service API

# Mengirim, menerima, dan menghapus Amazon Simple Queue Service pesan
<a name="examples-sqs-messages"></a>

Pesan adalah sepotong data yang dapat dikirim dan diterima oleh komponen terdistribusi. Pesan selalu dikirimkan menggunakan [SQS Queue](examples-sqs-message-queues.md).

`sqsClient`Variabel yang digunakan dalam contoh berikut dapat dibuat dari cuplikan berikut.

```
SqsClient sqsClient = SqsClient.create();
```

Bila Anda membuat `SqsClient` dengan menggunakan `create()` metode statis, SDK akan mengonfigurasi Region menggunakan [rantai penyedia wilayah default dan kredensialnya menggunakan rantai penyedia](region-selection.md#default-region-provider-chain) kredensial [default](credentials-chain.md).

## Kirim pesan
<a name="sqs-message-send"></a>

Tambahkan satu pesan ke Amazon Simple Queue Service antrian dengan memanggil `sendMessage` metode SqsClient klien. Berikan [SendMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageRequest.html)objek yang berisi [URL](examples-sqs-message-queues.md#sqs-get-queue-url) antrian, isi pesan, dan nilai penundaan opsional (dalam hitungan detik).

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
            sqsClient.sendMessage(SendMessageRequest.builder()
                .queueUrl(queueUrl)
                .messageBody("Hello world!")
                .delaySeconds(10)
                .build());

            sqsClient.sendMessage(sendMsgRequest);
```

## Kirim beberapa pesan dalam satu permintaan
<a name="sqs-messages-send-multiple"></a>

Kirim lebih dari satu pesan dalam satu permintaan dengan menggunakan SqsClient `sendMessageBatch` metode ini. Metode ini mengambil [SendMessageBatchRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequest.html)yang berisi URL antrian dan daftar pesan untuk dikirim. (Setiap pesan adalah a [SendMessageBatchRequestEntry](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequestEntry.html).) Anda juga dapat menunda pengiriman pesan tertentu dengan menetapkan nilai penundaan pada pesan.

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
            SendMessageBatchRequest sendMessageBatchRequest = SendMessageBatchRequest.builder()
                .queueUrl(queueUrl)
                .entries(SendMessageBatchRequestEntry.builder().id("id1").messageBody("Hello from msg 1").build(),
                        SendMessageBatchRequestEntry.builder().id("id2").messageBody("msg 2").delaySeconds(10).build())
                .build();
            sqsClient.sendMessageBatch(sendMessageBatchRequest);
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L133) di GitHub.

## Ambil Pesan
<a name="sqs-messages-receive"></a>

Ambil pesan apa pun yang saat ini berada dalam antrian dengan memanggil metode. SqsClient `receiveMessage` Metode ini mengambil [ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)yang berisi URL antrian. Anda juga dapat menentukan jumlah maksimum pesan yang akan dikembalikan. Pesan dikembalikan sebagai daftar objek [Pesan](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/Message.html).

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
        try {
            ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .maxNumberOfMessages(5)
                .build();
            List<Message> messages = sqsClient.receiveMessage(receiveMessageRequest).messages();
            return messages;
        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return null;
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L148) di GitHub.

## Hapus pesan setelah diterima
<a name="sqs-messages-delete"></a>

Setelah menerima pesan dan memproses isinya, hapus pesan dari antrian dengan mengirimkan alamat tanda terima pesan dan URL antrian ke metode. `SqsClient's` [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsClient.html#deleteMessage(software.amazon.awssdk.services.sqs.model.DeleteMessageRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsClient.html#deleteMessage(software.amazon.awssdk.services.sqs.model.DeleteMessageRequest))

 **Impor** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Kode** 

```
        try {
            for (Message message : messages) {
                DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                        .queueUrl(queueUrl)
                        .receiptHandle(message.receiptHandle())
                        .build();
                sqsClient.deleteMessage(deleteMessageRequest);
            }
```

Lihat [sampel lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L187) di GitHub.

## Info Selengkapnya
<a name="more-info"></a>
+  [Cara Kerja Amazon Simple Queue Service Antrian di Panduan](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html) Pengembang Amazon Simple Queue Service 
+  [SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)di Referensi Amazon Simple Queue Service API
+  [SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)di Referensi Amazon Simple Queue Service API
+  [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)di Referensi Amazon Simple Queue Service API
+  [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)di Referensi Amazon Simple Queue Service API

# Bekerja dengan Amazon Transcribe
<a name="examples-transcribe"></a>

Contoh berikut menunjukkan cara kerja streaming dua arah menggunakan. Amazon Transcribe Streaming dua arah berarti bahwa ada aliran data yang masuk ke layanan dan diterima kembali secara real time. Contoh menggunakan transkripsi Amazon Transcribe streaming untuk mengirim aliran audio dan menerima aliran teks yang ditranskripsi kembali secara real time.

Lihat [Transkripsi Streaming](https://docs.aws.amazon.com//transcribe/latest/dg/streaming.html) di Panduan Amazon Transcribe Pengembang untuk mempelajari lebih lanjut tentang fitur ini.

Lihat [Memulai](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html) di Panduan Amazon Transcribe Pengembang untuk mulai menggunakan Amazon Transcribe.

## Siapkan mikrofon
<a name="set-up-the-microphone"></a>

Kode ini menggunakan paket javax.sound.sampled untuk mengalirkan audio dari perangkat input.

 **Kode** 

```
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;

public class Microphone {

    public static TargetDataLine get() throws Exception {
        AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
        DataLine.Info datalineInfo = new DataLine.Info(TargetDataLine.class, format);

        TargetDataLine dataLine = (TargetDataLine) AudioSystem.getLine(datalineInfo);
        dataLine.open(format);

        return dataLine;
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/Microphone.java) di GitHub.

## Buat penerbit
<a name="create-a-publisher"></a>

Kode ini mengimplementasikan penerbit yang menerbitkan data audio dari aliran audio. Amazon Transcribe 

 **Kode** 

```
package com.amazonaws.transcribe;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.transcribestreaming.model.AudioEvent;
import software.amazon.awssdk.services.transcribestreaming.model.AudioStream;
import software.amazon.awssdk.services.transcribestreaming.model.TranscribeStreamingException;


public class AudioStreamPublisher implements Publisher<AudioStream> {
    private final InputStream inputStream;

    public AudioStreamPublisher(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    @Override
    public void subscribe(Subscriber<? super AudioStream> s) {
        s.onSubscribe(new SubscriptionImpl(s, inputStream));
    }

    private class SubscriptionImpl implements Subscription {
        private static final int CHUNK_SIZE_IN_BYTES = 1024 * 1;
        private ExecutorService executor = Executors.newFixedThreadPool(1);
        private AtomicLong demand = new AtomicLong(0);

        private final Subscriber<? super AudioStream> subscriber;
        private final InputStream inputStream;

        private SubscriptionImpl(Subscriber<? super AudioStream> s, InputStream inputStream) {
            this.subscriber = s;
            this.inputStream = inputStream;
        }

        @Override
        public void request(long n) {
            if (n <= 0) {
                subscriber.onError(new IllegalArgumentException("Demand must be positive"));
            }

            demand.getAndAdd(n);

            executor.submit(() -> {
                try {
                    do {
                        ByteBuffer audioBuffer = getNextEvent();
                        if (audioBuffer.remaining() > 0) {
                            AudioEvent audioEvent = audioEventFromBuffer(audioBuffer);
                            subscriber.onNext(audioEvent);
                        } else {
                            subscriber.onComplete();
                            break;
                        }
                    } while (demand.decrementAndGet() > 0);
                } catch (TranscribeStreamingException e) {
                    subscriber.onError(e);
                }
            });
        }

        @Override
        public void cancel() {

        }

        private ByteBuffer getNextEvent() {
            ByteBuffer audioBuffer;
            byte[] audioBytes = new byte[CHUNK_SIZE_IN_BYTES];

            int len = 0;
            try {
                len = inputStream.read(audioBytes);

                if (len <= 0) {
                    audioBuffer = ByteBuffer.allocate(0);
                } else {
                    audioBuffer = ByteBuffer.wrap(audioBytes, 0, len);
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }

            return audioBuffer;
        }

        private AudioEvent audioEventFromBuffer(ByteBuffer bb) {
            return AudioEvent.builder()
                    .audioChunk(SdkBytes.fromByteBuffer(bb))
                    .build();
        }
    }
}
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/AudioStreamPublisher.java) di GitHub.

## Buat klien dan mulai streaming
<a name="create-the-client-and-start-the-stream"></a>

Dalam metode utama, buat objek permintaan, mulai aliran input audio dan buat instance penerbit dengan input audio.

Anda juga harus membuat [StartStreamTranscriptionResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/transcribestreaming/model/StartStreamTranscriptionResponseHandler.html)untuk menentukan cara menangani respons dari Amazon Transcribe.

Kemudian, gunakan `startStreamTranscription` metode ini untuk memulai streaming dua arah. TranscribeStreamingAsyncClient

 **Impor** 

```
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.AudioInputStream;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.transcribestreaming.TranscribeStreamingAsyncClient;
import software.amazon.awssdk.services.transcribestreaming.model.TranscribeStreamingException ;
import software.amazon.awssdk.services.transcribestreaming.model.StartStreamTranscriptionRequest;
import software.amazon.awssdk.services.transcribestreaming.model.MediaEncoding;
import software.amazon.awssdk.services.transcribestreaming.model.LanguageCode;
import software.amazon.awssdk.services.transcribestreaming.model.StartStreamTranscriptionResponseHandler;
import software.amazon.awssdk.services.transcribestreaming.model.TranscriptEvent;
```

 **Kode** 

```
    public static void convertAudio(TranscribeStreamingAsyncClient client) throws Exception {

        try {

            StartStreamTranscriptionRequest request = StartStreamTranscriptionRequest.builder()
                    .mediaEncoding(MediaEncoding.PCM)
                    .languageCode(LanguageCode.EN_US)
                    .mediaSampleRateHertz(16_000).build();

            TargetDataLine mic = Microphone.get();
            mic.start();

            AudioStreamPublisher publisher = new AudioStreamPublisher(new AudioInputStream(mic));

            StartStreamTranscriptionResponseHandler response =
                    StartStreamTranscriptionResponseHandler.builder().subscriber(e -> {
                        TranscriptEvent event = (TranscriptEvent) e;
                        event.transcript().results().forEach(r -> r.alternatives().forEach(a -> System.out.println(a.transcript())));
                    }).build();

            // Keeps Streaming until you end the Java program
            client.startStreamTranscription(request, publisher, response);

        } catch (TranscribeStreamingException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
         }
    }
```

Lihat [contoh lengkapnya](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/BidirectionalStreaming.java) di GitHub.

## Informasi selengkapnya
<a name="more-info"></a>
+  [Cara Kerjanya](https://docs.aws.amazon.com//transcribe/latest/dg/how-it-works.html) di Panduan Amazon Transcribe Pengembang.
+  [Memulai Dengan Streaming Audio](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html) di Panduan Amazon Transcribe Pengembang.