

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# En appelant Services AWS depuis le AWS SDK for Java 2.x
<a name="work-with-services"></a>

Cette section fournit de courts didacticiels et des conseils sur la façon d'utiliser Select Services AWS. Pour un ensemble complet d'exemples, consultez la [section Exemples de code](java_code_examples.md).

**Topics**
+ [CloudWatch](examples-cloudwatch.md)
+ [AWS services de base de données](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)

# Travaillez avec CloudWatch
<a name="examples-cloudwatch"></a>

Cette section fournit des exemples de programmation d'[Amazon](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) à l'aide CloudWatch de la version AWS SDK pour Java 2.x.

 Amazon CloudWatch surveille vos ressources Amazon Web Services (AWS) et les applications que vous exécutez AWS en temps réel. Vous pouvez les utiliser CloudWatch pour collecter et suivre les métriques, qui sont des variables que vous pouvez mesurer pour vos ressources et vos applications. CloudWatch les alarmes envoient des notifications ou modifient automatiquement les ressources que vous surveillez en fonction des règles que vous définissez.

Les exemples suivants incluent uniquement le code nécessaire pour démontrer chaque technique. L'[exemple de code complet est disponible sur GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). À partir de là, vous pouvez télécharger un fichier source unique ou cloner le référentiel en local pour obtenir tous les exemples à générer et exécuter.

**Topics**
+ [Obtenez des statistiques auprès de CloudWatch](examples-cloudwatch-get-metrics.md)
+ [Publiez des données métriques personnalisées sur CloudWatch](examples-cloudwatch-publish-custom-metrics.md)
+ [Travailler avec des CloudWatch alarmes](examples-cloudwatch-create-alarms.md)
+ [Utiliser Amazon CloudWatch Events](examples-cloudwatch-send-events.md)

# Obtenez des statistiques auprès de CloudWatch
<a name="examples-cloudwatch-get-metrics"></a>

## Affichage des métriques
<a name="listing-metrics"></a>

Pour répertorier CloudWatch les métriques, créez une méthode [ListMetricsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsRequest.html)et appelez CloudWatchClient la `listMetrics` méthode. Vous pouvez utiliser `ListMetricsRequest` pour filtrer les métriques renvoyées par espace de noms, nom de métrique ou dimension.

**Note**  
Une liste des mesures et des dimensions publiées par les AWS services se trouve dans la [référence Amazon CloudWatch des mesures et dimensions](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) du guide de l' Amazon CloudWatch utilisateur.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Les métriques sont renvoyées dans un [ListMetricsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsResponse.html)en appelant sa `getMetrics` méthode.

Les résultats peuvent être *paginés*. Pour extraire le prochain lot de résultats, appelez `nextToken` sur l'objet réponse et utilisez la valeur du jeton pour générer un objet nouvelle demande. Puis, appelez à nouveau la méthode `listMetrics` avec la nouvelle demande.

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [ListMetrics](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_ListMetrics.html)dans la référence de Amazon CloudWatch l'API

# Publiez des données métriques personnalisées sur CloudWatch
<a name="examples-cloudwatch-publish-custom-metrics"></a>

Un certain nombre de AWS services publient [leurs propres métriques dans des](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) espaces de noms commençant par « `AWS` ». Vous pouvez également publier des données métriques personnalisées en utilisant votre propre espace de noms (à condition qu'il ne commence pas par `AWS` « »).

## Publier des données de métriques personnalisées
<a name="cwid1"></a>

Pour publier vos propres données métriques, appelez la `putMetricData` méthode CloudWatchClient's avec un [PutMetricDataRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricDataRequest.html). Ils `PutMetricDataRequest` doivent inclure l'espace de noms personnalisé à utiliser pour les données, ainsi que des informations sur le point de données lui-même dans un [MetricDatum](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/MetricDatum.html)objet.

**Note**  
Vous ne pouvez pas spécifier un espace de noms commençant par « `AWS` ». Les espaces de noms commençant par `AWS` « » sont réservés aux Amazon Web Services produits.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
     }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Utilisez Amazon CloudWatch les métriques](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/working_with_metrics.html) dans le guide de Amazon CloudWatch l'utilisateur.
+  [AWS Espaces de noms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) dans le guide de Amazon CloudWatch l'utilisateur.
+  [PutMetricData](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricData.html)dans la référence de Amazon CloudWatch l'API.

# Travailler avec des CloudWatch alarmes
<a name="examples-cloudwatch-create-alarms"></a>

## Créer une alarme
<a name="create-an-alarm"></a>

Pour créer une alarme basée sur une CloudWatch métrique, appelez la `putMetricAlarm` méthode CloudWatchClient's avec un [PutMetricAlarmRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricAlarmRequest.html)rempli des conditions d'alarme.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java) sur GitHub.

## Répertorier les alarmes
<a name="list-alarms"></a>

Pour répertorier les CloudWatch alarmes que vous avez créées, appelez la `describeAlarms` méthode CloudWatchClient's avec un [DescribeAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsRequest.html)que vous pouvez utiliser pour définir les options du résultat.

 **Importations** 

```
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;
```

 **Code** 

```
    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");
    }
```

La liste des alarmes peut être obtenue `MetricAlarms` en appelant [DescribeAlarmsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsResponse.html)le code renvoyé par`describeAlarms`.

Les résultats peuvent être *paginés*. Pour extraire le prochain lot de résultats, appelez `nextToken` sur l'objet réponse et utilisez la valeur du jeton pour générer un objet nouvelle demande. Puis, appelez à nouveau la méthode `describeAlarms` avec la nouvelle demande.

**Note**  
Vous pouvez également récupérer les alarmes pour une métrique spécifique en utilisant la `describeAlarmsForMetric` méthode CloudWatchClient's. Son utilisation est similaire à `describeAlarms`.

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java) sur GitHub.

## Supprimer des alertes
<a name="delete-alarms"></a>

Pour supprimer des CloudWatch alarmes, appelez la `deleteAlarms` méthode CloudWatchClient's [DeleteAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DeleteAlarmsRequest.html)en indiquant un ou plusieurs noms d'alarmes que vous souhaitez supprimer.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Utilisation des Amazon CloudWatch alarmes](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) dans le guide de Amazon CloudWatch l'utilisateur
+  [PutMetricAlarm](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricAlarm.html)dans la référence de Amazon CloudWatch l'API
+  [DescribeAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)dans la référence de Amazon CloudWatch l'API
+  [DeleteAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DeleteAlarms.html)dans la référence de Amazon CloudWatch l'API

# Utiliser Amazon CloudWatch Events
<a name="examples-cloudwatch-send-events"></a>

 CloudWatch Events fournit un flux d'événements système en temps quasi réel décrivant les modifications apportées aux AWS ressources des Amazon EC2 instances, des Lambda fonctions, des Kinesis flux, Amazon ECS des tâches, des machines d' Step Functions état, des Amazon SNS sujets, des Amazon SQS files d'attente ou des cibles intégrées. À l'aide de règles simples, vous pouvez faire correspondre les événements et les acheminer vers un ou plusieurs flux ou fonctions cibles.

Amazon EventBridge est l'[évolution](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cwe-now-eb.html) des CloudWatch événements. Les deux services utilisent la même API. Vous pouvez donc continuer à utiliser le [client CloudWatch Events](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/CloudWatchClient.html) fourni par le SDK ou migrer vers le [EventBridge client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/eventbridge/EventBridgeClient.html) du SDK pour Java pour la fonctionnalité CloudWatch Events. CloudWatch [La documentation du Guide de l'utilisateur](https://docs.aws.amazon.com/eventbridge/latest/userguide/index.html) des événements et les [références des API](https://docs.aws.amazon.com/eventbridge/latest/APIReference/index.html) sont désormais disponibles sur les sites de EventBridge documentation.

## Ajouter des événements
<a name="add-events"></a>

Pour ajouter CloudWatch des événements personnalisés, appelez la `CloudWatchEventsClient’s` `putEvents` méthode avec un [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)objet contenant un ou plusieurs [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)objets fournissant des détails sur chaque événement. Vous pouvez spécifier plusieurs paramètres pour l'entrée, tels que la source et le type de l'événement, les ressources associées à l'événement, et ainsi de suite.

**Note**  
Vous pouvez spécifier un maximum de 10 événements par appel de `putEvents`.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutEvents.java) sur GitHub.

## Ajout de règles
<a name="add-rules"></a>

Pour créer ou mettre à jour une règle, appelez la `CloudWatchEventsClient’s` `putRule` méthode avec un [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)avec le nom de la règle et des paramètres facultatifs tels que le [modèle d'événement](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html), le IAM rôle à associer à la règle et une [expression de planification](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html) décrivant la fréquence d'exécution de la règle.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutRule.java) sur GitHub.

## Ajouter des cibles
<a name="add-targets"></a>

Les cibles sont les ressources appelées lorsqu'une règle est déclenchée. Les exemples de cibles incluent Amazon EC2 les instances, Lambda les fonctions, Kinesis les flux, Amazon ECS les tâches, les machines d' Step Functions état et les cibles intégrées.

Pour ajouter une cible à une règle, appelez la `CloudWatchEventsClient’s` `putTargets` méthode avec un [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)contenant la règle à mettre à jour et une liste de cibles à ajouter à la règle.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutTargets.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Ajouter des événements PutEvents](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html) dans le guide de EventBridge l'utilisateur Amazon
+  [Expressions de planification pour les règles](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html#eb-create-scheduled-rule-schedule) dans le guide de EventBridge l'utilisateur Amazon
+  [Types d'événements figurant CloudWatch Events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html) dans le guide de EventBridge l'utilisateur Amazon
+  [Modèles d'événements](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html) présentés dans le guide de EventBridge l'utilisateur Amazon
+  [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)dans le Amazon EventBridge API Reference
+  [PutTargets](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html)dans le Amazon EventBridge API Reference
+  [PutRule](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html)dans le Amazon EventBridge API Reference

# AWS services de base de données et AWS SDK for Java 2.x
<a name="examples-databases"></a>

AWS [propose plusieurs types de bases de données : relationnelle, clé-valeur, en mémoire, documentaire, etc.](https://aws.amazon.com/products/databases/) La prise en charge du SDK for Java 2.x varie en fonction de la nature du service de base de données dans. AWS

Certains services de base de données, par exemple le service [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/Welcome.html), disposent d'un APIs service Web pour gérer AWS la ressource (base de données) ainsi que d'un APIs service Web pour interagir avec les données. [Dans le SDK pour Java 2.x, ces types de services ont des clients de service dédiés, par exemple Dynamo. DBClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)

D'autres services de base de données ont un service Web APIs qui interagit avec la ressource, comme l'API [Amazon DocumentDB](https://docs.aws.amazon.com/documentdb/latest/developerguide/api-reference.html) (pour la gestion des clusters, des instances et des ressources), mais n'ont pas d'API de service Web pour travailler avec les données. Le SDK pour Java 2.x possède une interface [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html)correspondante pour travailler avec la ressource. Cependant, vous avez besoin d'une autre API Java, telle que [MongoDB pour Java, pour](https://www.mongodb.com/developer/languages/java/) travailler avec les données.

Utilisez les exemples ci-dessous pour savoir comment utiliser le SDK pour les clients de service Java 2.x avec les différents types de bases de données.

## Exemples d'Amazon DynamoDB
<a name="examples-db-dynamodb"></a>


| Travailler avec les données | Utilisation de la base de données | 
| --- |--- |
| Client du service SDK : [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | Client du service SDK : [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | 
| Exemple : application [REST React/Spring utilisant DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) | Exemples : [CreateTable, ListTables, DeleteTable](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) | 
| Exemples : [plusieurs exemples de DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) |  | 
|  | 
| --- |
| Client du service SDK : [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html) |  | 
| Exemple : application [REST React/Spring utilisant DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) |  | 
| Exemples : [plusieurs exemples de DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) (noms commençant par « Enhanced ») |  | 

Consultez [d'autres exemples de DynamoDB](examples-dynamodb.md) dans la section des exemples de code guidés de ce guide.

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


|  Travailler avec les données  |  Utilisation de la base de données  | 
| --- | --- | 
| API non SDK : JDBC, version SQL spécifique à la base de données ; votre code gère les connexions à la base de données ou un pool de connexions. | Client du service SDK : [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Exemple : application [REST React/Spring utilisant MySQL](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_rds_item_tracker) | Exemples : [Plusieurs RdsClient exemples](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) | 

## Exemples d'Amazon Redshift
<a name="examples-db-redshift"></a>


|  Travailler avec les données  |  Utilisation de la base de données  | 
| --- | --- | 
| Client du service SDK : [RedshiftDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshiftdata/RedshiftDataClient.html) | Client du service SDK : [RedshiftClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshift/RedshiftClient.html) | 
| Exemples : [Plusieurs RedshiftDataClient exemples](https://github.com/awsdocs/aws-doc-sdk-examples/blob/c682a07a1e6abce793e3c32ef3b9661fa723d0ff/javav2/example_code/redshift/src/main/java/com/example/scenario/RedshiftScenario.java) | Exemples : [Plusieurs RedshiftClient exemples](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/redshift/src/main/java/com/example/redshift) | 
| Exemple : application [REST React/Spring utilisant RedshiftDataClient](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/CreatingSpringRedshiftRest) |  | 

## Exemples d'Amazon Aurora Serverless v2
<a name="examples-db-aurora-sv1"></a>


|  Travailler avec les données  |  Utilisation de la base de données  | 
| --- | --- | 
| Client du service SDK : [RdsDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rdsdata/RdsDataClient.html) | Client du service SDK : [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Exemple : application [REST React/Spring utilisant RdsDataClient](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_Spring_RDS_Rest) | Exemples : [Plusieurs RdsClient exemples](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) | 

## Exemples d'Amazon DocumentDB
<a name="examples-db-docdb"></a>


|  Travailler avec les données  |  Utilisation de la base de données  | 
| --- | --- | 
| API non SDK : bibliothèque Java spécifique à MongoDB (par exemple [MongoDB pour Java](https://www.mongodb.com/developer/languages/java/)) ; votre code gère les connexions à la base de données ou un pool de connexions. | Client du service SDK : [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html) | 
| Exemples : [Guide du développeur de DocumentDB (Mongo)](https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html#connect_programmatically-tls_enabled) (sélectionnez l'onglet « Java ») |  | 

# Travaillez avec DynamoDB
<a name="examples-dynamodb"></a>

[DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) est un service de base de données NoSQL entièrement géré qui fournit des performances rapides et prévisibles ainsi qu'une évolutivité sans faille. Cette section explique comment utiliser DynamoDB à l'aide de la version 2.x. AWS SDK pour Java 

## Choisissez votre client DynamoDB
<a name="ddb-clients-overview"></a>

Le SDK propose deux approches principales pour travailler avec DynamoDB :

Client de bas niveau (`DynamoDbClient`)  
Fournit un accès direct aux opérations DynamoDB avec un contrôle total sur les demandes et les réponses. Utilisez ce client lorsque vous avez besoin d'un contrôle précis ou lorsque vous travaillez avec des schémas dynamiques.

Client amélioré (`DynamoDbEnhancedClient`)  
Propose une programmation orientée objet avec mappage automatique entre les objets Java et les éléments DynamoDB. Fournit également des fonctionnalités orientées document pour travailler avec des données de type JSON qui ne suivent pas un schéma fixe. Utilisez ce client lorsque vous travaillez avec des modèles de données bien définis ou des données de type document.

## Configuration des clients DynamoDB
<a name="ddb-configuration-setup"></a>

Avant d'utiliser DynamoDB, configurez votre client pour des performances et une fiabilité optimales.

### Comprendre le comportement des nouvelles tentatives de DynamoDB
<a name="ddb-retry-behavior"></a>

Les clients DynamoDB utilisent un nombre maximal de tentatives par défaut de 8, ce qui est supérieur à celui des autres clients. Service AWS Ce nombre de tentatives plus élevé permet de gérer la nature distribuée et les limites de capacité temporaires de DynamoDB. Pour plus d'informations sur les stratégies de nouvelle tentative, consultez[Configurez le comportement des nouvelles tentatives dans AWS SDK for Java 2.x](retry-strategy.md).

### Optimisez les performances avec des points de terminaison basés sur des comptes
<a name="ddb-account-based-endpoints-v2"></a>

DynamoDB [AWS propose des points de terminaison basés sur les comptes](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.SDKOverview.html#Programming.SDKs.endpoints) qui améliorent les performances en utilisant AWS votre identifiant de compte pour rationaliser le routage des demandes. 

Pour utiliser cette fonctionnalité, vous devez disposer de la version 2.28.4 ou supérieure du. AWS SDK for Java 2.x Vous pouvez trouver la dernière version dans le [dépôt central de Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/bom/versions). Les versions du SDK prises en charge utilisent automatiquement les nouveaux points de terminaison.

Pour désactiver le routage basé sur le compte, choisissez l'une des options suivantes :
+ Configurez un client `AccountIdEndpointMode` de service DynamoDB défini sur. `DISABLED`
+ Définissez une variable d'environnement.
+ Définissez une propriété du système JVM.
+ Mettez à jour le paramètre du fichier de AWS configuration partagé.

L'exemple suivant montre comment désactiver le routage basé sur un compte en configurant un client de service DynamoDB :

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

Pour plus d'informations sur les autres options de configuration, consultez la section [Points de terminaison basés sur un compte](https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html) dans le guide de référence des outils AWS SDKs et.

## Ce qui est abordé dans cette rubrique
<a name="ddb-topics-overview"></a>

Les sections suivantes expliquent comment utiliser DynamoDB :
+ [Travaillez avec des tables dans DynamoDB](examples-dynamodb-tables.md)- Créer, décrire, mettre à jour et supprimer des tables
+ [Travaillez avec des objets dans DynamoDB](examples-dynamodb-items.md)- Ajouter, récupérer et mettre à jour des éléments individuels
+ [Mappez des objets Java à des éléments DynamoDB à l'aide du AWS SDK for Java 2.x](dynamodb-enhanced-client.md)- Utilisez le mappage d'objets et les données orientées document avec le client amélioré

Pour des exemples de code DynamoDB supplémentaires, consultez la section Exemples de code [DynamoDB dans la bibliothèque d'exemples](java_dynamodb_code_examples.md) de code. AWS 

# Travaillez avec des tables dans DynamoDB
<a name="examples-dynamodb-tables"></a>

Les tables sont les conteneurs de tous les éléments d'une DynamoDB base de données. Avant de pouvoir ajouter ou supprimer des données DynamoDB, vous devez créer une table.

Pour chaque table, vous devez définir :
+ *Nom* de table unique pour votre compte et votre région.
+ Une *clé primaire* pour laquelle chaque valeur doit être unique : deux éléments de votre table ne peuvent pas avoir la même valeur de clé primaire.

  Une clé primaire peut être *simple*, constituée d'une seule clé de partition (HASH) ou *composite*, constituée d'une partition et d'une clé de tri (RANGE).

  Chaque valeur clé est associée à un *type de données*, énuméré par la [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)classe. La valeur de la clé peut être binaire (B), numérique (N) ou de type chaîne (S). Pour plus d'informations, consultez la section [Règles de dénomination et types de données](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) dans le Guide du Amazon DynamoDB développeur.
+  Le *débit alloué* désigne les valeurs qui définissent le nombre d'unités de capacité en lecture/écriture réservées pour la table.
**Note**  
Amazon DynamoDB la [tarification](https://aws.amazon.com/dynamodb/pricing/) est basée sur les valeurs de débit provisionnées que vous définissez sur vos tables. Ne réservez donc que la capacité dont vous pensez avoir besoin pour votre table.

  Le débit alloué pour une table peut être modifié à tout moment pour que vous puissiez ajuster la capacité si vos besoins évoluent.

## Créer une table
<a name="dynamodb-create-table"></a>

Utilisez `DynamoDbClient’s` `createTable` cette méthode pour créer une nouvelle DynamoDB table. Vous devez créer des attributs de table et un schéma de table qui sont utilisés pour identifier la clé primaire de votre table. Vous devez également fournir des valeurs initiales de débit alloué et un nom de table.

**Note**  
Si une table portant le nom que vous avez choisi existe déjà, un `[DynamoDbException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)` est généré.

### Créer une table avec une clé primaire simple
<a name="dynamodb-create-table-simple"></a>

Ce code crée une table avec un attribut qui est la clé primaire simple de la table. L'exemple utilise `[AttributeDefinition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeDefinition.html)` et `[KeySchemaElement](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/KeySchemaElement.html)` objecte pour. [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)

 **Importations** 

```
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;
```

 **Code** 

```
    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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java) sur GitHub.

### Créer une table avec une clé primaire composite
<a name="dynamodb-create-table-composite"></a>

L'exemple suivant crée une table avec deux attributs. Les deux attributs sont utilisés pour la clé primaire composite.

 **Importations** 

```
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;
```

 **Code** 

```
    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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTableCompositeKey.java) sur GitHub.

## Répertorier des tables
<a name="dynamodb-list-tables"></a>

Vous pouvez répertorier les tables d'une région donnée en appelant la `DynamoDbClient’s` `listTables` méthode.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, un [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)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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!");
    }
```

Par défaut, jusqu'à 100 tables sont renvoyées par appel. À utiliser `lastEvaluatedTableName` sur l'[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)objet renvoyé pour obtenir la dernière table évaluée. Vous pouvez utiliser cette valeur pour démarrer la liste après la dernière valeur renvoyée de la liste précédente.

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/ListTables.java) sur GitHub.

## Décrire (obtenir des informations) sur une table
<a name="dynamodb-describe-table"></a>

Utilisez `DynamoDbClient’s` `describeTable` cette méthode pour obtenir des informations sur une table.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, un [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)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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!");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DescribeTable.java) sur GitHub.

## Modifier (mettre à jour) une table
<a name="dynamodb-update-table"></a>

Vous pouvez modifier les valeurs de débit provisionnées de votre table à tout moment en appelant la `DynamoDbClient’s` `updateTable` méthode.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, un [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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!");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateTable.java) sur GitHub.

## Supprimer une table
<a name="dynamodb-delete-table"></a>

Pour supprimer une table, appelez la `DynamoDbClient’s` `deleteTable` méthode et indiquez le nom de la table.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, un [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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!");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteTable.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Instructions relatives à l'utilisation des tables](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html) dans le guide du Amazon DynamoDB développeur
+  [Utilisation des tableaux DynamoDB dans](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html) le guide du Amazon DynamoDB développeur

# Travaillez avec des objets dans DynamoDB
<a name="examples-dynamodb-items"></a>

Dans DynamoDB, un élément est un ensemble d'*attributs*, chacun ayant un *nom* et une *valeur*. Une valeur d'attribut peut être de type scalar, set ou document. Pour plus d'informations, consultez la section [Règles de dénomination et types de données](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) dans le Guide du Amazon DynamoDB développeur.

## Extraction (get) d’un élément d'une table
<a name="dynamodb-get-item"></a>

Appelez la `getItem` méthode DynamoDbClient's et transmettez-lui un [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)objet avec le nom de la table et la valeur de la clé primaire de l'élément souhaité. Elle renvoie un [GetItemResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemResponse.html)objet avec tous les attributs de cet élément. Vous pouvez spécifier une ou plusieurs [expressions de projection](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) dans `GetItemRequest` pour extraire des attributs spécifiques.

Vous pouvez utiliser la `item()` méthode de l'`GetItemResponse`objet renvoyé pour récupérer une [carte](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) des paires clé (chaîne [AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html)) et valeur () associées à l'élément.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/GetItem.java) sur GitHub.

## Extraire (get) un élément d'une table à l'aide du client asynchrone
<a name="id1ddb"></a>

Invoquez la `getItem` méthode du DynamoDbAsyncClient et transmettez-lui un [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)objet avec le nom de la table et la valeur de la clé primaire de l'élément souhaité.

Vous pouvez renvoyer une instance [Collection](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html) avec tous les attributs de cet élément (reportez-vous à l'exemple suivant).

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/DynamoDBAsyncGetItem.java) sur GitHub.

## Ajouter un nouvel élément à une table
<a name="dynamodb-add-item"></a>

Créez un [mappage](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) des paires clé-valeur qui représentent les attributs de l'élément. Elles doivent inclure les valeurs des champs de clé primaire de la table. Si l'élément identifié par la clé primaire existe déjà, ses champs sont *mis à jour* par la demande.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, un [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/PutItem.java) sur GitHub.

## Mettre à jour un élément existant dans une table
<a name="dynamodb-update-item"></a>

Vous pouvez mettre à jour un attribut pour un élément déjà existant dans une table à l'aide de la méthode `updateItem` d'DynamoDbClient, en fournissant un nom de table, une valeur de clé primaire et un mappage des champs à mettre à jour.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, ou si l'élément identifié par la clé primaire que vous avez transmise n'existe pas, un [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
    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!");
    }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateItem.java) sur GitHub.

## Supprimer un élément existant d’une table
<a name="dynamodb-delete-item"></a>

Vous pouvez supprimer un élément existant dans une table en utilisant la `deleteItem` méthode DynamoDbClient's et en fournissant un nom de table ainsi que la valeur de la clé primaire.

**Note**  
Si la table nommée n'existe pas pour votre compte et votre région, ou si l'élément identifié par la clé primaire que vous avez transmise n'existe pas, un [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)est généré.

 **Importations** 

```
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;
```

 **Code** 

```
  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);
        }
    }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteItem.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Directives relatives à l'utilisation des éléments](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/best-practices.html) du guide du Amazon DynamoDB développeur
+  [Utilisation des éléments contenus DynamoDB dans](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/WorkingWithItems.html) le guide du Amazon DynamoDB développeur

# Mappez des objets Java à des éléments DynamoDB à l'aide du AWS SDK for Java 2.x
<a name="dynamodb-enhanced-client"></a>

L'API [DynamoDB Enhanced Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) est une bibliothèque de haut niveau qui succède à la classe `DynamoDBMapper` du SDK for Java v1.x. Il offre un moyen simple de mapper des classes côté client à des tables DynamoDB. Vous définissez les relations entre les tables et les classes de données correspondantes dans votre code. Après avoir défini ces relations, vous pouvez effectuer de manière intuitive diverses opérations de création, de lecture, de mise à jour ou de suppression (CRUD) sur des tables ou des éléments dans DynamoDB.

L'API DynamoDB Enhanced Client inclut également l'API [Enhanced Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) qui vous permet de travailler avec des éléments de type document qui ne suivent pas un schéma défini. 

**Topics**
+ [Commencez à utiliser l'API client améliorée DynamoDB](ddb-en-client-getting-started.md)
+ [Découvrez les principes de base de l'API client améliorée DynamoDB](ddb-en-client-use.md)
+ [Utiliser les fonctionnalités de cartographie avancées](ddb-en-client-adv-features.md)
+ [Travaillez avec des documents JSON avec l'API de document améliorée pour DynamoDB](ddb-en-client-doc-api.md)
+ [Utiliser des extensions pour personnaliser les opérations du client DynamoDB Enhanced](ddb-en-client-extensions.md)
+ [Utiliser l'API client améliorée DynamoDB de manière asynchrone](ddb-en-client-async.md)
+ [Annotations de classes de données](ddb-en-client-anno-index.md)

# Commencez à utiliser l'API client améliorée DynamoDB
<a name="ddb-en-client-getting-started"></a>

Le didacticiel suivant présente les principes fondamentaux dont vous avez besoin pour utiliser l'API client améliorée DynamoDB.

## Ajouter des dépendances
<a name="ddb-en-client-gs-dep"></a>

Pour commencer à utiliser l'API client améliorée DynamoDB dans votre projet, ajoutez une dépendance à l'artefact Maven. `dynamodb-enhanced` Cela est illustré dans les exemples suivants. 

------
#### [ 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>
```

Effectuez une recherche dans le référentiel central Maven pour trouver la [dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) et remplacez-la *<VERSION>* par cette valeur.

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

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

Effectuez une recherche dans le référentiel central Maven pour trouver la [dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) et remplacez-la *<VERSION>* par cette valeur.

------

# Générer un `TableSchema` à partir d'une classe de données
<a name="ddb-en-client-gs-tableschema"></a>

A `[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)` permet au client amélioré de mapper les valeurs d'attribut DynamoDB vers et depuis vos classes côté client. Dans ce didacticiel, vous découvrirez `TableSchema` s dérivé d'une classe de données statique et généré à partir de code à l'aide d'un générateur.

## Utiliser une classe de données annotée
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

Le SDK pour Java 2.x inclut [un ensemble d'annotations que vous pouvez utiliser avec une classe de](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html) données pour générer `TableSchema` rapidement un fichier permettant de mapper vos classes à des tables.

Commencez par créer une classe de données conforme à la [JavaBean spécification](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf). La spécification exige qu'une classe ait un constructeur public sans argument et dispose de getters et setters pour chaque attribut de la classe. Incluez une annotation au niveau de la classe pour indiquer que la classe de données est une. `DynamoDbBean` Incluez également, au minimum, une `DynamoDbPartitionKey` annotation sur le getter ou le setter pour l'attribut clé primaire. 

Vous pouvez appliquer des [annotations au niveau des attributs](ddb-en-client-anno-index.md) aux getters ou aux setters, mais pas aux deux.

**Note**  
Le terme `property` est normalement utilisé pour une valeur encapsulée dans un JavaBean. Toutefois, ce guide utilise ce terme à la `attribute` place, par souci de cohérence avec la terminologie utilisée par DynamoDB.

La `Customer` classe suivante affiche les annotations qui lient la définition de classe à une table DynamoDB.

### classe `Customer`
<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 + "]";
    }
}
```

Après avoir créé une classe de données annotée, utilisez-la pour créer la`TableSchema`, comme indiqué dans l'extrait de code suivant.

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

A `TableSchema` est conçu pour être statique et immuable. Vous pouvez généralement l'instancier au moment du chargement de la classe.

La méthode static `TableSchema.fromBean()` factory introspecte le bean pour générer le mappage des attributs de classe de données (propriétés) vers et depuis les attributs DynamoDB.

Pour un exemple d'utilisation d'un modèle de données composé de plusieurs classes de données, consultez la `Person` classe dans la [Travaillez avec des attributs tels que des beans, des cartes, des listes et des ensembles](ddb-en-client-adv-features-nested.md) section.

## Utilisez un constructeur
<a name="ddb-en-client-gs-tableschema-builder"></a>

Vous pouvez éviter le coût de l'introspection des haricots si vous définissez le schéma de table dans le code. Si vous codez le schéma, votre classe n'a pas besoin de suivre les normes de JavaBean dénomination ni d'être annotée. L'exemple suivant utilise un générateur et est équivalent à l'exemple de `Customer` classe qui utilise des annotations.

```
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();
```

# Créez un client amélioré et `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## Créez un client amélioré
<a name="ddb-en-client-getting-started-dynamodbTable-eclient"></a>

La [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)classe, ou son équivalent asynchrone [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html), est le point d'entrée pour utiliser l'API DynamoDB Enhanced Client.

Le client amélioré a besoin d'une norme `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)` pour effectuer le travail. L'API propose deux méthodes pour créer une `DynamoDbEnhancedClient` instance. La première option, illustrée dans l'extrait suivant, crée une norme dont les paramètres `DynamoDbClient` par défaut sont extraits des paramètres de configuration.

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

Si vous souhaitez configurer le client standard sous-jacent, vous pouvez le fournir à la méthode de création du client amélioré, comme indiqué dans l'extrait suivant.

```
// 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();
```

## Créer une instance `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

Considérez 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)comme la représentation côté client d'une table DynamoDB qui utilise la fonctionnalité de mappage fournie par a. `TableSchema` La `DynamoDbTable` classe fournit des méthodes pour les opérations CRUD qui vous permettent d'interagir avec une seule table DynamoDB.

`DynamoDbTable<T>`est une classe générique qui prend un seul argument de type, qu'il s'agisse d'une classe personnalisée ou d'un `EnhancedDocument` lorsque vous travaillez avec des éléments de type document. Ce type d'argument établit la relation entre la classe que vous utilisez et l'unique table DynamoDB.

Utilisez la méthode `table()` factory du `DynamoDbEnhancedClient` pour créer une `DynamoDbTable` instance, comme indiqué dans l'extrait de code suivant.

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

`DynamoDbTable`les instances sont candidates aux singletons car elles sont immuables et peuvent être utilisées dans l'ensemble de votre application.

Votre code possède désormais une représentation en mémoire d'une table DynamoDB qui peut fonctionner avec des instances. `Customer` La table DynamoDB réelle peut exister ou ne pas exister. Si la table nommée existe `Customer` déjà, vous pouvez commencer à effectuer des opérations CRUD sur elle. Si elle n'existe pas, utilisez l'`DynamoDbTable`instance pour créer la table comme indiqué dans la section suivante.

# Créez une table DynamoDB si nécessaire
<a name="ddb-en-client-gs-ddbtable"></a>

Après avoir créé une `DynamoDbTable` instance, utilisez-la pour créer une *seule fois* une table dans DynamoDB.

## Créer un exemple de code de table
<a name="ddb-en-client-gs-ddbtable-createex"></a>

L'exemple suivant crée une table DynamoDB basée sur `Customer` la classe de données. 

Cet exemple crée une table DynamoDB dont le nom est identique au `Customer` nom de classe, mais le nom de la table peut être différent. Quel que soit le nom que vous donnez à la table, vous devez utiliser ce nom dans d'autres applications pour travailler avec la table. Fournissez ce nom à la `table()` méthode chaque fois que vous créez un autre `DynamoDbTable` objet afin de travailler avec la table DynamoDB sous-jacente.

Le paramètre Java lambda,`builder`, transmis à la `createTable` méthode vous permet de [personnaliser le tableau](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html). Dans cet exemple, le [débit provisionné](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual) est configuré. Si vous souhaitez utiliser les paramètres par défaut lorsque vous créez une table, ignorez le générateur, comme indiqué dans l'extrait de code suivant.

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

Lorsque les paramètres par défaut sont utilisés, les valeurs du débit provisionné ne sont pas définies. Au lieu de cela, le mode de facturation de la table est défini [sur demande](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand).

L'exemple utilise également un `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)` avant de tenter d'imprimer le nom de la table reçu dans la réponse. La création d'une table prend un certain temps. Par conséquent, l'utilisation d'un serveur signifie que vous n'avez pas à écrire une logique qui interroge le service DynamoDB pour vérifier si la table existe avant de l'utiliser.

### Importations
<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;
```

### Code
<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.");
     }
 }
```

**Note**  
Les noms d'attributs d'une table DynamoDB commencent par une lettre minuscule lorsque la table est générée à partir d'une classe de données. Si vous souhaitez que le nom d'attribut de la table commence par une lettre majuscule, utilisez l'[`@DynamoDbAttribute(NAME)`annotation](ddb-en-client-adv-features-inex-attr.md) et indiquez le nom souhaité en tant que paramètre.

# Réaliser des opérations
<a name="ddb-en-client-gs-use"></a>

Une fois la table créée, utilisez l'`DynamoDbTable`instance pour effectuer des opérations sur la table DynamoDB. 

Dans l'exemple suivant, un singleton `DynamoDbTable<Customer>` est transmis en tant que paramètre avec une instance de [classe de `Customer` données](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) pour ajouter un nouvel élément à la table.

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

## Objet `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"));
```

Avant d'envoyer l'`customer`objet au service DynamoDB, enregistrez le résultat de la méthode de l'objet `toString()` pour le comparer à ce que le client amélioré envoie.

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

La journalisation au niveau du fil indique la charge utile de la demande générée. Le client amélioré a généré la représentation de bas niveau à partir de la classe de données. L'`regDate`attribut, qui est un `Instant` type en Java, est représenté sous la forme d'une chaîne DynamoDB.

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

# Travailler avec une table existante
<a name="ddb-en-client-gs-existingtable"></a>

La section précédente a montré comment créer une table DynamoDB à partir d'une classe de données Java. Si vous possédez déjà une table et que vous souhaitez utiliser les fonctionnalités du client amélioré, vous pouvez créer une classe de données Java qui fonctionnera avec la table. Vous devez examiner la table DynamoDB et ajouter les annotations nécessaires à la classe de données. 

Avant de travailler avec une table existante, appelez la `DynamoDbEnhanced.table()` méthode. Cela a été fait dans l'exemple précédent avec l'instruction suivante.

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

Une fois l'`DynamoDbTable`instance renvoyée, vous pouvez commencer à travailler immédiatement avec la table sous-jacente. Il n'est pas nécessaire de recréer la table en appelant la `DynamoDbTable.createTable()` méthode.

L'exemple suivant illustre cela en récupérant immédiatement une `Customer` instance de la table 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());
```

**Important**  
Le nom de table utilisé dans la `table()` méthode doit correspondre au nom de table DynamoDB existant.

# Découvrez les principes de base de l'API client améliorée DynamoDB
<a name="ddb-en-client-use"></a>

Cette rubrique décrit les fonctionnalités de base de l'API DynamoDB Enhanced Client et les compare à l'API client [DynamoDB standard](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html).

Si vous découvrez l'API DynamoDB Enhanced Client, nous vous recommandons de suivre [le didacticiel d'introduction pour vous familiariser avec les](ddb-en-client-getting-started.md) classes fondamentales.

## Éléments DynamoDB en Java
<a name="ddb-en-client-use-usecase"></a>

Les tables DynamoDB stockent des éléments. Selon votre cas d'utilisation, les éléments du côté Java peuvent prendre la forme de données structurées statiquement ou de structures créées dynamiquement. 

Si votre cas d'utilisation nécessite des éléments dotés d'un ensemble cohérent d'attributs, utilisez des [classes annotées](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) ou utilisez un [générateur](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder) pour générer le type statique `TableSchema` approprié. 

Sinon, si vous devez stocker des éléments composés de différentes structures, créez un`DocumentTableSchema`. `DocumentTableSchema`fait partie de l'[API Enhanced Document](ddb-en-client-doc-api.md) et ne nécessite qu'une clé primaire de type statique et fonctionne avec des `EnhancedDocument` instances pour contenir les éléments de données. L'API de document améliorée est abordée dans une autre [rubrique.](ddb-en-client-doc-api.md)

## Types d'attributs pour les classes de modèles de données
<a name="ddb-en-client-use-types"></a>

Bien que DynamoDB prenne [en charge un petit nombre de types d'attributs](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) par rapport au système de types riches de Java, l'API DynamoDB Enhanced Client fournit des mécanismes permettant de convertir les membres d'une classe Java vers et depuis les types d'attributs DynamoDB.

Les types d'attributs (propriétés) de vos classes de données Java doivent être des types d'objets et non des primitives. Par exemple, utilisez toujours des types de données `Long` et des `Integer` objets, `long` et non des `int` primitives.

[Par défaut, l'API DynamoDB Enhanced Client prend en charge les convertisseurs d'attributs pour un grand nombre de types, [tels que](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html) Integer [[BigDecimal](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/BigDecimalAttributeConverter.html), String et](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html) Instant.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/InstantAsStringAttributeConverter.html) La liste apparaît dans les [classes d'implémentation connues de l' AttributeConverter interface](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html). La liste comprend de nombreux types et collections tels que des cartes, des listes et des ensembles.

Pour stocker les données d'un type d'attribut qui n'est pas pris en charge par défaut ou qui n'est pas conforme à la JavaBean convention, vous pouvez écrire une `AttributeConverter` implémentation personnalisée pour effectuer la conversion. Consultez la section sur la conversion d'attributs pour un [exemple](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example).

Pour stocker les données d'un type d'attribut dont la classe est conforme à la spécification Java Beans (ou d'une [classe de données immuable](ddb-en-client-use-immut.md)), vous pouvez adopter deux approches. 
+ Si vous avez accès au fichier source, vous pouvez annoter la classe avec `@DynamoDbBean` (ou`@DynamoDbImmutable`). La section qui traite des attributs imbriqués présente des [exemples](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-anno) d'utilisation de classes annotées.
+ Si vous n'avez pas accès au fichier source de la classe de JavaBean données pour l'attribut (ou si vous ne souhaitez pas annoter le fichier source d'une classe à laquelle vous avez accès), vous pouvez utiliser l'approche du générateur. Cela crée un schéma de table sans définir les clés. Vous pouvez ensuite imbriquer ce schéma de table dans un autre schéma de table pour effectuer le mappage. La section des attributs imbriqués contient un [exemple](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-builder) illustrant l'utilisation de schémas imbriqués.

### Valeurs nulles
<a name="ddb-en-client-use-types-nulls"></a>

Lorsque vous utilisez `putItem` cette méthode, le client amélioré n'inclut pas les attributs à valeur nulle d'un objet de données mappé dans la demande adressée à DynamoDB.

Le comportement par défaut du SDK pour les `updateItem` demandes supprime les attributs de l'élément de DynamoDB qui sont définis sur null dans l'objet que vous soumettez dans la méthode. `updateItem` Si vous avez l'intention de mettre à jour certaines valeurs d'attributs et de conserver les autres inchangées, deux options s'offrent à vous.
+ Récupérez l'élément (en utilisant`getItem`) avant de modifier les valeurs. En utilisant cette approche, le SDK soumet toutes les valeurs anciennes et mises à jour à DynamoDB.
+ Utilisez le `[IgnoreNullsMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html).SCALAR_ONLY` ou `IgnoreNullsMode.MAPS_ONLY` lorsque vous créez la demande pour mettre à jour l'élément. Les deux modes ignorent les propriétés à valeur nulle de l'objet qui représentent des attributs scalaires dans DynamoDB. La [Mettre à jour les éléments contenant des types complexes](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-updates) rubrique de ce guide contient plus d'informations sur les `IgnoreNullsMode` valeurs et sur la manière de travailler avec des types complexes.

L'exemple suivant illustre `ignoreNullsMode()` la `updateItem()` méthode.

```
    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]
```

## Méthodes de base du client DynamoDB Enhanced
<a name="ddb-en-client-use-basic-ops"></a>

Les méthodes de base du client amélioré correspondent aux opérations de service DynamoDB dont elles portent le nom. Les exemples suivants montrent la variante la plus simple de chaque méthode. Vous pouvez personnaliser chaque méthode en transmettant un objet de demande amélioré. Les objets de requête améliorés offrent la plupart des fonctionnalités disponibles dans le client DynamoDB standard. Ils sont entièrement documentés dans le Guide de référence des AWS SDK for Java 2.x API.

L'exemple utilise ce qui [classe `Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) est indiqué précédemment.

```
// 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));
```

## Comparez le client DynamoDB amélioré au client DynamoDB standard
<a name="ddb-en-client-use-compare"></a>

Les APIs clients DynamoDB (standard [et](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) amélioré) vous [permettent](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html) de travailler avec des tables DynamoDB pour effectuer des opérations CRUD (création, lecture, mise à jour et suppression) au niveau des données. La différence entre le client APIs réside dans la manière dont cela est accompli. Avec le client standard, vous travaillez directement avec des attributs de données de bas niveau. L'API client améliorée utilise des classes Java familières et correspond à l'API de bas niveau utilisée en arrière-plan.

Bien que les deux clients APIs prennent en charge les opérations au niveau des données, le client DynamoDB standard prend également en charge les opérations au niveau des ressources. Les opérations au niveau des ressources gèrent la base de données, telles que la création de sauvegardes, la liste des tables et la mise à jour des tables. L'API client améliorée prend en charge un certain nombre d'opérations au niveau des ressources, telles que la création, la description et la suppression de tables.

Pour illustrer les différentes approches utilisées par les deux clients APIs, les exemples de code suivants montrent la création de la même `ProductCatalog` table à l'aide du client standard et du client amélioré.

### Comparaison : création d'une table à l'aide du client DynamoDB standard
<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))
);
```

### Comparaison : création d'une table à l'aide du client DynamoDB Enhanced
<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))
        )
);
```

Le client amélioré utilise la classe de données annotée suivante. Le client DynamoDB Enhanced fait correspondre les types de données Java aux types de données DynamoDB pour un code moins détaillé et plus facile à suivre. `ProductCatalog`est un exemple d'utilisation d'une classe immuable avec le client DynamoDB Enhanced. L'utilisation de classes immuables pour les classes de données mappées est [abordée plus loin](ddb-en-client-use-immut.md) dans cette rubrique.

### classe `ProductCatalog`
<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);
        }
    }
}
```

Les deux exemples de code suivants illustrant une écriture par lots illustrent le caractère verbeux et le manque de sécurité de type liés à l'utilisation du client standard par opposition au client amélioré.

### Comparaison : écriture par lots à l'aide du client DynamoDB standard
<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());
    }
```

### Comparaison : écriture par lots à l'aide du client DynamoDB Enhanced
<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());
    }
```

# Travaillez avec des classes de données immuables
<a name="ddb-en-client-use-immut"></a>

La fonctionnalité de mappage de l'API DynamoDB Enhanced Client fonctionne avec des classes de données immuables. Une classe immuable ne possède que des méthodes getter et nécessite une classe de générateur que le kit SDK utilise pour créer des instances de la classe. Au lieu d'utiliser l'`@DynamoDbBean`annotation comme indiqué dans la [classe Customer](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust), les classes immuables utilisent l'`@DynamoDbImmutable`annotation, qui prend un paramètre indiquant la classe de générateur à utiliser.

La classe suivante est une version immuable de. `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); }
    }
}
```

Vous devez satisfaire aux exigences suivantes lorsque vous annotez une classe de données avec`@DynamoDbImmutable`.

1. Chaque méthode qui n'est pas une substitution `Object.class` et qui n'a pas été annotée `@DynamoDbIgnore` doit être un getter pour un attribut de la table DynamoDB.

1. Chaque getter doit avoir un setter correspondant distinguant majuscules et minuscules dans la classe de générateur.

1. Seule l'une des conditions de construction suivantes doit être respectée.
   + La classe de générateur doit avoir un constructeur public par défaut.
   + La classe de données doit avoir une méthode statique publique nommée `builder()` qui ne prend aucun paramètre et renvoie une instance de la classe de générateur. Cette option est affichée dans la `Customer` classe immuable.

1.  La classe builder doit avoir une méthode publique nommée `build()` qui ne prend aucun paramètre et renvoie une instance de la classe immuable. 

Pour créer un `TableSchema` pour votre classe immuable, utilisez la `fromImmutableClass()` méthode on `TableSchema` comme indiqué dans l'extrait suivant.

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

Tout comme vous pouvez créer une table DynamoDB à partir d'une classe mutable, vous pouvez en créer une à partir d'une classe immuable avec *un* appel unique à of, comme indiqué dans l'exemple `DynamoDbTable` d'`createTable()`extrait de code suivant.

```
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));
}
```

## Utilisez des bibliothèques tierces, telles que Lombok
<a name="ddb-en-client-use-immut-lombok"></a>

Les bibliothèques tierces, telles que [Project Lombok](https://projectlombok.org/), aident à générer du code standard associé à des objets immuables. L'API DynamoDB Enhanced Client fonctionne avec ces bibliothèques tant que les classes de données respectent les conventions détaillées dans cette section. 

L'exemple suivant montre la `CustomerImmutable` classe immuable avec les annotations Lombok. Notez comment la `onMethod` fonctionnalité de Lombok copie les annotations DynamoDB basées sur les attributs, telles que, sur le code généré. `@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;
}
```

# Expressions et conditions d'utilisation
<a name="ddb-en-client-expressions"></a>

[Les expressions de l'API DynamoDB Enhanced Client sont des représentations Java des expressions DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html)

L'API client améliorée DynamoDB utilise trois types d'expressions :

[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)  
La `Expression` classe est utilisée lorsque vous définissez des conditions et des filtres.

[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)  
Ce type d'expression représente [les conditions clés](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions) pour les opérations de requête.

[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)  
Cette classe vous aide à écrire des expressions de [mise à jour DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) et est actuellement utilisée dans le framework d'extension lorsque vous mettez à jour un élément.

## Anatomie de l'expression
<a name="ddb-en-client-expressions-compoonents"></a>

Une expression est composée des éléments suivants :
+ Une expression sous forme de chaîne (obligatoire). La chaîne contient une expression logique DynamoDB avec des noms d'espaces réservés pour les noms d'attributs et les valeurs d'attribut.
+ Une carte des valeurs d'expression (généralement obligatoire).
+ Carte des noms d'expressions (facultatif).

Utilisez un générateur pour générer un `Expression` objet qui prend la forme générale suivante.

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

`Expression`s nécessitent généralement une carte des valeurs d'expression. La carte fournit les valeurs des espaces réservés dans l'expression sous forme de chaîne. La clé de carte se compose du nom de l'espace réservé précédé de deux points (`:`) et la valeur de la carte est une instance de [AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html). La [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/AttributeValues.html)classe dispose de méthodes pratiques pour générer une `AttributeValue` instance à partir d'un littéral. Vous pouvez également utiliser le `AttributeValue.Builder` pour générer une `AttributeValue` instance.

L'extrait suivant montre une carte avec deux entrées après la ligne de commentaire 2. La chaîne transmise à la `expression()` méthode, affichée après la ligne de commentaire 1, contient les espaces réservés que DynamoDB résout avant d'effectuer l'opération. Cet extrait ne contient pas de carte des noms d'expressions, car le *prix* est un nom d'attribut autorisé.

```
    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();
```

Si un nom d'attribut dans la table DynamoDB est un mot réservé, commence par un chiffre ou contient un espace, une carte des noms d'expressions est requise pour le. `Expression`

Par exemple, si le nom de l'attribut ne figurait `1price` pas `price` dans l'exemple de code précédent, celui-ci devra être modifié comme indiqué dans l'exemple suivant.

```
        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();
```

Un espace réservé pour le nom d'une expression commence par le signe dièse (`#`). Une entrée pour la carte des noms d'expressions utilise l'espace réservé comme clé et le nom de l'attribut comme valeur. La carte est ajoutée au générateur d'expressions avec la `expressionNames()` méthode. DynamoDB résout le nom de l'attribut avant d'effectuer l'opération.

Les valeurs d'expression ne sont pas obligatoires si une fonction est utilisée dans l'expression sous forme de chaîne. Voici un exemple de fonction d'expression`attribute_exists(<attribute_name>)`.

L'exemple suivant crée un fichier `Expression` qui utilise une fonction [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions). Dans cet exemple, la chaîne d'expression n'utilise aucun espace réservé. Cette expression peut être utilisée lors d'une `putItem` opération visant à vérifier si un élément existe déjà dans la base de données avec une valeur d'`movie`attribut égale à celle de l'`movie`attribut de l'objet de données.

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

Le guide du développeur DynamoDB contient des informations complètes sur les expressions de [bas niveau utilisées](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html) avec DynamoDB.

## Expressions de conditions et conditions
<a name="ddb-en-client-expressions-cond"></a>

Lorsque vous utilisez les `deleteItem()` méthodes`putItem()`, et`updateItem()`, ainsi que lorsque vous utilisez des opérations de transaction et de traitement par lots, vous utilisez `[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)` des objets pour spécifier les conditions que DynamoDB doit respecter pour poursuivre l'opération. Ces expressions sont appelées expressions de condition. Pour un exemple, consultez l'expression de condition utilisée dans la `addDeleteItem()` méthode (après la ligne de commentaire 1) de l'[exemple de transaction](ddb-en-client-use-multiop-trans.md#ddb-en-client-use-multiop-trans-writeitems-opcondition) présenté dans ce guide.

Lorsque vous utilisez les `query()` méthodes, une condition est exprimée sous la forme d'un [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). La `QueryConditional` classe dispose de plusieurs méthodes pratiques statiques qui vous aident à écrire les critères qui déterminent les éléments à lire dans DynamoDB.

Pour des exemples`QueryConditionals`, consultez le premier exemple de code de la [`Query`exemples de méthodes](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-query-example) section de ce guide.

## Expressions de filtrage
<a name="ddb-en-client-expressions-filter"></a>

Les expressions de filtre sont utilisées dans les opérations de numérisation et de requête pour filtrer les éléments renvoyés. 

Une expression de filtre est appliquée une fois que toutes les données ont été lues dans la base de données. Le coût de lecture est donc le même que s'il n'y avait pas de filtre. [Le guide du *développeur Amazon DynamoDB* contient plus d'informations sur l'utilisation d'expressions de filtre pour [les opérations de requête et](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression) de numérisation.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.FilterExpression)

L'exemple suivant montre une expression de filtre ajoutée à une demande d'analyse. Les critères limitent les articles retournés aux articles dont le prix se situe entre 8,00 et 80,00€ inclus.

```
        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();
```

## Expressions de mise à jour
<a name="ddb-en-client-expressions-update"></a>

La méthode du client `updateItem()` DynamoDB Enhanced fournit une méthode standard pour mettre à jour des éléments dans DynamoDB. Toutefois, lorsque vous avez besoin de fonctionnalités supplémentaires, [UpdateExpressions](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)fournissez une représentation sécurisée de la syntaxe de l'expression de mise à jour [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html). Par exemple, vous pouvez l'utiliser `UpdateExpressions` pour augmenter les valeurs sans lire au préalable les éléments de DynamoDB, ou pour ajouter des membres individuels à une liste. Les expressions de mise à jour sont actuellement disponibles dans les extensions personnalisées de la `updateItem()` méthode.

Pour un exemple utilisant des expressions de mise à jour, consultez l'[exemple d'extension personnalisée](ddb-en-client-extensions-custom.md) présenté dans ce guide.

De plus amples informations sur les expressions de mise à jour sont disponibles dans le [manuel du développeur Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).

# Travailler avec des résultats paginés : scans et requêtes
<a name="ddb-en-client-use-multirecord"></a>

*Les `scan` `batch` méthodes `query` et de l'API DynamoDB Enhanced Client renvoient des réponses contenant une ou plusieurs pages.* Une page contient un ou plusieurs éléments. Votre code peut traiter la réponse page par page ou traiter des éléments individuels.

Une réponse paginée renvoyée par le `DynamoDbEnhancedClient` client synchrone renvoie un [PageIterable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PageIterable.html)objet, tandis qu'une réponse renvoyée par le client asynchrone `DynamoDbEnhancedAsyncClient` renvoie un objet. [PagePublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PagePublisher.html)

Cette section traite du traitement des résultats paginés et fournit des exemples d'utilisation du scan et de la requête APIs.

## Analyser une table
<a name="ddb-en-client-use-multirecord-scan"></a>

La [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))méthode du SDK correspond à l'opération [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) du même nom. L'API DynamoDB Enhanced Client propose les mêmes options, mais elle utilise un modèle d'objet familier et gère la pagination à votre place.

Tout d'abord, nous explorons l'`PageIterable`interface en examinant la `scan` méthode de la classe de mappage synchrone, [DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html).

### Utiliser l'API synchrone
<a name="ddb-en-client-use-multirecord-scan-sync"></a>

L'exemple suivant montre la `scan` méthode qui utilise une [expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html) pour filtrer les éléments renvoyés. [ProductCatalog](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)Il s'agit de l'objet modèle présenté précédemment.

L'expression de filtrage affichée après la ligne de commentaire 2 limite les `ProductCatalog` articles renvoyés à ceux dont le prix est compris entre 8,00 et 80,00€ inclusivement.

Cet exemple exclut également les `isbn` valeurs en utilisant la `attributesToProject` méthode indiquée après la ligne de commentaire 1.

Après la ligne de commentaire 3`pagedResults`, l'`PageIterable`objet est renvoyé par la `scan` méthode. La `stream` méthode de `PageIterable` renvoi d'un [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)objet, que vous pouvez utiliser pour traiter les pages. Dans cet exemple, le nombre de pages est compté et enregistré.

À partir de la ligne de commentaire 4, l'exemple montre deux variantes d'accès aux `ProductCatalog` éléments. La version située après la ligne de commentaire 4a parcourt chaque page et trie et enregistre les éléments de chaque page. La version située après la ligne de commentaire 4b ignore l'itération de la page et accède directement aux éléments.

L'`PageIterable`interface offre plusieurs manières de traiter les résultats grâce à ses deux interfaces parentes : [https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html)et [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`apporte les `forEach` `spliterator` méthodes, et `SdkIterable` apporte la `stream` méthode. `iterator`

```
    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())
                );
    }
```

### Utiliser l'API asynchrone
<a name="ddb-en-client-use-multirecord-scan-async"></a>

La `scan` méthode asynchrone renvoie les résultats sous forme d'`PagePublisher`objet. L'`PagePublisher`interface comporte deux `subscribe` méthodes que vous pouvez utiliser pour traiter les pages de réponse. L'une des `subscribe` méthodes provient de l'interface `org.reactivestreams.Publisher` parent. Pour traiter les pages à l'aide de cette première option, transmettez une `[Subscriber](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Subscriber.html)` instance à la `subscribe` méthode. Le premier exemple qui suit montre l'utilisation de la `subscribe` méthode.

La deuxième `subscribe` méthode provient de l'[SdkPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)interface. Cette version de `subscribe` accepte un [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)plutôt qu'un`Subscriber`. Cette variante de `subscribe` méthode est illustrée dans le deuxième exemple qui suit.

L'exemple suivant montre la version asynchrone de la `scan` méthode qui utilise la même expression de filtre que dans l'exemple précédent. 

Après la ligne de commentaire 3, `DynamoDbAsyncTable.scan` renvoie un `PagePublisher` objet. Sur la ligne suivante, le code crée une instance de l'`org.reactivestreams.Subscriber`interface`ProductCatalogSubscriber`, qui s'abonne à la ligne de commentaire 4 `PagePublisher` après.

L'`Subscriber`objet collecte les `ProductCatalog` éléments de chaque page de la `onNext` méthode après la ligne de commentaire 8 dans l'exemple `ProductCatalogSubscriber` de classe. Les éléments sont stockés dans la `List` variable privée et sont accessibles dans le code d'appel avec la `ProductCatalogSubscriber.getSubscribedItems()` méthode. Ceci est appelé après la ligne de commentaire 5.

Une fois la liste récupérée, le code trie tous les `ProductCatalog` articles par prix et enregistre chaque article.

La `ProductCatalogSubscriber` classe [CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)in bloque le fil d'appel jusqu'à ce que tous les éléments aient été ajoutés à la liste avant de continuer après la ligne de commentaire 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;
        }
    }
```

L'exemple d'extrait de code suivant utilise la version de la `PagePublisher.subscribe` méthode qui accepte une ligne de commentaire `Consumer` 6 après. Le paramètre Java lambda consomme des pages, qui traitent ensuite chaque élément. Dans cet exemple, chaque page est traitée et les éléments de chaque page sont triés puis enregistrés.

```
        // 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.
```

La `items` méthode qui consiste à `PagePublisher` déballer les instances du modèle afin que votre code puisse traiter les éléments directement. Cette approche est illustrée dans l'extrait suivant.

```
        // 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.
```

## Interroger une table
<a name="ddb-en-client-use-multirecord-query"></a>

Vous pouvez utiliser le client DynamoDB amélioré pour interroger votre table et récupérer plusieurs éléments répondant à des critères spécifiques. La [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))méthode recherche des éléments en fonction des valeurs de clé primaire à l'`@DynamoDbPartitionKey`aide `@DynamoDbSortKey` des annotations facultatives définies dans votre classe de données.

La `query()` méthode nécessite une valeur de clé de partition et accepte éventuellement les conditions de clé de tri pour affiner davantage les résultats. Comme l'`scan`API, les requêtes renvoient a `PageIterable` pour les appels synchrones et a `PagePublisher` pour les appels asynchrones.

### `Query`exemples de méthodes
<a name="ddb-en-client-use-multirecord-query-example"></a>

L'exemple de code de `query()` méthode qui suit utilise la `MovieActor` classe. La classe de données définit une clé primaire composite composée de l'**`movie`**attribut en tant que clé de partition et de l'**`actor`**attribut en tant que clé de tri. 

#### classe `MovieActor`
<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);
        }
    }
}
```

Les exemples de code qui suivent portent sur les éléments suivants.

#### Éléments du `MovieActor` tableau
<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'}
```

Le code suivant définit deux `QueryConditional` instances : `keyEqual` (après la ligne de commentaire 1) et `sortGreaterThanOrEqualTo` (après la ligne de commentaire 1a).

#### Éléments de requête par clé de partition
<a name="keyEqual-query-conditional-example"></a>

L'`keyEqual`instance fait correspondre les éléments dont la valeur de clé de partition est de **`movie01`**. 

Cet exemple définit également une expression de filtre après la ligne de commentaire 2 qui filtre tout élément dépourvu de **`actingschoolname`**valeur.

`QueryEnhancedRequest`Combine la condition clé et l'expression du filtre pour la requête.

```
    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 — Sortie utilisant la `keyEqual` requête conditionnelle**  
Voici le résultat de l'exécution de la méthode. La sortie affiche les éléments dont `movieName` la valeur est **movie01** et n'affiche aucun élément dont la valeur est `actingSchoolName` égale à. **`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'}
```

#### Rechercher des éléments par clé de partition et clé de tri
<a name="sort-type-query-conditional-example"></a>

`sortGreaterThanOrEqualTo``QueryConditional`**Affine une correspondance de clé de partition (**movie01**) en ajoutant une condition de clé de tri pour les valeurs supérieures ou égales à actor2.**

[`QueryConditional`les méthodes](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html) qui commencent par `sort` nécessitent qu'une valeur de clé de partition corresponde et affinent davantage la requête par une comparaison basée sur la valeur de la clé de tri. `Sort`dans le nom de la méthode ne signifie pas que les résultats sont triés, mais qu'une valeur de clé de tri sera utilisée pour la comparaison.

Dans l'extrait suivant, nous modifions la demande de requête affichée précédemment après la ligne de commentaire 3. Cet extrait remplace la requête conditionnelle « KeyEqual » par la requête conditionnelle « sortGreaterThan OrEqualTo » définie après la ligne de commentaire 1a. Le code suivant supprime également l'expression du filtre.

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

**Example — Sortie utilisant la `sortGreaterThanOrEqualTo` requête conditionnelle**  
La sortie suivante affiche les résultats de la requête. **La requête renvoie les éléments dont `movieName` la valeur est égale à **movie01** et uniquement les éléments dont `actorName` la valeur est supérieure ou égale à actor2.** Comme nous supprimons le filtre, la requête renvoie des éléments qui n'ont aucune valeur pour l'`actingSchoolName`attribut.  

```
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'}
```

# Effectuer des opérations par lots
<a name="ddb-en-client-use-multiop-batch"></a>

[L'API DynamoDB Enhanced Client propose deux méthodes par lots [`batchGetItem`, () et (](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))

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

Avec [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))cette méthode, vous pouvez récupérer jusqu'à 100 éléments individuels dans plusieurs tables dans une seule demande globale. L'exemple suivant utilise les classes de [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)données [`Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust)et présentées précédemment.

Dans l'exemple qui suit les lignes 1 et 2, vous créez `[ReadBatch](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ReadBatch.html)` des objets que vous ajoutez ultérieurement en tant que paramètres à la `batchGetItem()` méthode après la ligne de commentaire 3. 

Le code situé après la ligne de commentaire 1 crée le lot à lire dans le `Customer` tableau. Le code situé après la ligne de commentaire 1a montre l'utilisation d'un `[GetItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/GetItemEnhancedRequest.Builder.html)` générateur qui prend une valeur de clé primaire et une valeur de clé de tri pour spécifier l'élément à lire. Si la classe de données possède une clé composite, vous devez fournir à la fois la valeur de la clé de partition et la valeur de la clé de tri. 

Contrairement à la spécification de valeurs clés pour demander un élément, vous pouvez utiliser une classe de données pour demander un élément, comme indiqué après la ligne de commentaire 1b. Le SDK extrait les valeurs clés en arrière-plan avant de soumettre la demande.

[Lorsque vous spécifiez l'élément à l'aide de l'approche basée sur les clés, comme indiqué dans les deux instructions situées après 2a, vous pouvez également spécifier que DynamoDB doit effectuer une lecture très cohérente.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html) Lorsque la `consistentRead()` méthode est utilisée, elle doit être utilisée sur tous les éléments demandés pour la même table.

Pour récupérer les éléments trouvés par DynamoDB, utilisez `[resultsForTable() ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#resultsForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` la méthode indiquée après la ligne de commentaire 4. Appelez la méthode pour chaque table lue dans la demande. `resultsForTable()`renvoie une liste des éléments trouvés que vous pouvez traiter à l'aide de n'importe quelle `java.util.List` méthode. Cet exemple enregistre chaque élément.

Pour découvrir les éléments que DynamoDB n'a pas traités, utilisez l'approche indiquée après la ligne de commentaire 5. La `BatchGetResultPage` classe possède la `[unprocessedKeysForTable()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#unprocessedKeysForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` méthode qui vous donne accès à chaque clé non traitée. La [référence de l'BatchGetItem API](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) contient plus d'informations sur les situations qui se traduisent par des éléments non traités.

```
    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()));
        });
    }
```

Supposons que les éléments suivants se trouvent dans les deux tables avant d'exécuter l'exemple de code.

### Éléments figurant dans les tableaux
<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'}
```

La sortie suivante montre les éléments renvoyés et enregistrés après la ligne de commentaire 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'}
```

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

Le `batchWriteItem()` procédé place ou supprime plusieurs éléments dans une ou plusieurs tables. Vous pouvez spécifier jusqu'à 25 opérations de mise ou de suppression individuelles dans la demande. L'exemple suivant utilise les classes de [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)modèles [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)et présentées précédemment.

`WriteBatch`les objets sont créés après les lignes de commentaires 1 et 2. Pour le `ProductCatalog` tableau, le code place un élément et en supprime un. Pour le `MovieActor` tableau situé après la ligne de commentaire 2, le code place deux éléments et en supprime un.

La `batchWriteItem` méthode est appelée après la ligne de commentaire 3. Le `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteItemEnhancedRequest.Builder.html)` paramètre fournit les demandes par lots pour chaque table.

L'`[BatchWriteResult](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteResult.html)`objet renvoyé fournit des méthodes distinctes pour chaque opération afin de visualiser les demandes non traitées. Le code situé après la ligne de commentaire 4a fournit les clés pour les demandes de suppression non traitées et le code situé après la ligne de commentaire 4b fournit les éléments de saisie non traités.

```
    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()));
        }
    }
```

Les méthodes d'assistance suivantes fournissent les objets modèles pour les opérations de saisie et de suppression.

### Méthodes auxiliaires
<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.     }
```

Supposons que les tables contiennent les éléments suivants avant d'exécuter l'exemple de code.

```
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}
```

Une fois l'exemple de code terminé, les tableaux contiennent les éléments suivants.

```
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}
```

Notez dans le `MovieActor` tableau que l'élément du `Blue Jasmine` film a été remplacé par l'élément utilisé dans la demande de vente acquise via la méthode d'`getMovieActorBlanchettPartial()`assistance. Si aucune valeur d'attribut Data Bean n'a été fournie, la valeur de la base de données est supprimée. C'est pourquoi le résultat `actingSchoolName` est nul pour l'élément `Blue Jasmine` vidéo.

**Note**  
[Bien que la documentation de l'API suggère que des expressions de condition peuvent être utilisées et que les mesures de capacité consommée et de collecte peuvent être renvoyées avec des demandes d'envoi et de [suppression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/DeleteItemEnhancedRequest.html) individuelles, ce n'est pas le cas dans un scénario d'écriture par lots.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PutItemEnhancedRequest.html) Pour améliorer les performances des opérations par lots, ces options individuelles sont ignorées.

# Effectuer des opérations de transaction
<a name="ddb-en-client-use-multiop-trans"></a>

L'API DynamoDB Enhanced Client fournit `transactGetItems()` les méthodes et. `transactWriteItems()` Les méthodes de transaction du SDK for Java assurent l'atomicité, la cohérence, l'isolation et la durabilité (ACID) des tables DynamoDB, vous aidant ainsi à maintenir l'exactitude des données dans vos applications.

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

La `[transactGetItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactGetItems(java.util.function.Consumer))` méthode accepte jusqu'à 100 demandes individuelles d'articles. Tous les éléments sont lus en une seule transaction atomique. Le guide du *développeur Amazon DynamoDB* contient des informations sur les [conditions à l'origine de l'échec `transactGetItems()` d'une méthode, ainsi que sur le niveau d'isolation utilisé lorsque vous](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txgetitems) appelez. `[transactGetItem()](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-isolation)`

Après la ligne de commentaire 1 dans l'exemple suivant, le code appelle la `transactGetItems()` méthode avec un `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html)` paramètre. Le générateur `[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))` est invoqué trois fois avec un objet de données contenant les valeurs clés que le SDK utilisera pour générer la demande finale.

La demande renvoie une liste d'`[Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html)`objets après la ligne de commentaire 2. La liste des documents renvoyée contient des instances de [document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html) non nulles contenant des données d'article dans le même ordre que celui demandé. La `[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))` méthode convertit un objet non typé en `Document` objet Java typé si des données d'élément ont été renvoyées, sinon la méthode renvoie 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());
        }
    }
```

Les tables DynamoDB contiennent les éléments suivants avant l'exécution de l'exemple de code.

```
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'}
```

La sortie suivante est enregistrée. Si un article est demandé mais introuvable, il n'est pas retourné comme c'est le cas pour la demande pour le film nommé`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'}
```

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

Il `[transactWriteItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))` accepte jusqu'à 100 actions de mise, de mise à jour ou de suppression dans une seule transaction atomique sur plusieurs tables. Le guide du *développeur Amazon DynamoDB* contient des informations détaillées sur les restrictions et les conditions de défaillance du fonctionnement du service [DynamoDB sous-jacent](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems).

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

Dans l'exemple suivant, quatre opérations sont demandées pour deux tables. Les classes [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)de modèles correspondantes [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)ont été présentées précédemment.

Chacune des trois opérations possibles (put, update et delete) utilise un paramètre de demande dédié pour spécifier les détails. 

Le code après la ligne de commentaire 1 montre la variante simple de la `addPutItem()` méthode. La méthode accepte un `[MappedTableResource](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/MappedTableResource.html)` objet et l'instance d'objet de données à placer. L'instruction située après la ligne de commentaire 2 indique la variante qui accepte une `[TransactPutItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactPutItemEnhancedRequest.html)` instance. Cette variante vous permet d'ajouter d'autres options dans la demande, comme une expression conditionnelle. L'[exemple](#ddb-en-client-use-multiop-trans-writeitems-opcondition) suivant montre une expression de condition pour une opération individuelle.

Une opération de mise à jour est demandée après la ligne de commentaire 3. `[TransactUpdateItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactUpdateItemEnhancedRequest.Builder.html)`possède une `ignoreNulls()` méthode qui vous permet de configurer ce que le SDK fait avec `null` les valeurs de l'objet modèle. Si la `ignoreNulls()` méthode renvoie true, le SDK ne supprime pas les valeurs d'attribut de la table pour les attributs d'objets de données qui le sont`null`. Si la `ignoreNulls()` méthode renvoie false, le SDK demande au service DynamoDB de supprimer les attributs de l'élément de la table. La valeur par défaut pour `ignoreNulls` est false.

L'instruction située après la ligne de commentaire 4 montre la variante d'une demande de suppression qui prend un objet de données. Le client amélioré extrait les valeurs clés avant d'envoyer la demande finale.

```
    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())
        );
    }
```

Les méthodes d'assistance suivantes fournissent les objets de données pour les `add*Item` paramètres.

#### Méthodes auxiliaires
<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;
    }
```

Les tables DynamoDB contiennent les éléments suivants avant l'exécution de l'exemple de code.

```
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'}
```

Les éléments suivants figurent dans les tableaux une fois l'exécution du code terminée.

```
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'}
```

L'élément de la ligne 2 a été supprimé et les lignes 3 et 5 indiquent les articles qui ont été placés. La ligne 4 montre la mise à jour de la ligne 1. La `price` valeur est la seule valeur qui a changé sur l'élément. Si la valeur renvoyée `ignoreNulls()` était fausse, la ligne 4 ressemblerait à la ligne suivante.

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

### Exemple de vérification de l'état
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond"></a>

L'exemple suivant montre l'utilisation d'un contrôle de condition. Un contrôle de condition est utilisé pour vérifier l'existence d'un article ou pour vérifier l'état d'attributs spécifiques d'un article dans la base de données. L'article enregistré lors du contrôle de condition ne peut pas être utilisé lors d'une autre opération de la transaction.

**Note**  
Vous ne pouvez pas cibler le même élément avec plusieurs opérations contenues dans la même transaction. Par exemple, vous ne pouvez pas effectuer de vérification de condition et essayer de mettre à jour le même article dans le cadre de la même transaction.

L'exemple montre un type d'opération de chaque type dans une demande d'écriture d'éléments transactionnelle. Après la ligne de commentaire 2, la `addConditionCheck()` méthode fournit la condition qui fait échouer la transaction si le `conditionExpression` paramètre est évalué à`false`. L'expression de condition renvoyée par la méthode indiquée dans le bloc des méthodes d'assistance vérifie si l'année de récompense du film n'`Sophie's Choice`est pas égale à`1982`. Si c'est le cas, l'expression est évaluée à `false` et la transaction échoue.

Ce guide aborde les [expressions](ddb-en-client-expressions.md) de manière approfondie dans une autre rubrique.

```
    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());
            });
        }
    }
```

Les méthodes d'assistance suivantes sont utilisées dans l'exemple de code précédent.

#### Méthodes auxiliaires
<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;
    }
```

Les tables DynamoDB contiennent les éléments suivants avant l'exécution de l'exemple de code.

```
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'}
```

Les éléments suivants figurent dans les tableaux une fois l'exécution du code terminée.

```
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'}
```

Les éléments restent inchangés dans les tables car la transaction a échoué. La `actingYear` valeur du film `Sophie's Choice` est`1982`, comme indiqué à la ligne 2 des éléments du tableau avant l'appel de la `transactWriteItem()` méthode.

Pour saisir les informations d'annulation de la transaction, placez l'appel de `transactWriteItems()` méthode dans un `try` bloc et `catch` le [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). Après la ligne de commentaire 4 de l'exemple, le code enregistre chaque `[CancellationReason](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CancellationReason.html)` objet. Étant donné que le code suivant la ligne de commentaire 3 de l'exemple indique que des valeurs doivent être renvoyées pour l'élément à l'origine de l'échec de la transaction, le journal affiche les valeurs de base de données brutes pour l'élément `Sophie's Choice` vidéo.

```
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.)
```

### Exemple de condition de fonctionnement unique
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition"></a>

L'exemple suivant montre l'utilisation d'une condition pour une seule opération dans une demande de transaction. L'opération de suppression après la ligne de commentaire 1 contient une condition qui vérifie la valeur de l'élément cible de l'opération par rapport à la base de données. Dans cet exemple, l'expression de condition créée avec la méthode d'assistance après la ligne de commentaire 2 indique que l'élément doit être supprimé de la base de données si l'année active du film n'est pas égale à 2013.

Les [expressions](ddb-en-client-expressions.md) sont abordées plus loin dans ce guide.

```
    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();
    }
```

Les méthodes d'assistance suivantes sont utilisées dans l'exemple de code précédent.

#### Méthodes auxiliaires
<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;
    }
```

Les tables DynamoDB contiennent les éléments suivants avant l'exécution de l'exemple de code.

```
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'}
```

Les éléments suivants figurent dans les tableaux une fois l'exécution du code terminée.

```
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'}
```

Les éléments restent inchangés dans les tables car la transaction a échoué. La `actingYear` valeur du film `Blue Jasmine` est `2013` celle indiquée à la ligne 2 dans la liste des éléments avant l'exécution de l'exemple de code.

Les lignes suivantes sont enregistrées dans la console.

```
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)
```

# Utiliser des indices secondaires
<a name="ddb-en-client-use-secindex"></a>

Les index secondaires améliorent l'accès aux données en définissant des clés alternatives que vous pouvez utiliser dans les opérations de requête et de numérisation. Les indices secondaires globaux (GSI) possèdent une clé de partition et une clé de tri qui peuvent être différentes de celles de la table de base. En revanche, les indices secondaires locaux (LSI) utilisent la clé de partition de l'index principal.

## Annoter une classe de données avec des annotations d'index secondaires
<a name="ddb-en-client-use-secindex-annomodel"></a>

Les attributs qui participent aux index secondaires nécessitent l'`@DynamoDbSecondarySortKey`annotation `@DynamoDbSecondaryPartitionKey` ou.

La classe suivante montre les annotations pour deux indices. Le GSI nommé *SubjectLastPostedDateIndex*utilise l'`Subject`attribut pour la clé de partition et `LastPostedDateTime` pour la clé de tri. Le LSI nommé *ForumLastPostedDateIndex*utilise le `ForumName` comme clé de partition et `LastPostedDateTime` comme clé de tri.

Notez que l'`Subject`attribut joue un double rôle. Il s'agit de la clé de tri de la clé primaire et de la clé de partition du GSI nommé *SubjectLastPostedDateIndex*.

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

La `MessageThread` classe peut être utilisée comme classe de données pour l'[exemple de table de threads](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html) du manuel *Amazon DynamoDB Developer* Guide.

#### Importations
<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 +
                '}';
    }
}
```

## Création de l'index
<a name="ddb-en-client-use-secindex-confindex"></a>

À partir de la version 2.20.86 du SDK pour Java, la `createTable()` méthode génère automatiquement des index secondaires à partir des annotations de classes de données. Par défaut, tous les attributs de la table de base sont copiés dans un index et les valeurs de débit allouées sont de 20 unités de capacité de lecture et 20 unités de capacité d'écriture.

Toutefois, si vous utilisez une version du SDK antérieure à la version 2.20.86, vous devez créer l'index avec le tableau, comme indiqué dans l'exemple suivant. Cet exemple crée les deux index de la `Thread` table. Le paramètre [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) possède des méthodes pour configurer les deux types d'index, comme indiqué après les lignes de commentaire 1 et 2. Vous utilisez la `indexName()` méthode du générateur d'index pour associer les noms d'index spécifiés dans les annotations de classe de données au type d'index souhaité.

Ce code configure tous les attributs de table pour qu'ils apparaissent dans les deux index après les lignes de commentaires 3 et 4. De plus amples informations sur [les projections d'attributs](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Projections) sont disponibles dans le manuel du *développeur 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))
                )
        );
```

## Requête à l'aide d'un index
<a name="ddb-en-client-use-secindex-query"></a>

L’exemple suivant interroge l’index secondaire global *ForumLastPostedDateIndex*.

Après la ligne de commentaire 2, vous créez un [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)objet obligatoire lors de l'appel de la méthode [DynamoDbIndex.query ()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbIndex.html#query(java.util.function.Consumer)). 

Vous obtenez une référence à l'index que vous souhaitez interroger après la ligne de commentaire 3 en transmettant le nom de l'index. Après la ligne de commentaire 4, vous appelez la `query()` méthode sur l'index qui transmet l'`QueryConditional`objet. 

Vous configurez également la requête pour renvoyer trois valeurs d'attribut, comme indiqué après la ligne de commentaire 5. Si elle n'`attributesToProject()`est pas appelée, la requête renvoie toutes les valeurs d'attribut. Notez que les noms d'attributs spécifiés commencent par des lettres minuscules. Ces noms d'attributs correspondent à ceux utilisés dans la table, pas nécessairement aux noms d'attributs de la classe de données.

Après la ligne de commentaire 6, parcourez les résultats, enregistrez chaque élément renvoyé par la requête et stockez-le également dans la liste pour le renvoyer à l'appelant.

```
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;
    }
```

Les éléments suivants existent dans la base de données avant l'exécution de la requête.

```
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}
```

Les instructions de journalisation des lignes 1 et 6 génèrent la sortie de console suivante.

```
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}
```

La requête a renvoyé des éléments avec une `forumName` valeur de *Forum02* et une `lastPostedDateTime` valeur supérieure ou égale à *2023.03.31*. Les résultats affichent `message` des valeurs avec une chaîne vide, bien que les `message` attributs contiennent des valeurs dans l'index. Cela est dû au fait que l'attribut message n'a pas été projeté par le code après la ligne de commentaire 5. 

# Utiliser les fonctionnalités de cartographie avancées
<a name="ddb-en-client-adv-features"></a>

Découvrez les fonctionnalités avancées du schéma de table dans l'API DynamoDB Enhanced Client.

## Comprendre les types de schéma de table
<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)`est l'interface permettant d'accéder à la fonctionnalité de mappage de l'API DynamoDB Enhanced Client. Il peut mapper un objet de données vers et depuis une carte de [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html). Un `TableSchema` objet doit connaître la structure de la table qu'il mappe. Ces informations de structure sont stockées dans un [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)objet.

L'API client améliorée comporte plusieurs implémentations de`TableSchema`, qui suivent. 

### Schéma de table généré à partir de classes annotées
<a name="ddb-en-client-adv-features-schema-mapped"></a>

La création d'une classe à `TableSchema` partir de classes annotées est une opération modérément coûteuse. Nous vous recommandons donc de ne le faire qu'une seule fois, au démarrage de l'application.

 [ BeanTableSchema ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.html)   
Cette implémentation est construite sur la base des attributs et des annotations d'une classe de bean. Un exemple de cette approche est présenté dans la [section Commencer](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean).  
Si a ne `BeanTableSchema` se comporte pas comme prévu, activez la journalisation du débogage pour. `software.amazon.awssdk.enhanced.dynamodb.beans`

[ImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchema.html)  
Cette implémentation est construite à partir d'une classe de données immuable. Cette approche est décrite dans la [Travaillez avec des classes de données immuables](ddb-en-client-use-immut.md) section.

### Schéma de table généré avec un générateur
<a name="ddb-en-client-adv-features-schema-static"></a>

Les éléments suivants `TableSchema` sont créés à partir du code à l'aide d'un générateur. Cette approche est moins coûteuse que celle qui utilise des classes de données annotées. L'approche du générateur évite l'utilisation d'annotations et ne nécessite pas de normes de JavaBean dénomination.

[StaticTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchema.html)  
Cette implémentation est conçue pour les classes de données mutables. La section de démarrage de ce guide explique comment [générer un à `StaticTableSchema` l'aide d'un générateur](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)  
De la même manière que vous créez un`StaticTableSchema`, vous générez une implémentation de ce type en `TableSchema` utilisant un [générateur](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html) à utiliser avec des classes de données immuables.

### Schéma de table pour les données sans schéma fixe
<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)  
Contrairement aux autres implémentations de`TableSchema`, vous ne définissez pas d'attributs pour une `DocumentTableSchema` instance. En général, vous ne spécifiez que les clés primaires et les fournisseurs de convertisseurs d'attributs. Une `EnhancedDocument` instance fournit les attributs que vous créez à partir d'éléments individuels ou d'une chaîne JSON.

# Inclure ou exclure explicitement des attributs
<a name="ddb-en-client-adv-features-inex-attr"></a>

L'API DynamoDB Enhanced Client propose des annotations pour empêcher les attributs de classe de données de devenir des attributs d'une table. Avec l'API, vous pouvez également utiliser un nom d'attribut différent du nom d'attribut de classe de données.

## Exclure les attributs
<a name="ddb-en-client-adv-features-inex-attr-ex"></a>

Pour ignorer les attributs qui ne doivent pas être mappés à une table DynamoDB, marquez l'attribut avec l'annotation. `@DynamoDbIgnore`

```
private String internalKey;

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

## Inclure les attributs
<a name="ddb-en-client-adv-features-inex-attr-in"></a>

Pour modifier le nom d'un attribut utilisé dans la table DynamoDB, marquez-le avec `@DynamoDbAttribute` l'annotation et saisissez un autre nom.

```
private String internalKey;

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

# Conversion des attributs de contrôle
<a name="ddb-en-client-adv-features-conversion"></a>

Par défaut, un schéma de table fournit des convertisseurs pour de nombreux types Java courants via une implémentation par défaut de l'`[AttributeConverterProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverterProvider.html)`interface. Vous pouvez modifier le comportement général par défaut à l’aide d’une implémentation de `AttributeConverterProvider` personnalisée. Vous pouvez également modifier le convertisseur pour un seul attribut.

Pour une liste des convertisseurs disponibles, consultez la documentation Java de [AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html)l'interface.

## Fournir des fournisseurs de convertisseurs d'attributs personnalisés
<a name="ddb-en-client-adv-features-conversion-prov"></a>

Vous pouvez fournir un seul `AttributeConverterProvider` ou une chaîne de `AttributeConverterProvider` s ordonnés par le biais de l'`@DynamoDbBean``(converterProviders = {…})`annotation. Toute personnalisation `AttributeConverterProvider` doit étendre l'`AttributeConverterProvider`interface.

Notez que si vous fournissez votre propre chaîne de fournisseurs de convertisseurs d'attributs, vous remplacerez le fournisseur de conversion par défaut,`DefaultAttributeConverterProvider`. Si vous souhaitez utiliser les fonctionnalités du`DefaultAttributeConverterProvider`, vous devez l'inclure dans la chaîne. 

Il est également possible d'annoter le bean avec un tableau `{}` vide. Cela désactive l'utilisation de tous les fournisseurs de convertisseurs d'attributs, y compris le fournisseur par défaut. Dans ce cas, tous les attributs à mapper doivent disposer de leur propre convertisseur d'attributs.

L'extrait suivant montre un fournisseur de conversion unique.

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

}
```

L'extrait suivant montre l'utilisation d'une chaîne de fournisseurs de convertisseurs. La valeur par défaut du SDK étant fournie en dernier, elle a la priorité la plus basse.

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

}
```

Les constructeurs de schémas de tables statiques ont une `attributeConverterProviders()` méthode qui fonctionne de la même manière. Cela est illustré dans l'extrait suivant.

```
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();
```

## Remplacer le mappage d'un seul attribut
<a name="ddb-en-client-adv-features-conversion-single"></a>

Pour modifier la façon dont un seul attribut est mappé, fournissez un `AttributeConverter` pour l'attribut. Cet ajout remplace tous les convertisseurs fournis `AttributeConverterProviders` dans le schéma de table. Cela ajoute un convertisseur personnalisé pour cet attribut uniquement. Les autres attributs, même ceux du même type, n'utiliseront pas ce convertisseur à moins qu'il ne soit explicitement spécifié pour ces autres attributs.

L'`@DynamoDbConvertedBy`annotation est utilisée pour spécifier la `AttributeConverter` classe personnalisée, comme indiqué dans l'extrait de code suivant.

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

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

Les générateurs de schémas statiques utilisent une `attributeConverter()` méthode de génération d'attributs équivalente. Cette méthode prend une instance d'un `AttributeConverter` comme le montre ce qui suit.

```
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();
```

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

Cet exemple montre une `AttributeConverterProvider` implémentation qui fournit un convertisseur d'attributs pour les [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)objets. 

La `SimpleUser` classe suivante contient un attribut nommé `lastUsedCookie` qui est une instance de`HttpCookie`.

Le paramètre des `@DynamoDbBean` annotations répertorie les deux `AttributeConverterProvider` classes qui fournissent des convertisseurs.

------
#### [ 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`L'exemple suivant fournit une instance de`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);
        }
    }
```

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

Dans la `transformFrom()` méthode de la `HttpCookieConverter` classe suivante, le code reçoit une `HttpCookie` instance et la transforme en une carte DynamoDB stockée sous forme d'attribut.

La `transformTo()` méthode reçoit un paramètre de carte DynamoDB, puis appelle le constructeur qui a besoin d'un `HttpCookie` nom et d'une valeur.

```
    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;
        }
    }
```

# Modifier le comportement de mise à jour des attributs
<a name="ddb-en-client-adv-features-upd-behavior"></a>

Vous pouvez personnaliser le comportement de mise à jour des attributs individuels lorsque vous effectuez une opération de *mise à jour*. [UpdateItem () et () sont des exemples d'opérations de mise à jour](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#updateItem(T)) [dans l'API DynamoDB Enhanced Client. transactWriteItems](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))

Imaginons, par exemple, que vous souhaitiez enregistrer un fichier *créé sur* horodatage dans votre dossier. Toutefois, vous souhaitez que sa valeur ne soit écrite que s'il n'existe aucune valeur existante pour l'attribut dans la base de données. Dans ce cas, vous utilisez le comportement de `[WRITE\$1IF\$1NOT\$1EXISTS](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html#WRITE_IF_NOT_EXISTS)` mise à jour.

L'exemple suivant montre l'annotation qui ajoute le comportement à l'`createdOn`attribut.

```
@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; }
}
```

Vous pouvez déclarer le même comportement de mise à jour lorsque vous créez un schéma de table statique, comme indiqué dans l'exemple suivant après la ligne de commentaire 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();
```

# Aplatir les attributs des autres classes
<a name="ddb-en-client-adv-features-flatmap"></a>

Si les attributs de votre table sont répartis dans plusieurs classes Java différentes, que ce soit par héritage ou par composition, l'API DynamoDB Enhanced Client permet de regrouper les attributs en une seule classe.

## Utiliser l'héritage
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

Si vos classes utilisent l'héritage, appliquez les approches suivantes pour aplatir la hiérarchie.

### Utiliser des haricots annotés
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

Pour l'approche d'annotation, les deux classes doivent porter l'`@DynamoDbBean`annotation et une classe doit porter une ou plusieurs annotations de clé primaire.

Vous trouverez ci-dessous des exemples de classes de données dotées d'une relation d'héritage.

------
#### [ 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 ]

L'[`onMethod`option](https://projectlombok.org/features/experimental/onX) de Lombok copie les annotations DynamoDB basées sur les attributs, telles que, sur le code généré. `@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;
}
```

------

### Utiliser des schémas statiques
<a name="ddb-en-client-adv-features-flatmap-inheritance-static"></a>

Pour l'approche du schéma statique, utilisez la `extend()` méthode du générateur pour réduire les attributs de la classe parent sur ceux de la classe enfant. Ceci est affiché après la ligne de commentaire 1 dans l'exemple suivant.

```
        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();
```

L'exemple de schéma statique précédent utilise les classes de données suivantes. Comme le mappage est défini lorsque vous créez le schéma de table statique, les classes de données ne nécessitent pas d'annotations.

#### Classes de données
<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;
}
```

------

## Utiliser la composition
<a name="ddb-en-client-adv-features-flatmap-comp"></a>

Si vos classes utilisent la composition, appliquez les approches suivantes pour aplatir la hiérarchie.

### Utiliser des haricots annotés
<a name="ddb-en-client-adv-features-flatmap-comp-anno"></a>

L'`@DynamoDbFlatten`annotation aplatit la classe contenue.

Les exemples de classes de données suivants utilisent l'`@DynamoDbFlatten`annotation pour ajouter efficacement tous les attributs de la `GenericRecord` classe contenue à la `Customer` classe.

------
#### [ 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;
}
```

------

Vous pouvez utiliser l'annotation aplatir pour aplatir autant de classes éligibles que nécessaire. Les contraintes suivantes s’appliquent :
+ Tous les noms d'attributs doivent être uniques une fois aplatis.
+ Il ne doit jamais y avoir plus d'une clé de partition, clé de tri ou nom de table.

### Utiliser des schémas statiques
<a name="ddb-en-client-adv-features-flatmap-comp-static"></a>

Lorsque vous créez un schéma de table statique, utilisez la `flatten()` méthode du générateur. Vous fournissez également les méthodes getter et setter qui identifient la classe contenue.

```
        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();
```

L'exemple de schéma statique précédent utilise les classes de données suivantes.

#### Classes de données
<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;
}
```

------

Vous pouvez utiliser le modèle Builder pour aplatir autant de classes éligibles que nécessaire.

## Implications pour les autres codes
<a name="ddb-en-client-adv-features-flatmap-compare"></a>

Lorsque vous utilisez l'`@DynamoDbFlatten`attribut (ou la méthode du `flatten()` générateur), l'élément de DynamoDB contient un attribut pour chaque attribut de l'objet composé. Il inclut également les attributs de l'objet composant. 

En revanche, si vous annotez une classe de données avec une classe composée et que vous ne l'utilisez pas`@DynamoDbFlatten`, l'élément est enregistré avec l'objet composé en tant qu'attribut unique.

Par exemple, comparez la `Customer` classe indiquée dans l'[exemple d'aplatissement avec la composition avec](#ddb-en-client-adv-features-flatmap-comp-anno) et sans aplatissement de l'attribut. `record` Vous pouvez visualiser la différence avec JSON, comme indiqué dans le tableau suivant.


****  

| Avec aplatissement | Sans aplatir | 
| --- | --- | 
| 3 attributs | 2 attributs | 
|  <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>  | 

La différence devient importante si vous disposez d'un autre code accédant à la table DynamoDB qui devrait trouver certains attributs.

# Travaillez avec des attributs tels que des beans, des cartes, des listes et des ensembles
<a name="ddb-en-client-adv-features-nested"></a>

Une définition de bean, telle que la `Person` classe illustrée ci-dessous, peut définir des propriétés (ou des attributs) qui font référence à des types dotés d'attributs supplémentaires. Par exemple, dans la `Person` classe, se `mainAddress` trouve une propriété qui fait référence à un `Address` bean qui définit des attributs de valeur supplémentaires. `addresses`fait référence à une carte Java, dont les éléments font référence à des `Address` beans. Ces types complexes peuvent être considérés comme des conteneurs d'attributs simples que vous utilisez pour leur valeur de données dans le contexte de DynamoDB. 

*DynamoDB désigne les propriétés de valeur des éléments imbriqués, tels que les cartes, les listes ou les beans, en tant qu'attributs imbriqués.* *Le guide du [développeur Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) fait référence à la forme enregistrée d'une carte, d'une liste ou d'un bean Java en tant que type de document.* Les attributs simples que vous utilisez pour leur valeur de données en Java sont appelés *types scalaires* dans DynamoDB. Ensembles, qui contiennent plusieurs éléments scalaires du même type, appelés *types d'ensembles*. 

Il est important de savoir que l'API DynamoDB Enhanced Client convertit une propriété qui est un bean en un type de document ArcMap DynamoDB lors de son enregistrement.

## classe `Person`
<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 +
               '}';
    }
}
```

## classe `Address`
<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 + '\'' +
                '}';
    }
}
```

## classe `PhoneNumber`
<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 + '\'' +
                '}';
    }
}
```

## Enregistrer des types complexes
<a name="ddb-en-client-adv-features-nested-mapping"></a>

### Utiliser des classes de données annotées
<a name="ddb-en-client-adv-features-nested-map-anno"></a>

Pour enregistrer les attributs imbriqués des classes personnalisées, il suffit de les annoter. La `Address` classe et la `PhoneNumber` classe affichées précédemment sont annotées uniquement avec l'`@DynamoDbBean`annotation. Lorsque l'API DynamoDB Enhanced Client crée le schéma de table pour la classe à `Person` l'aide de l'extrait suivant, l'API découvre l'utilisation des classes et `PhoneNumber` et crée les mappages `Address` correspondants pour fonctionner avec DynamoDB.

```
TableSchema<Person> personTableSchema = TableSchema.fromBean(Person.class);
```

### Utiliser des schémas abstraits avec des constructeurs
<a name="ddb-en-client-adv-features-nested-map-builder"></a>

L'approche alternative consiste à utiliser des générateurs de schémas de tables statiques pour chaque classe de bean imbriquée, comme indiqué dans le code suivant.

Les schémas de table des `PhoneNumber` classes `Address` et sont abstraits dans le sens où ils ne peuvent pas être utilisés avec une table DynamoDB. Cela est dû au fait qu'ils ne disposent pas de définitions pour la clé primaire. Ils sont toutefois utilisés comme schémas imbriqués dans le schéma de table de la `Person` classe.

Après les lignes de commentaire 1 et 2 de la définition de`PERSON_TABLE_SCHEMA`, vous pouvez voir le code qui utilise les schémas de table abstraits. L'utilisation de `documentOf` dans la `EnhanceType.documentOf(...)` méthode n'indique pas que la méthode renvoie un `EnhancedDocument` type d'API de document améliorée. Dans ce contexte, la `documentOf(...)` méthode renvoie un objet qui sait comment mapper son argument de classe vers et depuis les attributs de table DynamoDB en utilisant l'argument de schéma de table.

#### Code de schéma statique
<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();
```

## Attributs de projet de types complexes
<a name="ddb-en-client-adv-features-nested-projection"></a>

Pour les `scan()` méthodes `query()` et, vous pouvez spécifier les attributs que vous souhaitez voir renvoyés dans les résultats en utilisant des appels de méthode tels que `addNestedAttributeToProject()` et`attributesToProject()`. L'API DynamoDB Enhanced Client convertit les paramètres d'appel de méthode Java [en expressions de projection](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) avant l'envoi de la demande.

L'exemple suivant remplit le `Person` tableau avec deux éléments, puis exécute trois opérations de numérisation. 

Le premier scan accède à tous les éléments du tableau afin de comparer les résultats aux autres opérations d'analyse. 

Le second scan utilise la méthode du [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))générateur pour renvoyer uniquement la valeur de `street` l'attribut.

La troisième opération d'analyse utilise la méthode du [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...))générateur pour renvoyer les données de l'attribut de premier niveau,`hobbies`. Le type d'attribut de `hobbies` est une liste. Pour accéder à des éléments de liste individuels, effectuez une `get()` opération sur la liste.

```
        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
```

**Note**  
Si la `attributesToProject()` méthode suit une autre méthode de création qui ajoute les attributs que vous souhaitez projeter, la liste des noms d'attributs fournie au `attributesToProject()` remplace tous les autres noms d'attributs.  
Une analyse effectuée avec l'`ScanEnhancedRequest`instance figurant dans l'extrait suivant renvoie uniquement les données relatives aux loisirs.  

```
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]}
```
L'extrait de code suivant utilise d'abord la `attributesToProject()` méthode. Cet ordre préserve tous les autres attributs demandés.  

```
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]}
```

## Utiliser des types complexes dans les expressions
<a name="ddb-en-client-adv-features-nested-expressions"></a>

Vous pouvez utiliser des types complexes dans les expressions, telles que les expressions de filtre et les expressions de condition, en utilisant des opérateurs de déréférencement pour parcourir la structure du type complexe. Pour les objets et les cartes, utilisez le `. (dot)` et pour les éléments de liste `[n]` (crochets autour du numéro de séquence de l'élément). Vous ne pouvez pas faire référence à des éléments individuels d'un ensemble, mais vous pouvez utiliser la [`contains`fonction](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

L'exemple suivant montre deux expressions de filtre utilisées dans les opérations de numérisation. Les expressions de filtre spécifient les conditions de correspondance pour les éléments que vous souhaitez voir apparaître dans les résultats. L'exemple utilise`Person`,`Address`, et `PhoneNumber` les classes présentés précédemment.

```
    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");
    }
```

### Méthode d'assistance qui remplit le tableau
<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);
    }
```

### Représentation JSON des éléments de la base de données
<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"
  }
 ]
}
```

## Mettre à jour les éléments contenant des types complexes
<a name="ddb-en-client-adv-features-nested-updates"></a>

Pour mettre à jour un élément contenant des types complexes, vous avez deux approches de base :
+ Approche 1 : récupérez d'abord l'élément (en utilisant`getItem`), mettez à jour l'objet, puis appelez`DynamoDbTable#updateItem`.
+ Approche 2 : Ne récupérez pas l'élément, mais créez une nouvelle instance, définissez les propriétés que vous souhaitez mettre à jour et soumettez l'instance `DynamoDbTable#updateItem` en définissant la valeur appropriée de [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). Cette approche ne nécessite pas que vous récupériez l'élément avant de le mettre à jour.

Les exemples présentés dans cette section utilisent les `PhoneNumber` classes `Person``Address`,, et présentées précédemment.

### Approche de mise à jour 1 : récupération, puis mise à jour
<a name="ddb-en-client-adv-features-nested-updates-retreive"></a>

En utilisant cette approche, vous vous assurez qu'aucune donnée n'est perdue lors de la mise à jour. L'API DynamoDB Enhanced Client recrée le bean avec les attributs de l'élément enregistré dans DynamoDB, y compris les valeurs de types complexes. Vous devez ensuite utiliser les getters et setters pour mettre à jour le bean. L'inconvénient de cette approche est le coût que vous devez engager pour récupérer l'article en premier.

L'exemple suivant montre qu'aucune donnée n'est perdue si vous récupérez l'élément avant de le mettre à jour.

```
    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;
    }
```

### Approche de mise à jour 2 : utilisez une `IgnoreNullsMode` énumération sans récupérer l'élément au préalable
<a name="ddb-en-client-adv-features-nested-updates-nullmode"></a>

Pour mettre à jour un élément dans DynamoDB, vous pouvez fournir un nouvel objet contenant uniquement les propriétés que vous souhaitez mettre à jour et laisser les autres valeurs nulles. Avec cette approche, vous devez être conscient de la manière dont les valeurs nulles de l'objet sont traitées par le SDK et de la manière dont vous pouvez contrôler le comportement.

Pour spécifier les propriétés à valeur nulle que vous souhaitez que le SDK ignore, fournissez une `IgnoreNullsMode` énumération lorsque vous créez le. [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) À titre d'exemple d'utilisation de l'une des valeurs énumérées, l'extrait de code suivant utilise le 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"
    }
  }
*/
```

[Le guide du développeur Amazon DynamoDB contient plus d'informations sur les expressions de mise à jour.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html)

#### Descriptions des `IgnoreNullsMode` options
<a name="ignore-nulls-mode-descriptions"></a>
+ `IgnoreNullsMode.SCALAR_ONLY`- Utilisez ce paramètre pour mettre à jour les attributs scalaires à tous les niveaux. Le SDK crée une instruction de mise à jour qui envoie uniquement des attributs scalaires non nuls à DynamoDB. Le SDK ignore les attributs scalaires à valeur nulle d'un bean ou d'une carte, en conservant la valeur enregistrée dans DynamoDB.

  Lorsque vous mettez à jour un attribut scalaire de map ou bean, la carte doit déjà exister dans DynamoDB. Si vous ajoutez une carte ou un bean à l'objet qui n'existe pas déjà pour cet objet dans DynamoDB, le *message « Le chemin du document indiqué dans l'expression de mise à jour n'est pas `DynamoDbException` valide pour la mise à jour* » s'affiche. Vous devez utiliser `MAPS_ONLY` le mode pour ajouter un bean ou une carte à DynamoDB avant de mettre à jour l'un de ses attributs.
+ `IgnoreNullsMode.MAPS_ONLY`- Utilisez ce paramètre pour ajouter ou remplacer des propriétés qui sont un bean ou une carte. Le SDK remplace ou ajoute toute carte ou bean fourni dans l'objet. Tous les beans ou cartes dont la valeur est nulle dans l'objet sont ignorés, ce qui permet de conserver la carte qui existe dans DynamoDB.
+ `IgnoreNullsMode.DEFAULT`- Avec ce paramètre, le SDK n'ignore jamais les valeurs nulles. Les attributs scalaires de tous les niveaux qui sont nuls sont mis à jour à zéro. Le SDK met à jour toute propriété de type bean, map, list ou set dont la valeur est nulle dans l'objet en lui attribuant la valeur null dans DynamoDB. Lorsque vous utilisez ce mode (ou que vous n'en fournissez aucun puisqu'il s'agit du mode par défaut), vous devez d'abord récupérer l'élément afin que les valeurs fournies dans l'objet pour la mise à jour dans DynamoDB ne soient pas définies sur null, sauf si vous avez l'intention de définir les valeurs sur null.

Dans tous les modes, si vous fournissez un objet `updateItem` dont la liste ou l'ensemble n'est pas nul, la liste ou l'ensemble est enregistré dans DynamoDB. 

#### Pourquoi les modes ?
<a name="ddb-en-client-adv-features-nested-updates-nullmodes-why"></a>

Lorsque vous fournissez à un objet un bean ou un mappage vers la `updateItem` méthode, le SDK ne peut pas dire s'il doit utiliser les valeurs des propriétés du bean (ou les valeurs d'entrée dans la carte) pour mettre à jour l'élément, ou si l'intégralité bean/map doit remplacer ce qui a été enregistré dans DynamoDB.

À partir de notre exemple précédent qui montre d'abord la récupération de l'élément, essayons de mettre à jour l'`city`attribut de `mainAddress` sans la récupération.

```
/* 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'.
*/
```

Les deux exemples suivants montrent les utilisations des valeurs `SCALAR_ONLY` énumérées `MAPS_ONLY` et. `MAPS_ONLY`ajoute une carte et `SCALAR_ONLY` met à jour une carte.

##### Exemple de `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.
    }
```

Reportez-vous au tableau suivant pour savoir quelles valeurs nulles sont ignorées pour chaque mode. Vous pouvez souvent travailler avec l'un ou `SCALAR_ONLY` l'autre`MAPS_ONLY`, sauf lorsque vous travaillez avec des beans ou des cartes.


**Quelles propriétés à valeur nulle de l'objet soumis le SDK `updateItem` ignore-t-il pour chaque mode ?**  

| Type de propriété | en mode SCALAR\$1ONLY | en mode MAPS\$1ONLY | en mode DEFAULT | 
| --- | --- | --- | --- | 
| Meilleur scalaire | Oui | Oui | Non | 
| Bean ou carte | Oui | Oui | Non | 
| Valeur scalaire d'un bean ou d'une entrée de carte | Oui1 | No2 | Non | 
| Liste ou ensemble | Oui | Oui | Non | 

1 Cela suppose que la carte existe déjà dans DynamoDB. Toute valeur scalaire (nulle ou non nulle) du bean ou de la carte que vous fournissez dans l'objet à mettre à jour nécessite qu'un chemin d'accès à la valeur existe dans DynamoDB. Le SDK construit un chemin d'accès à l'attribut en utilisant l'opérateur de `. (dot)` déréférencement avant de soumettre la demande.

2 Puisque vous utilisez le `MAPS_ONLY` mode pour remplacer complètement ou ajouter un bean ou une map, toutes les valeurs nulles du bean ou de la map sont conservées dans la map enregistrée dans DynamoDB.

# Préservez les objets vides avec `@DynamoDbPreserveEmptyObject`
<a name="ddb-en-client-adv-features-empty"></a>

Si vous enregistrez un bean dans Amazon DynamoDB avec des objets vides et que vous souhaitez que le SDK recrée les objets vides lors de leur extraction, annotez le getter du bean interne avec. `@DynamoDbPreserveEmptyObject`

Pour illustrer le fonctionnement de l'annotation, l'exemple de code utilise les deux beans suivants.

## Exemple de haricots
<a name="ddb-en-client-adv-features-empty-ex1"></a>

La classe de données suivante contient deux `InnerBean` champs. La méthode getter`getInnerBeanWithoutAnno()`, n'est pas annotée avec. `@DynamoDbPreserveEmptyObject` La `getInnerBeanWithAnno()` méthode est annotée.

```
@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();
    }
}
```

Les instances de la `InnerBean` classe suivante sont des champs de `MyBean` et sont initialisées en tant qu'objets vides dans l'exemple de code.

```
@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 + '\'' +
                '}';
    }
}
```

L'exemple de code suivant enregistre un `MyBean` objet avec des beans internes initialisés dans DynamoDB, puis récupère l'élément. La sortie enregistrée indique que le n'`innerBeanWithoutAnno`est pas initialisé, mais qu'il `innerBeanWithAnno` a été créé.

```
    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;
    }
```

## Schéma statique alternatif
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Vous pouvez utiliser la `StaticTableSchema` version suivante des schémas de table à la place des annotations sur les beans.

```
    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();
    }
```

# Évitez de sauvegarder les attributs nuls des objets imbriqués
<a name="ddb-en-client-adv-features-ignore-null"></a>

Vous pouvez ignorer les attributs nuls des objets imbriqués lorsque vous enregistrez un objet de classe de données dans DynamoDB en appliquant l'annotation. `@DynamoDbIgnoreNulls` En revanche, les attributs de niveau supérieur contenant des valeurs nulles ne sont jamais enregistrés dans la base de données.

Pour illustrer le fonctionnement de l'annotation, l'exemple de code utilise les deux beans suivants.

## Exemple de haricots
<a name="ddb-en-client-adv-features-ignore-null-ex1"></a>

La classe de données suivante contient deux `InnerBean` champs. La méthode getter`getInnerBeanWithoutAnno()`, n'est pas annotée. La `getInnerBeanWithIgnoreNullsAnno()` méthode est annotée avec`@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();
    }
}
```

Les instances de la `InnerBean` classe suivante sont des champs de `MyBean` et sont utilisées dans l'exemple de code suivant.

```
@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();
    }
}
```

L'exemple de code suivant crée un `InnerBean` objet et attribue une valeur à un seul de ses deux attributs. 

```
    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);
    }
```

Pour visualiser les données de bas niveau envoyées à DynamoDB, le code enregistre la carte attributaire avant d'enregistrer l'objet. `MyBean`

La sortie enregistrée montre qu'elle `innerBeanWithIgnoreNullsAnno` produit un attribut,

```
innerBeanWithIgnoreNullsAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200)})
```

L'`innerBeanWithoutAnno`instance génère deux attributs. L'un des attributs a une valeur de 200 et l'autre est un attribut de valeur nulle.

```
innerBeanWithoutAnno=AttributeValue(M={innerBeanFieldInteger=AttributeValue(N=200), innerBeanFieldString=AttributeValue(NUL=true)})
```

## Représentation JSON de la carte attributaire
<a name="ddb-en-client-adv-features-ignore-null-ex2"></a>

La représentation JSON suivante permet de visualiser plus facilement les données enregistrées dans DynamoDB.

```
{
  "id": {
    "S": "1"
  },
  "innerBeanWithIgnoreNullsAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      }
    }
  },
  "innerBeanWithoutAnno": {
    "M": {
      "innerBeanFieldInteger": {
        "N": "200"
      },
      "innerBeanFieldString": {
        "NULL": true
      }
    }
  }
}
```

## Schéma statique alternatif
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

Vous pouvez utiliser la `StaticTableSchema` version suivante des schémas de table pour mettre en place des annotations de classe de données.

```
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();
}
```

# Travaillez avec des documents JSON avec l'API de document améliorée pour DynamoDB
<a name="ddb-en-client-doc-api"></a>

L'[API de document améliorée](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) pour AWS SDK for Java 2.x est conçue pour fonctionner avec des données orientées document qui n'ont aucun schéma fixe. Toutefois, il vous permet également d'utiliser des classes personnalisées pour mapper des attributs individuels.

 L'Enhanced Document API est le successeur de l'[API Document](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/DynamoDB.html) de la AWS SDK pour Java v1.x.

**Contents**
+ [Commencez à utiliser l'API Enhanced Document](ddb-en-client-doc-api-steps.md)
  + [Créez un `DocumentTableSchema` et un `DynamoDbTable`](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema)
+ [Créez des documents améliorés](ddb-en-client-doc-api-steps-create-ed.md)
  + [Construire à partir d'une chaîne JSON](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromJson)
  + [Construisez à partir d'éléments individuels](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts)
+ [Effectuer des opérations CRUD](ddb-en-client-doc-api-steps-use.md)
+ [Accédez aux attributs de document améliorés sous forme d'objets personnalisés](ddb-en-client-doc-api-convert.md)
+ [Utiliser et `EnhancedDocument` sans DynamoDB](ddb-en-client-doc-api-standalone.md)

# Commencez à utiliser l'API Enhanced Document
<a name="ddb-en-client-doc-api-steps"></a>

L'API de document améliorée nécessite les mêmes [dépendances](ddb-en-client-getting-started.md#ddb-en-client-gs-dep) que celles requises pour l'API client améliorée DynamoDB. Cela nécessite également une [`DynamoDbEnhancedClient`instance](ddb-en-client-getting-started-dynamodbTable.md#ddb-en-client-getting-started-dynamodbTable-eclient), comme indiqué au début de cette rubrique.

Étant donné que l'API Enhanced Document a été publiée avec la version 2.20.3 du AWS SDK for Java 2.x, vous avez besoin de cette version ou d'une version ultérieure.

## Créez un `DocumentTableSchema` et un `DynamoDbTable`
<a name="ddb-en-client-doc-api-steps-createschema"></a>

Pour appeler des commandes sur une table DynamoDB à l'aide de l'API Enhanced Document, associez la table à un objet de ressource < > [DynamoDbTablecôté client EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html). 

La `table()` méthode du client amélioré crée une `DynamoDbTable<EnhancedDocument>` instance et nécessite des paramètres pour le nom de la table DynamoDB et un. `DocumentTableSchema` 

Le générateur d'un [DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)nécessite une clé d'index principale et un ou plusieurs fournisseurs de convertisseurs d'attributs. La `AttributeConverterProvider.defaultProvider()` méthode fournit des convertisseurs pour les [types par défaut](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/package-summary.html). Il doit être spécifié même si vous fournissez un fournisseur de convertisseur d'attributs personnalisé. Vous pouvez ajouter une clé d'index secondaire facultative au générateur.

L'extrait de code suivant montre le code qui génère la représentation côté client d'une table DynamoDB qui stocke des objets sans schéma. `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.
```

Ce qui suit montre la représentation JSON d'un `person` objet utilisé dans cette section.

### `person`Objet JSON
<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"
    }
  ]
}
```

# Créez des documents améliorés
<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)` représente un objet de type document doté d'une structure complexe avec des attributs imbriqués. An `EnhancedDocument` nécessite des attributs de haut niveau qui correspondent aux attributs de clé primaire spécifiés pour le`DocumentTableSchema`. Le contenu restant est arbitraire et peut être composé d'attributs de haut niveau ou d'attributs profondément imbriqués.

Vous créez une `EnhancedDocument` instance à l'aide d'un générateur qui propose plusieurs méthodes pour ajouter des éléments.

## Construire à partir d'une chaîne JSON
<a name="ddb-en-client-doc-api-steps-create-ed-fromJson"></a>

Avec une chaîne JSON, vous pouvez créer un appel de méthode `EnhancedDocument` en un. L'extrait suivant crée une chaîne `EnhancedDocument` à partir d'une chaîne JSON renvoyée par la méthode d'`jsonPerson()`assistance. La `jsonPerson()` méthode renvoie la version de chaîne JSON de l'[objet person](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema-obj) affiché précédemment.

```
EnhancedDocument document = 
        EnhancedDocument.builder()
                        .json( jsonPerson() )
                        .build());
```

## Construisez à partir d'éléments individuels
<a name="ddb-en-client-doc-api-steps-create-ed-fromparts"></a>

Vous pouvez également créer une `EnhancedDocument` instance à partir de composants individuels à l'aide des méthodes de type sécurisé du générateur.

L'exemple suivant crée un document `person` amélioré similaire au document amélioré créé à partir de la chaîne JSON de l'exemple précédent.

```
        /* 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();
```

### Méthodes auxiliaires
<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"));

    }
```

# Effectuer des opérations CRUD
<a name="ddb-en-client-doc-api-steps-use"></a>

Après avoir défini une `EnhancedDocument` instance, vous pouvez l'enregistrer dans une table DynamoDB. L'extrait de code suivant utilise le [PersonDocument](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts) créé à partir d'éléments individuels.

```
documentDynamoDbTable.putItem(personDocument);
```

Après avoir lu une instance de document améliorée depuis DynamoDB, vous pouvez extraire les valeurs d'attribut individuelles à l'aide de getters, comme indiqué dans l'extrait de code suivant qui accède aux données enregistrées depuis le. `personDocument` Vous pouvez également extraire le contenu complet dans une chaîne JSON, comme indiqué dans la dernière partie de l'exemple de code.

```
        // 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`les instances peuvent être utilisées avec n'importe quelle méthode `[DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)` ou [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)à la place de classes de données mappées.

# Accédez aux attributs de document améliorés sous forme d'objets personnalisés
<a name="ddb-en-client-doc-api-convert"></a>

En plus de fournir une API pour lire et écrire des attributs avec des structures sans schéma, l'API Enhanced Document vous permet de convertir des attributs depuis et vers des instances de classes personnalisées.

L'API de document améliorée utilise `AttributeConverterProvider` les valeurs s et `AttributeConverter` s affichées dans la section de [conversion des attributs de contrôle](ddb-en-client-adv-features-conversion.md) dans le cadre de l'API client améliorée DynamoDB.

Dans l'exemple suivant, nous utilisons a `CustomAttributeConverterProvider` avec sa `AddressConverter` classe imbriquée pour convertir `Address` des objets. 

Cet exemple montre que vous pouvez mélanger des données provenant de classes et des données provenant de structures créées selon les besoins. Cet exemple montre également que les classes personnalisées peuvent être utilisées à n'importe quel niveau d'une structure imbriquée. Les `Address` objets de cet exemple sont des valeurs utilisées dans une carte.

```
    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'}
```

## Code de la `CustomAttributeConverterProvider`
<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;
        }
    }
}
```

## classe `Address`
<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;
                  }
                  }
```

## Méthode d'assistance qui fournit des adresses
<a name="ddb-en-client-doc-api-convert-helper"></a>

La méthode d'assistance suivante fournit la carte qui utilise des `Address` instances personnalisées pour les valeurs plutôt que des `Map<String, String>` instances génériques pour les valeurs.

```
    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);
    }
```

# Utiliser et `EnhancedDocument` sans DynamoDB
<a name="ddb-en-client-doc-api-standalone"></a>

Bien que vous utilisiez généralement une instance d'un `EnhancedDocument` pour lire et écrire des éléments DynamoDB de type document, elle peut également être utilisée indépendamment de DynamoDB. 

Vous pouvez `EnhancedDocuments` les utiliser pour leur capacité à convertir des chaînes JSON ou des objets personnalisés en cartes de bas niveau, `AttributeValues` comme indiqué dans l'exemple suivant.

```
    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'}
   */
```

**Note**  
Lorsque vous utilisez un document amélioré indépendant d'une table DynamoDB, assurez-vous de définir explicitement les fournisseurs de convertisseurs d'attributs dans le générateur.  
En revanche, le schéma de table de documents fournit les fournisseurs de conversion lorsqu'un document amélioré est utilisé avec une table DynamoDB.

# Utiliser des extensions pour personnaliser les opérations du client DynamoDB Enhanced
<a name="ddb-en-client-extensions"></a>

L'API DynamoDB Enhanced Client prend en charge les extensions de plug-in qui fournissent des fonctionnalités allant au-delà des opérations de mappage. Les extensions utilisent deux méthodes hook pour modifier les données lors des opérations de lecture et d'écriture :
+ `beforeWrite()`- Modifie une opération d'écriture avant qu'elle ne se produise
+ `afterRead()`- Modifie les résultats d'une opération de lecture après qu'elle se soit produite

Certaines opérations (telles que les mises à jour d'éléments) effectuent à la fois une écriture puis une lecture. Les deux méthodes hook sont donc appelées.

## Comment les extensions sont chargées
<a name="ddb-en-client-extensions-loading"></a>

Les extensions sont chargées dans l'ordre que vous spécifiez dans le générateur de clients amélioré. L'ordre de chargement peut être important car une extension peut agir sur des valeurs transformées par une extension précédente.

Par défaut, le client amélioré charge deux extensions :
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Assure un verrouillage optimiste
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Incrémente automatiquement les attributs du compteur

Vous pouvez modifier le comportement par défaut à l'aide du générateur de clients amélioré et charger n'importe quelle extension. Vous pouvez également n'en spécifier aucune si vous ne souhaitez pas utiliser les extensions par défaut.

**Important**  
Si vous chargez vos propres extensions, le client amélioré ne charge aucune extension par défaut. Si vous souhaitez obtenir le comportement fourni par l'une ou l'autre des extensions par défaut, vous devez l'ajouter explicitement à la liste des extensions.

L'exemple suivant montre comment charger une extension personnalisée nommée d'`verifyChecksumExtension`après le`VersionedRecordExtension`. Le n'`AtomicCounterExtension`est pas chargé dans cet exemple.

```
DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build();

DynamoDbEnhancedClient enhancedClient = 
    DynamoDbEnhancedClient.builder()
                          .dynamoDbClient(dynamoDbClient)
                          .extensions(versionedRecordExtension, verifyChecksumExtension)
                          .build();
```

## Détails et configuration des extensions disponibles
<a name="ddb-en-client-extensions-details"></a>

Les sections suivantes fournissent des informations détaillées sur chaque extension disponible dans le SDK.

### Mettez en œuvre un verrouillage optimiste avec le `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

L'`VersionedRecordExtension`extension permet un verrouillage optimiste en incrémentant et en suivant le numéro de version d'un élément au fur et à mesure que les éléments sont écrits dans la base de données. Une condition est ajoutée à chaque écriture qui entraîne l'échec de l'écriture si le numéro de version de l'élément persistant réel ne correspond pas à la valeur lue pour la dernière fois par l'application.

#### Configuration
<a name="ddb-en-client-extensions-VRE-conf"></a>

Pour spécifier l'attribut à utiliser pour suivre le numéro de version de l'article, balisez un attribut numérique dans le schéma du tableau.

L'extrait suivant indique que l'`version`attribut doit contenir le numéro de version de l'article.

```
    @DynamoDbVersionAttribute
    public Integer getVersion() {...};
    public void setVersion(Integer version) {...};
```

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

```
    .addAttribute(Integer.class, a -> a.name("version")
                                       .getter(Customer::getVersion)
                                       .setter(Customer::setVersion)
                                        // Apply the 'version' tag to the attribute.
                                       .tags(VersionedRecordExtension.AttributeTags.versionAttribute())
```

#### Comment ça marche
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

Le verrouillage optimiste avec le `VersionedRecordExtension` a l'impact suivant sur ces derniers `DynamoDbEnhancedClient` et sur `DynamoDbTable` les méthodes :

**`putItem`**  
Une valeur de version initiale de 0 est attribuée aux nouveaux éléments. Cela peut être configuré avec`@DynamoDbVersionAttribute(startAt = X)`.

**`updateItem`**  
Si vous récupérez un élément, mettez à jour une ou plusieurs de ses propriétés et tentez d'enregistrer les modifications, l'opération n'aboutit que si le numéro de version côté client et côté serveur correspondent.  
En cas de succès, le numéro de version est automatiquement incrémenté de 1. Cela peut être configuré avec`@DynamoDbVersionAttribute(incrementBy = X)`.

**`deleteItem`**  
L'`DynamoDbVersionAttribute`annotation n'a aucun effet. Vous devez ajouter une expression de condition manuellement lorsque vous supprimez un élément.  
L'exemple suivant ajoute une expression conditionnelle pour garantir que l'élément supprimé est bien celui qui a été lu. Dans l'exemple suivant, `recordVersion` l'attribut du bean est annoté avec`@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`: Cette méthode a le même comportement que`putItem`.
+ `addUpdateItem`: Cette méthode a le même comportement que`updateItem`.
+ `addDeleteItem`: Cette méthode a le même comportement que`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Cette méthode a le même comportement que`putItem`.
+ `addDeleteItem`: Cette méthode a le même comportement que`deleteItem`.

**Note**  
Les tables globales DynamoDB utilisent [une réconciliation « le dernier rédacteur gagne » entre les](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) mises à jour simultanées, DynamoDB faisant de son mieux pour déterminer le dernier rédacteur. Si vous utilisez des tables globales, cette règle du « dernier rédacteur gagne » signifie que les stratégies de verrouillage risquent de ne pas fonctionner comme prévu, car toutes les répliques finiront par converger en fonction de la dernière écriture déterminée par DynamoDB. 

#### Comment désactiver
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Pour désactiver le verrouillage optimiste, n'utilisez pas l'`@DynamoDbVersionAttribute`annotation.

### Implémentez des compteurs avec le `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

L'`AtomicCounterExtension`extension incrémente un attribut numérique balisé chaque fois qu'un enregistrement est écrit dans la base de données. Vous pouvez spécifier des valeurs de départ et d'incrémentation. Si aucune valeur n'est spécifiée, la valeur de départ est définie sur 0 et la valeur de l'attribut augmente de 1.

#### Configuration
<a name="ddb-en-client-extensions-ACE-conf"></a>

Pour spécifier quel attribut est un compteur, balisez un attribut de type `Long` dans le schéma du tableau.

L'extrait suivant montre l'utilisation des valeurs de début et d'incrément par défaut pour l'attribut. `counter`

```
    @DynamoDbAtomicCounter
    public Long getCounter() {...};
    public void setCounter(Long counter) {...};
```

L'approche du schéma de table statique est illustrée dans l'extrait suivant. L'extension du compteur atomique utilise une valeur de départ de 10 et augmente la valeur de 5 à chaque fois que l'enregistrement est écrit.

```
    .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))
```

### Ajoutez des horodatages avec le `AutoGeneratedTimestampRecordExtension`
<a name="ddb-en-client-extensions-AGTE"></a>

L'`AutoGeneratedTimestampRecordExtension`extension met automatiquement à jour les attributs de type balisés `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` avec un horodatage actuel chaque fois que l'élément est écrit avec succès dans la base de données. Cette extension n'est pas chargée par défaut.

#### Configuration
<a name="ddb-en-client-extensions-AGTE-conf"></a>

Pour spécifier l'attribut à mettre à jour avec l'horodatage actuel, balisez-le dans le `Instant` schéma de la table.

L'`lastUpdate`attribut est la cible du comportement de l'extension dans l'extrait suivant. Notez l'exigence selon laquelle l'attribut doit être un `Instant` type.

```
    @DynamoDbAutoGeneratedTimestampAttribute
    public Instant getLastUpdate() {...}
    public void setLastUpdate(Instant lastUpdate) {...}
```

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

```
     .addAttribute(Instant.class, a -> a.name("lastUpdate")
                                        .getter(Customer::getLastUpdate)
                                        .setter(Customer::setLastUpdate)
                                        // Applying the 'autoGeneratedTimestamp' tag to the attribute.
                                        .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())
```

### Générez un UUID avec le AutoGeneratedUuidExtension
<a name="ddb-en-client-extensions-AGUE"></a>

L'`AutoGeneratedUuidExtension`extension génère un UUID (identifiant unique universel) unique pour un attribut lorsqu'un nouvel enregistrement est écrit dans la base de données. Utilise la méthode Java JDK [UUID.randomUUID ()](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--) et s'applique aux attributs de type. `java.lang.String` Cette extension n'est pas chargée par défaut.

#### Configuration
<a name="ddb-en-client-extensions-AGUE-conf"></a>

L'`uniqueId`attribut est la cible du comportement de l'extension dans l'extrait suivant.

```
    @AutoGeneratedUuidExtension
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

L'approche équivalente du schéma de table statique est illustrée dans l'extrait suivant.

```
     .addAttribute(String.class, a -> a.name("uniqueId")
                                        .getter(Customer::getUniqueId)
                                        .setter(Customer::setUniqueId)
                                        // Applying the 'autoGeneratedUuid' tag to the attribute.
                                        .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())
```

Si vous souhaitez que l'extension renseigne l'UUID uniquement pour les `putItem` méthodes et non pour les `updateItem` méthodes, ajoutez l'annotation du [comportement de mise à jour](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) comme indiqué dans l'extrait suivant.

```
    @AutoGeneratedUuidExtension
    @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)
    public String getUniqueId() {...}
    public void setUniqueId(String uniqueId) {...}
```

Si vous utilisez l'approche du schéma de table statique, utilisez le code équivalent suivant.

```
     .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))
```

# Exemple d'extension personnalisée
<a name="ddb-en-client-extensions-custom"></a>

Vous pouvez créer des extensions personnalisées en implémentant l'`DynamoDbEnhancedClientExtension`interface. La classe d'extension personnalisée suivante montre une `beforeWrite()` méthode qui utilise une expression de mise à jour pour définir un `registrationDate` attribut si l'élément de la base de données n'en possède pas déjà un.

```
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();
    }
}
```

# Utiliser l'API client améliorée DynamoDB de manière asynchrone
<a name="ddb-en-client-async"></a>

Si votre application nécessite des appels asynchrones non bloquants à DynamoDB, vous pouvez utiliser le. [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html) Elle est similaire à l'implémentation synchrone, mais avec les principales différences suivantes :

1. Lorsque vous créez le`DynamoDbEnhancedAsyncClient`, vous devez fournir la version asynchrone du client standard`DynamoDbAsyncClient`, comme indiqué dans l'extrait de code suivant.

   ```
    DynamoDbEnhancedAsyncClient enhancedClient = 
        DynamoDbEnhancedAsyncClient.builder()
                                   .dynamoDbClient(dynamoDbAsyncClient)
                                   .build();
   ```

1. Les méthodes qui renvoient un seul objet de données renvoient une partie `CompletableFuture` du résultat au lieu du seul résultat. Votre application peut ensuite effectuer d'autres travaux sans avoir à bloquer le résultat. L'extrait suivant montre la méthode asynchrone`getItem()`. 

   ```
   CompletableFuture<Customer> result = customerDynamoDbTable.getItem(customer);
   // Perform other work here.
   return result.join();   // Now block and wait for the result.
   ```

1. Les méthodes qui renvoient des listes de résultats paginées renvoient un [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)au lieu d'un [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)que le synchrone `DynamoDbEnhanceClient` renvoie pour les mêmes méthodes. Votre application peut ensuite abonner un gestionnaire à cet éditeur pour traiter les résultats de manière asynchrone sans avoir à les bloquer.

   ```
   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.
   ```

   Pour un exemple plus complet d'utilisation du`SdkPublisher API`, consultez [l'exemple présenté](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-scan-async) dans la section de ce guide consacrée à la `scan()` méthode asynchrone.

# Annotations de classes de données
<a name="ddb-en-client-anno-index"></a>

Le tableau suivant répertorie les annotations qui peuvent être utilisées sur les classes de données et fournit des liens vers des informations et des exemples contenus dans ce guide. Le tableau est trié par ordre alphabétique croissant par nom d'annotation.


**Annotations de classes de données utilisées dans ce guide**  

| Nom de l'annotation | L'annotation s'applique à 1 | Ce qu'il fait | Où cela est indiqué dans ce guide | 
| --- | --- | --- | --- | 
| DynamoDbAtomicCounter | attribut 2 | Incrémente un attribut numérique balisé chaque fois qu'un enregistrement est écrit dans la base de données. | [Présentation et discussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-ACE) | 
| DynamoDbAttribute | attribute | Définit ou renomme une propriété de bean mappée à un attribut de table DynamoDB. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbAutoGeneratedTimestampAttribute | attribute | Met à jour un attribut balisé avec un horodatage actuel chaque fois que l'élément est correctement écrit dans la base de données | [Présentation et discussion](ddb-en-client-extensions.md#ddb-en-client-extensions-AGTE). | 
| DynamoDbAutoGeneratedUuid | attribute | Générez un UUID (identifiant unique universel) unique pour un attribut lorsqu'un nouvel enregistrement est écrit dans la base de données. | [Présentation et discussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-AGUE) | 
| DynamoDbBean | class | Marque une classe de données comme mappable à un schéma de table. | Première utilisation dans la [classe Customer](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) dans la section Commencer. Plusieurs utilisations apparaissent dans le guide. | 
| DynamoDbConvertedBy | attribute | Associe une personnalisation AttributeConverter à l'attribut annoté. | [Discussion initiale et exemple.](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-single) | 
| DynamoDbFlatten | attribute | Aplatit tous les attributs d'une classe de données DynamoDB distincte et les ajoute en tant qu'attributs de premier niveau à l'enregistrement lu et écrit dans la base de données.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnore | attribute |  Il en résulte que l'attribut reste non mappé.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnoreNulls | attribute | Empêche l'enregistrement des attributs nuls des DynamoDb objets imbriqués. | [Discussion et exemples.](ddb-en-client-adv-features-ignore-null.md) | 
| DynamoDbImmutable | class |  Marque une classe de données immuable comme mappable à un schéma de table.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPartitionKey | attribute |  Marque un attribut comme clé de partition principale (clé de hachage) de la DynamoDb table.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPreserveEmptyObject | attribute |  Spécifie que si aucune donnée n'est présente pour l'objet mappé à l'attribut annoté, l'objet doit être initialisé avec tous les champs nuls.  | [Discussion et exemples.](ddb-en-client-adv-features-empty.md) | 
| DynamoDbSecondaryPartitionKey | attribute |  Marque un attribut comme clé de partition pour un index secondaire global.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSecondarySortKey | attribute |  Marque un attribut comme clé de tri facultative pour un index secondaire global ou local.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSortKey | attribute |  Marque un attribut comme clé de tri primaire facultative (clé de plage).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbUpdateBehavior | attribute |  Spécifie le comportement lorsque cet attribut est mis à jour dans le cadre d'une opération de « mise à jour » telle que UpdateItem.  | [Introduction et exemple.](ddb-en-client-adv-features-upd-behavior.md) | 
| DynamoDbVersionAttribute | attribute | Incrémente le numéro de version d'un article. | [Présentation et discussion.](ddb-en-client-extensions.md#ddb-en-client-extensions-VRE) | 

1 Vous pouvez appliquer des annotations au niveau de l'attribut au getter ou au setter, mais pas aux deux. Ce guide montre les annotations sur les getters.

2 Le terme `property` est normalement utilisé pour une valeur encapsulée dans une classe de JavaBean données. Toutefois, ce guide utilise ce terme à la `attribute` place, par souci de cohérence avec la terminologie utilisée par DynamoDB.

# Travaillez avec Amazon EC2
<a name="examples-ec2"></a>

Cette section fournit des exemples de programmation [Amazon EC2](https://docs.aws.amazon.com/ec2/)utilisant la version AWS SDK pour Java 2.x.

**Topics**
+ [Gérer les Amazon EC2 instances](examples-ec2-instances.md)
+ [Zones d'utilisation Régions AWS et de disponibilité](examples-ec2-regions-zones.md)
+ [Travaillez avec des groupes de sécurité dans Amazon EC2](examples-ec2-security-groups.md)
+ [Utiliser les métadonnées des instances Amazon EC2](examples-ec2-IMDS.md)

# Gérer les Amazon EC2 instances
<a name="examples-ec2-instances"></a>

## Création d'une instance
<a name="create-an-instance"></a>

Créez une nouvelle Amazon EC2 instance en appelant la [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))méthode [Ec2Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html), en lui fournissant un [RunInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesRequest.html)contenant l'[Amazon Machine Image (AMI)](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/AMIs.html) à utiliser et un type d'[instance](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/instance-types.html).

 **Importations** 

```
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;
```

 **Code** 

```
   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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateInstance.java) sur GitHub.

## Démarrer une instance
<a name="start-an-instance"></a>

Pour démarrer une Amazon EC2 instance, appelez la [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))méthode Ec2Client, en lui fournissant un [StartInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StartInstancesRequest.html)contenant l'ID de l'instance à démarrer.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) sur GitHub.

## Arrêter une instance
<a name="stop-an-instance"></a>

Pour arrêter une Amazon EC2 instance, appelez la [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))méthode Ec2Client, en lui fournissant un [StopInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StopInstancesRequest.html)contenant l'ID de l'instance à arrêter.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) sur GitHub.

## Redémarrer une instance
<a name="reboot-an-instance"></a>

Pour redémarrer une Amazon EC2 instance, appelez la [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))méthode Ec2Client, en lui fournissant un [RebootInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RebootInstancesRequest.html)contenant l'ID de l'instance à redémarrer.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
     }
  }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/RebootInstance.java) sur GitHub.

## Décrire des instances
<a name="describe-instances"></a>

Pour répertorier vos instances, créez une [DescribeInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesRequest.html)et appelez la méthode 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)). Il renverra un [DescribeInstancesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesResponse.html)objet que vous pourrez utiliser pour répertorier les Amazon EC2 instances de votre compte et de votre région.

Les instances sont regroupées par *réservation*. Chaque réservation correspond à l'appel de `startInstances` qui a lancé l'instance. Pour afficher vos instances, vous devez d'abord appeler la méthode `reservations` de la classe `DescribeInstancesResponse`, puis appeler `instances` sur chaque objet [Reservation](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Reservation.html) renvoyé.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Les résultats sont paginés ; vous pouvez obtenir plus de résultats en transmettant la valeur renvoyée par la méthode `nextToken` de l'objet de résultat à la méthode `nextToken` de l'objet de la demande d'origine, puis en utilisant l'objet nouvelle demande lors de votre prochain appel de `describeInstances`.

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeInstances.java) sur GitHub.

## Surveiller une instance
<a name="monitor-an-instance"></a>

Vous pouvez surveiller différents aspects de vos Amazon EC2 instances, tels que l'utilisation du processeur et du réseau, la mémoire disponible et l'espace disque restant. Pour en savoir plus sur la surveillance des instances, consultez la section [Surveillance Amazon EC2](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/monitoring_ec2.html) dans le guide de Amazon EC2 l'utilisateur pour les instances Linux.

Pour commencer à surveiller une instance, vous devez en créer un [MonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/MonitorInstancesRequest.html)avec l'ID de l'instance à surveiller et le transmettre à la méthode Ec2Client. [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))

 **Importations** 

```
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;
```

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) sur GitHub.

## Arrêter la surveillance d’une instance
<a name="stop-instance-monitoring"></a>

Pour arrêter de surveiller une instance, créez une [UnmonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/UnmonitorInstancesRequest.html)avec l'ID de l'instance pour arrêter la surveillance et transmettez-la à la méthode 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))

 **Importations** 

```
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;
```

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html)dans la référence de Amazon EC2 l'API
+  [DescribeInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html)dans la référence de Amazon EC2 l'API
+  [StartInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StartInstances.html)dans la référence de Amazon EC2 l'API
+  [StopInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StopInstances.html)dans la référence de Amazon EC2 l'API
+  [RebootInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RebootInstances.html)dans la référence de Amazon EC2 l'API
+  [MonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_MonitorInstances.html)dans la référence de Amazon EC2 l'API
+  [UnmonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_UnmonitorInstances.html)dans la référence de Amazon EC2 l'API

# Zones d'utilisation Régions AWS et de disponibilité
<a name="examples-ec2-regions-zones"></a>

## Décrire des régions
<a name="describe-regions"></a>

Pour répertorier les régions disponibles sur votre compte, appelez la méthode Ec2Client`describeRegions`. Elle renvoie un [DescribeRegionsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeRegionsResponse.html). Appelez la méthode `regions` de l'objet renvoyé pour obtenir une liste d'objets [Region](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Region.html) qui représentent chaque région.

 **Importations** 

```
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;
```

 **Code** 

```
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);
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) sur GitHub.

## Décrire les zones de disponibilité
<a name="describe-availability-zones"></a>

Pour répertorier chaque zone de disponibilité disponible pour votre compte, appelez la méthode Ec2Client`describeAvailabilityZones`. Elle renvoie un [DescribeAvailabilityZonesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAvailabilityZonesResponse.html). Appelez sa `availabilityZones` méthode pour obtenir une liste d'[AvailabilityZone](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AvailabilityZone.html)objets représentant chaque zone de disponibilité.

 **Importations** 

```
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;
```

 **Code** 

Créez le client Ec2.

```
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();
```

Appelez ensuite describeAvailabilityZones () et récupérez les résultats.

```
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);
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) sur GitHub.

## Décrire les comptes
<a name="describe-accounts"></a>

Pour répertorier EC2 les informations relatives à votre compte, appelez la méthode Ec2Client`describeAccountAttributes`. Cette méthode renvoie un [DescribeAccountAttributesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAccountAttributesResponse.html)objet. Invoquez cette `accountAttributes` méthode d'objets pour obtenir une liste d'[AccountAttribute](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttribute.html)objets. Vous pouvez parcourir la liste pour récupérer un `AccountAttribute` objet.

Vous pouvez obtenir les valeurs d'attribut de votre compte en invoquant la `attributeValues` méthode de `AccountAttribute` l'objet. Cette méthode renvoie une liste d'[AccountAttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttributeValue.html)objets. Vous pouvez parcourir cette deuxième liste pour afficher la valeur des attributs (voir l'exemple de code ci-dessous).

 **Importations** 

```
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;
```

 **Code** 

```
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()));
                });
            }
        });
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeAccount.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Régions et zones de disponibilité](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/using-regions-availability-zones.html) dans le guide de Amazon EC2 l'utilisateur pour les instances Linux
+  [DescribeRegions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html)dans la référence de Amazon EC2 l'API
+  [DescribeAvailabilityZones](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html)dans la référence de Amazon EC2 l'API

# Travaillez avec des groupes de sécurité dans Amazon EC2
<a name="examples-ec2-security-groups"></a>

## Création d’un groupe de sécurité
<a name="create-a-security-group"></a>

Pour créer un groupe de sécurité, appelez la `createSecurityGroup` méthode Ec2Client avec un [CreateSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/CreateSecurityGroupRequest.html)qui contient le nom de la clé.

 **Importations** 

```
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;
```

 **Code** 

```
            CreateSecurityGroupRequest createRequest = CreateSecurityGroupRequest.builder()
                .groupName(groupName)
                .description(groupDesc)
                .vpcId(vpcId)
                .build();

            CreateSecurityGroupResponse resp= ec2.createSecurityGroup(createRequest);
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) sur GitHub.

## Configurer un groupe de sécurité
<a name="configure-a-security-group"></a>

Un groupe de sécurité peut contrôler à la fois le trafic entrant (entrée) et sortant (sortie) vers vos instances. Amazon EC2 

Pour ajouter des règles d'entrée à votre groupe de sécurité, utilisez la `authorizeSecurityGroupIngress` méthode Ec2Client, en fournissant le nom du groupe de sécurité et les règles d'accès ([IpPermission](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/IpPermission.html)) que vous souhaitez lui attribuer dans un objet. [AuthorizeSecurityGroupIngressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupIngressRequest.html) L'exemple suivant montre comment ajouter des autorisations IP à un groupe de sécurité.

 **Importations** 

```
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;
```

 **Code** 

Tout d'abord, créez un client Ec2

```
        Region region = Region.US_WEST_2;
        Ec2Client ec2 = Ec2Client.builder()
                .region(region)
                .build();
```

Ensuite, utilisez la méthode 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 "";
    }
```

Pour ajouter une règle de sortie au groupe de sécurité, fournissez des données similaires dans la [AuthorizeSecurityGroupEgressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupEgressRequest.html)méthode Ec2Client. `authorizeSecurityGroupEgress`

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) sur GitHub.

## Décrire des groupes de sécurité
<a name="describe-security-groups"></a>

Pour décrire vos groupes de sécurité ou obtenir des informations à leur sujet, appelez la méthode Ec2Client. `describeSecurityGroups` Elle renvoie un [DescribeSecurityGroupsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeSecurityGroupsResponse.html)que vous pouvez utiliser pour accéder à la liste des groupes de sécurité en appelant sa `securityGroups` méthode, qui renvoie une liste d'[SecurityGroup](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/SecurityGroup.html)objets.

 **Importations** 

```
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;
```

 **Code** 

```
     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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeSecurityGroups.java) sur GitHub.

## Supprimer un groupe de sécurité
<a name="delete-a-security-group"></a>

Pour supprimer un groupe de sécurité, appelez la `deleteSecurityGroup` méthode Ec2Client en lui transmettant un identifiant [DeleteSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DeleteSecurityGroupRequest.html)contenant l'ID du groupe de sécurité à supprimer.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
     }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DeleteSecurityGroup.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Amazon EC2 Groupes de sécurité](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html) dans le guide de Amazon EC2 l'utilisateur pour les instances Linux
+  [Autorisez le trafic entrant pour vos instances Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html) dans le guide de l' Amazon EC2 utilisateur pour les instances Linux
+  [CreateSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateSecurityGroup.html)dans la référence de Amazon EC2 l'API
+  [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)dans la référence de Amazon EC2 l'API
+  [DeleteSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteSecurityGroup.html)dans la référence de Amazon EC2 l'API
+  [AuthorizeSecurityGroupIngress](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AuthorizeSecurityGroupIngress.html)dans la référence de Amazon EC2 l'API

# Utiliser les métadonnées des instances Amazon EC2
<a name="examples-ec2-IMDS"></a>

Un client Java SDK pour le service de métadonnées d'instance Amazon EC2 (client de métadonnées) permet à vos applications d'accéder aux métadonnées sur leur instance EC2 locale. Le client de métadonnées fonctionne avec l'instance locale de [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)(Instance Metadata Service v2) et utilise des requêtes orientées session. 

Deux classes de clients sont disponibles dans le SDK. Le synchrone `[Ec2MetadataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataClient.html)` est destiné aux opérations de blocage, tandis que le synchrone [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)est destiné aux cas d'utilisation asynchrones et non bloquants. 

## Mise en route
<a name="examples-ec2-IMDS-getstarted"></a>

Pour utiliser le client de métadonnées, ajoutez l'artefact `imds` Maven à votre projet. Vous avez également besoin de classes pour un `[SdkHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/SdkHttpClient.html)` (ou un `[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)` pour la variante asynchrone) sur le chemin de classe. 

Le code XML Maven suivant montre les extraits de dépendance pour l'utilisation du synchrone [UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)ainsi que la dépendance pour les clients de métadonnées.

```
<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>
```

Recherchez la dernière version de l'`bom`artefact dans le [référentiel central Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

Pour utiliser un client HTTP asynchrone, remplacez l'extrait de dépendance de l'artefact. `url-connection-client` Par exemple, l'extrait suivant introduit l'[NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)implémentation.

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>netty-nio-client</artifactId>
    </dependency>
```

## Utiliser le client de métadonnées
<a name="examples-ec2-IMDS-use"></a>

### Instancier un client de métadonnées
<a name="examples-ec2-IMDS-use-create"></a>

Vous pouvez instancier une instance d'un système synchrone `Ec2MetadataClient` lorsqu'une seule implémentation de l'`SdkHttpClient`interface est présente sur le chemin de classe. Pour ce faire, appelez la `Ec2MetadataClient#create()` méthode statique comme indiqué dans l'extrait suivant. 

```
Ec2MetadataClient client = Ec2MetadataClient.create(); // 'Ec2MetadataAsyncClient#create' is the asynchronous version.
```

Si votre application possède plusieurs implémentations de l'`SdkHttpAsyncClient`interface `SdkHttpClient` or, vous devez spécifier une implémentation à utiliser par le client de métadonnées, comme indiqué dans la [Client HTTP configurable](#examples-ec2-IMDS-features-http) section. 

**Note**  
Pour la plupart des clients de services, tels qu'Amazon S3, le SDK pour Java ajoute automatiquement des implémentations de `SdkHttpClient` l'`SdkHttpAsyncClient`interface or. Si votre client de métadonnées utilise la même implémentation, `Ec2MetadataClient#create()` cela fonctionnera. Si vous avez besoin d'une implémentation différente, vous devez la spécifier lors de la création du client de métadonnées.

### Envoyer des demandes
<a name="examples-ec2-IMDS-use-req"></a>

Pour récupérer les métadonnées de l'instance, instanciez la `EC2MetadataClient` classe et appelez la `get` méthode avec un paramètre de chemin qui spécifie la catégorie de [métadonnées de l'instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html).

L'exemple suivant imprime la valeur associée à la `ami-id` clé sur la console.

```
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.
```

Si le chemin n'est pas valide, la `get` méthode génère une exception. 

Réutilisez la même instance client pour plusieurs demandes, mais faites appel `close` au client lorsqu'il n'est plus nécessaire de libérer des ressources. Une fois la méthode close appelée, l'instance client ne peut plus être utilisée.

### Analyser les réponses
<a name="examples-ec2-IMDS-use-pares"></a>

Les métadonnées de l'instance EC2 peuvent être produites dans différents formats. Le texte brut et le JSON sont les formats les plus couramment utilisés. Les clients de métadonnées offrent des moyens de travailler avec ces formats. 

Comme le montre l'exemple suivant, utilisez la `asString` méthode pour obtenir les données sous forme de chaîne Java. Vous pouvez également utiliser `asList` cette méthode pour séparer une réponse en texte brut qui renvoie plusieurs lignes. 

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/");
String fullResponse = response.asString();
List<String> splits = response.asList();
```

Si la réponse est au format JSON, utilisez la `Ec2MetadataResponse#asDocument` méthode pour analyser la réponse JSON dans une instance de [document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/Document.html), comme indiqué dans l'extrait de code suivant.

```
Document fullResponse = response.asDocument();
```

Une exception sera émise si le format des métadonnées n'est pas au format JSON. Si la réponse est correctement analysée, vous pouvez utiliser l'[API du document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/package-summary.html) pour l'inspecter plus en détail. Consultez le [tableau des catégories de métadonnées](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html) de l'instance pour savoir quelles catégories de métadonnées fournissent des réponses au format JSON.

## Configuration d'un client de métadonnées
<a name="examples-ec2-IMDS-config"></a>

### Nouvelles tentatives
<a name="examples-ec2-IMDS-config-retries"></a>

Vous pouvez configurer un client de métadonnées avec un mécanisme de nouvelle tentative. Dans ce cas, le client peut automatiquement réessayer les demandes qui échouent pour des raisons inattendues. Par défaut, le client réessaie trois fois une demande qui a échoué, avec un temps d'attente exponentiel entre les tentatives.

Si votre cas d'utilisation nécessite un mécanisme de nouvelle tentative différent, vous pouvez personnaliser le client à l'aide de la `retryPolicy` méthode de son générateur. Par exemple, l'exemple suivant montre un client synchrone configuré avec un délai fixe de deux secondes entre les tentatives et de cinq nouvelles tentatives.

```
BackoffStrategy fixedBackoffStrategy = FixedDelayBackoffStrategy.create(Duration.ofSeconds(2));
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .retryPolicy(retryPolicyBuilder -> retryPolicyBuilder.numRetries(5)
                                                                           .backoffStrategy(fixedBackoffStrategy))
                     .build();
```

Il en existe plusieurs [BackoffStrategies](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/package-summary.html)que vous pouvez utiliser avec un client de métadonnées.

Vous pouvez également désactiver complètement le mécanisme de nouvelle tentative, comme le montre l'extrait suivant.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                    .retryPolicy(Ec2MetadataRetryPolicy.none())
                    .build();
```

L'utilisation `Ec2MetadataRetryPolicy#none()` désactive la politique de nouvelle tentative par défaut afin que le client de métadonnées ne tente aucune nouvelle tentative.

### Versions d’adresses IP
<a name="examples-ec2-IMDS-config-ipversion"></a>

Par défaut, un client de métadonnées utilise le IPV4 point de terminaison situé à`http://169.254.169.254`. Pour modifier le client afin qu'il utilise la IPV6 version, utilisez la méthode `endpointMode` ou la `endpoint` méthode du générateur. Une exception se produit si les deux méthodes sont appelées sur le générateur.

Les exemples suivants montrent les deux IPV6 options.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpointMode(EndpointMode.IPV6)
                     .build();
```

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpoint(URI.create("http://[fd00:ec2::254]"))
                     .build();
```

## Fonctions principales
<a name="examples-ec2-IMDS-features"></a>

### Client asynchrone
<a name="examples-ec2-IMDS-features-async"></a>

Pour utiliser la version non bloquante du client, instanciez une instance de la classe. `Ec2MetadataAsyncClient` Le code de l'exemple suivant crée un client asynchrone avec les paramètres par défaut et utilise la `get` méthode pour récupérer la valeur de la clé. `ami-id`

```
Ec2MetadataAsyncClient asyncClient = Ec2MetadataAsyncClient.create();
CompletableFuture<Ec2MetadataResponse> response = asyncClient.get("/latest/meta-data/ami-id");
```

Le `java.util.concurrent.CompletableFuture` résultat renvoyé par la `get` méthode se termine lorsque la réponse est renvoyée. L'exemple suivant imprime les `ami-id` métadonnées sur la console.

```
response.thenAccept(metadata -> System.out.println(metadata.asString()));
```

### Client HTTP configurable
<a name="examples-ec2-IMDS-features-http"></a>

Le générateur de chaque client de métadonnées dispose d'une `httpClient` méthode que vous pouvez utiliser pour fournir un client HTTP personnalisé. 

L'exemple suivant montre le code d'une `UrlConnectionHttpClient` instance personnalisée.

```
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.
```

L'exemple suivant montre le code d'une `NettyNioAsyncHttpClient` instance personnalisée avec un client de métadonnées asynchrone.

```
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.
```

La [Configurez les clients HTTP dans AWS SDK for Java 2.x](http-configuration.md) rubrique de ce guide explique en détail comment configurer les clients HTTP disponibles dans le SDK for Java.

### Mise en cache des jetons
<a name="examples-ec2-IMDS-features-token"></a>

Étant donné que les clients utilisent les métadonnées IMDSv2, toutes les demandes sont associées à une session. Une session est définie par un jeton expiré, que le client de métadonnées gère pour vous. Chaque demande de métadonnées réutilise automatiquement le jeton jusqu'à son expiration. 

Par défaut, un jeton dure six heures (21 600 secondes). Nous vous recommandons de conserver la time-to-live valeur par défaut, sauf si votre cas d'utilisation spécifique nécessite une configuration avancée. 

Si nécessaire, configurez la durée à l'aide de la méthode du `tokenTtl` générateur. Par exemple, le code de l'extrait suivant crée un client dont la durée de session est de cinq minutes. 

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .tokenTtl(Duration.ofMinutes(5))
                     .build();
```

Si vous omettez d'appeler la `tokenTtl` méthode sur le générateur, la durée par défaut de 21 600 est utilisée à la place. 

# Travaillez avec IAM
<a name="examples-iam"></a>

Cette section fournit des exemples de programmation Gestion des identités et des accès AWS (IAM) à l'aide de la version AWS SDK pour Java 2.x.

 Gestion des identités et des accès AWS (IAM) vous permet de contrôler en toute sécurité l'accès aux AWS services et aux ressources pour vos utilisateurs. À l'aide de IAM, vous pouvez créer et gérer des AWS utilisateurs et des groupes, et utiliser des autorisations pour autoriser ou refuser leur accès aux AWS ressources. Pour un guide complet IAM, consultez le [guide de l'IAM utilisateur](https://docs.aws.amazon.com//IAM/latest/UserGuide/introduction.html).

Les exemples suivants incluent uniquement le code nécessaire pour démontrer chaque technique. L'[exemple de code complet est disponible sur GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). À partir de là, vous pouvez télécharger un fichier source unique ou cloner le référentiel en local pour obtenir tous les exemples à générer et exécuter.

**Topics**
+ [Gérer les clés IAM d'accès](examples-iam-access-keys.md)
+ [Gérer les IAM utilisateurs](examples-iam-users.md)
+ [Création de politiques IAM](feature-iam-policy-builder.md)
+ [Travailler avec des IAM politiques](examples-iam-policies.md)
+ [Travailler avec des certificats IAM de serveur](examples-iam-server-certificates.md)

# Gérer les clés IAM d'accès
<a name="examples-iam-access-keys"></a>

## Créer une clé d'accès
<a name="create-an-access-key"></a>

Pour créer une clé d' IAM accès, appelez la `IamClient’s` `createAccessKey` méthode avec un [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)objet.

**Note**  
Vous devez définir la région sur **AWS\$1GLOBAL**pour que les `IamClient` appels fonctionnent, car il IAM s'agit d'un service mondial.

 **Importations** 

```
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;
```

 **Code** 

```
    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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/CreateAccessKey.java) sur GitHub.

## Répertorier des clés d'accès
<a name="list-access-keys"></a>

Pour répertorier les clés d'accès d'un utilisateur donné, créez un [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)objet contenant le nom d'utilisateur pour lequel vous souhaitez répertorier les clés et transmettez-le à la `IamClient’s` `listAccessKeys` méthode.

**Note**  
Si vous ne fournissez pas de nom d'utilisateur à`listAccessKeys`, il tentera de répertorier les clés d'accès associées au Compte AWS signataire de la demande.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Les résultats de `listAccessKeys` sont paginés par défaut (avec un maximum de 100 enregistrements par appel). Vous pouvez faire appel `isTruncated` à l'[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)objet renvoyé pour voir si la requête a renvoyé moins de résultats que ceux disponibles. Si tel est le cas, appelez `marker` sur l'objet `ListAccessKeysResponse` et utilise-la lors de la création d'une nouvelle demande. Utilisez cette nouvelle demande dans le prochain appel de `listAccessKeys`.

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/ListAccessKeys.java) sur GitHub.

## Extraire l'heure de la dernière utilisation d'une clé d'accès
<a name="retrieve-an-access-key-s-last-used-time"></a>

Pour connaître l'heure à laquelle une clé d'accès a été utilisée pour la dernière fois, appelez la `IamClient’s` `getAccessKeyLastUsed` méthode avec l'ID de la clé d'accès (qui peut être transmis à l'aide d'un [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)objet).

Vous pouvez ensuite utiliser l'[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)objet renvoyé pour récupérer la date de dernière utilisation de la clé.

 **Importations** 

```
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;
```

 **Code** 

```
    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");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/AccessKeyLastUsed.java) sur GitHub.

## Activer ou désactiver des clés d'accès
<a name="iam-access-keys-update"></a>

Vous pouvez activer ou désactiver une clé d'accès en créant un [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)objet, en fournissant l'identifiant de la clé d'accès, éventuellement le nom d'utilisateur et le nom souhaité [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), puis en transmettant l'objet de demande à la `IamClient’s` `updateAccessKey` méthode.

 **Importations** 

```
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;
```

 **Code** 

```
       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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/UpdateAccessKey.java) sur GitHub.

## Supprimer une clé d'accès
<a name="delete-an-access-key"></a>

Pour supprimer définitivement une clé d'accès, appelez la `IamClient’s` `deleteKey` méthode en lui fournissant un [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)contenant l'identifiant et le nom d'utilisateur de la clé d'accès.

**Note**  
Une fois supprimée, une clé ne peut plus être récupérée ou utilisée. Pour désactiver temporairement une clé afin qu'elle puisse être réactivée ultérieurement, utilisez plutôt la [`updateAccessKey`](#iam-access-keys-update)méthode.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/DeleteAccessKey.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [CreateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html)dans la référence de IAM l'API
+  [ListAccessKeys](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html)dans la référence de IAM l'API
+  [GetAccessKeyLastUsed](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccessKeyLastUsed.html)dans la référence de IAM l'API
+  [UpdateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html)dans la référence de IAM l'API
+  [DeleteAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html)dans la référence de IAM l'API

# Gérer les IAM utilisateurs
<a name="examples-iam-users"></a>

## créer un utilisateur ;
<a name="creating-a-user"></a>

Créez un nouvel IAM utilisateur en fournissant le nom d'utilisateur à la `createUser` méthode IamClient's à l'aide d'un [CreateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreateUserRequest.html)objet contenant le nom d'utilisateur.

 **Importations** 

```
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;
```

 **Code** 

```
    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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/CreateUser.java) sur GitHub.

## Répertorier des utilisateurs
<a name="listing-users"></a>

Pour répertorier les IAM utilisateurs de votre compte, créez-en un nouveau [ListUsersRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersRequest.html)et passez-le à IamClient la `listUsers` méthode. Vous pouvez récupérer la liste des utilisateurs en appelant `users` l'[ListUsersResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersResponse.html)objet renvoyé.

La liste d'utilisateurs renvoyée par `listUsers` est paginée. Vous pouvez vérifier s'il existe plus de résultats à récupérer en appelant la méthode `isTruncated` de l'objet de réponse. Si celle-ci renvoie `true`, appelez la méthode `marker()` de l'objet de réponse. Utilisez la valeur du marqueur de valeur pour créer un nouvel objet demande. Puis, appelez à nouveau la méthode `listUsers` avec la nouvelle demande.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/ListUsers.java) sur GitHub.

## Mettre à jour un utilisateur
<a name="updating-a-user"></a>

Pour mettre à jour un utilisateur, appelez la `updateUser` méthode de l' IamClient objet, qui prend un [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)objet que vous pouvez utiliser pour modifier le *nom* ou le *chemin* de l'utilisateur.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
      }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/UpdateUser.java) sur GitHub.

## Suppression d'un utilisateur
<a name="deleting-a-user"></a>

Pour supprimer un utilisateur, appelez IamClient la `deleteUser` demande avec un [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)objet défini avec le nom d'utilisateur à supprimer.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DeleteUser.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [IAM Utilisateurs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) dans le guide de IAM l'utilisateur
+  [Gestion des IAM utilisateurs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_manage.html) dans le guide de IAM l'utilisateur
+  [CreateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html)dans la référence de IAM l'API
+  [ListUsers](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html)dans la référence de IAM l'API
+  [UpdateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html)dans la référence de IAM l'API
+  [DeleteUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUser.html)dans la référence de IAM l'API

# Créez des politiques IAM avec le AWS SDK for Java 2.x
<a name="feature-iam-policy-builder"></a>

L'[API IAM Policy Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/package-summary.html) est une bibliothèque que vous pouvez utiliser pour créer des [politiques IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) en Java et les télécharger vers Gestion des identités et des accès AWS (IAM). 

Au lieu de créer une politique IAM en assemblant manuellement une chaîne JSON ou en lisant un fichier, l'API fournit une approche orientée objet côté client pour générer la chaîne JSON. Lorsque vous lisez une politique IAM existante au format JSON, l'API la convertit en [IamPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.html)instance à gérer.

L'API IAM Policy Builder est devenue disponible avec la version 2.20.105 du SDK. Utilisez donc cette version ou une version ultérieure dans votre fichier de build Maven. Le numéro de version le plus récent du SDK est [répertorié sur Maven Central](https://central.sonatype.com/artifact/software.amazon.awssdk/iam-policy-builder).

L'extrait suivant montre un exemple de bloc de dépendance pour un fichier `pom.xml` Maven. Cela vous permet d'utiliser l'API IAM Policy Builder dans votre projet. 

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>iam-policy-builder</artifactId>
    <version>2.27.21</version>
</dependency>
```

## Créer un `IamPolicy`
<a name="iam-policy-builder-create"></a>

Cette section présente plusieurs exemples de création de politiques à l'aide de l'API IAM Policy Builder.

Dans chacun des exemples suivants, commencez par les instructions `[IamPolicy.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.Builder.html)` et ajoutez une ou plusieurs instructions à l'aide de la `addStatement` méthode. Suivant ce modèle, le [IamStatement.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamStatement.Builder.html) dispose de méthodes pour ajouter l'effet, les actions, les ressources et les conditions à l'instruction.

### Exemple : créer une politique basée sur le temps
<a name="iam-policy-builder-create-ex-time-based"></a>

L'exemple suivant crée une politique basée sur l'identité qui autorise l'action Amazon `GetItem` DynamoDB entre deux points dans le temps.

```
    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());
    }
```

#### Sortie JSON
<a name="iam-builder-ex-json-date"></a>

La dernière instruction de l'exemple précédent renvoie la chaîne JSON suivante. 

Pour en savoir plus sur cet [exemple,](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws-dates.html) consultez le *guide de Gestion des identités et des accès AWS l'utilisateur*.

------
#### [ 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"
            }
        }
    }
}
```

------

### Exemple : Spécifier plusieurs conditions
<a name="iam-policy-builder-create-ex-multi-conditions"></a>

L'exemple suivant montre comment créer une politique basée sur l'identité qui autorise l'accès à des attributs DynamoDB spécifiques. La politique contient deux conditions.

```
    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());
    }
```

#### Sortie JSON
<a name="iam-builder-ex-json-multi-cond"></a>

La dernière instruction de l'exemple précédent renvoie la chaîne JSON suivante. 

Pour en savoir plus sur cet [exemple,](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_dynamodb_attributes.html) consultez le *guide de Gestion des identités et des accès AWS l'utilisateur*.

------
#### [ 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"
            }
        }
    }
}
```

------

### Exemple : Spécifier les principaux
<a name="iam-policy-builder-create-ex-principals"></a>

L'exemple suivant montre comment créer une politique basée sur les ressources qui refuse l'accès à un bucket à tous les principaux, à l'exception de ceux spécifiés dans la condition.

```
    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());
    }
```

#### Sortie JSON
<a name="iam-policy-builder-create-json-ex-principals"></a>

La dernière instruction de l'exemple précédent renvoie la chaîne JSON suivante. 

Pour en savoir plus sur cet [exemple,](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-anonymous) consultez le *guide de Gestion des identités et des accès AWS l'utilisateur*.

------
#### [ 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"
      }
    }
  }
}
```

------

### Exemple : autoriser l'accès entre comptes
<a name="iam-policy-builder-create-ex-cross-account"></a>

L'exemple suivant montre comment autoriser une autre personne Compte AWS à télécharger des objets dans votre compartiment tout en conservant le contrôle total du propriétaire sur les objets chargés. 

```
    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());
    }
```

#### Sortie JSON
<a name="iam-policy-builder-create-ex-json-cross-account"></a>

La dernière instruction de l'exemple précédent renvoie la chaîne JSON suivante. 

Pour en savoir plus sur cet [exemple,](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-acl-2) consultez le *guide de l'utilisateur d'Amazon Simple Storage Service*.

------
#### [ 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"
      }
    }
  }
}
```

------

## Utiliser et `IamPolicy` avec IAM
<a name="iam-policy-builder-work-with-service"></a>

Après avoir créé une `IamPolicy` instance, vous utilisez an [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)pour travailler avec le service IAM. 

L'exemple suivant crée une politique qui permet à une [identité IAM d'](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html)écrire des éléments dans une table DynamoDB du compte spécifié avec le paramètre. `accountID` La politique est ensuite téléchargée dans IAM sous forme de chaîne 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());
    }
```

L'exemple suivant s'appuie sur l'exemple précédent. Le code télécharge la politique et l'utilise comme base pour une nouvelle politique en copiant et en modifiant la déclaration. La nouvelle politique est ensuite téléchargée.

```
    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>

Les exemples précédents utilisent un `IamClient` argument créé comme indiqué dans l'extrait suivant.

```
IamClient iam = IamClient.builder().region(Region.AWS_GLOBAL).build();
```

### Politiques en JSON
<a name="iam-policy-builder-work-with-serivce-json"></a>

Les exemples renvoient les chaînes JSON suivantes.

```
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"
  }
}
```

# Travailler avec des IAM politiques
<a name="examples-iam-policies"></a>

## Créer une politique
<a name="create-a-policy"></a>

Pour créer une nouvelle politique, indiquez le nom de la stratégie et un document de politique au format JSON dans la méthode a [CreatePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreatePolicyRequest.html)to the IamClient. `createPolicy`

 **Importations** 

```
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;
```

 **Code** 

```
    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 "" ;
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/e41bacfd5e671e7ef1a9f73e972540dc6a434664/javav2/example_code/iam/src/main/java/com/example/iam/CreatePolicy.java) sur GitHub.

## Obtenir une politique
<a name="get-a-policy"></a>

Pour récupérer une politique existante, appelez la `getPolicy` méthode IamClient's, en fournissant l'ARN de la politique dans un [GetPolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetPolicyRequest.html)objet.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/GetPolicy.java) sur GitHub.

## Attacher une stratégie de rôle
<a name="attach-a-role-policy"></a>

Vous pouvez associer une politique à un IAM [rôle](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) en appelant la `attachRolePolicy` méthode IamClient's, en lui fournissant le nom du rôle et l'ARN de la politique dans un [AttachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/AttachRolePolicyRequest.html).

 **Importations** 

```
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;
```

 **Code** 

```
    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");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) sur GitHub.

## Répertorier les stratégies de rôle attachées
<a name="list-attached-role-policies"></a>

Répertoriez les politiques associées à un rôle en appelant la `listAttachedRolePolicies` méthode IamClient's. Il faut un [ListAttachedRolePoliciesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesRequest.html)objet contenant le nom du rôle pour répertorier les politiques.

Appelez `getAttachedPolicies` l'[ListAttachedRolePoliciesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesResponse.html)objet renvoyé pour obtenir la liste des politiques jointes. Les résultats peuvent être tronqués. Si la méthode `ListAttachedRolePoliciesResponse` de l'objet `isTruncated` renvoie `true`, appelez la méthode `ListAttachedRolePoliciesResponse` de l'objet `marker`. Utilisez le marqueur retourné pour créer une nouvelle demande et utilisez-la pour appeler à nouveau `listAttachedRolePolicies` afin d'obtenir le lot suivant de résultats.

 **Importations** 

```
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;
```

 **Code** 

```
    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");
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) sur GitHub.

## Détacher une stratégie de rôle
<a name="detach-a-role-policy"></a>

Pour détacher une politique d'un rôle, appelez la `detachRolePolicy` méthode IamClient's en lui fournissant le nom du rôle et l'ARN de la politique dans un [DetachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DetachRolePolicyRequest.html).

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DetachRolePolicy.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Présentation des IAM politiques](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) dans le guide de IAM l'utilisateur.
+ [AWS Référence à la politique IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) dans le guide de l' IAM utilisateur.
+  [CreatePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html)dans la référence de IAM l'API
+  [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html)dans la référence de IAM l'API
+  [AttachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachRolePolicy.html)dans la référence de IAM l'API
+  [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)dans la référence de IAM l'API
+  [DetachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html)dans la référence de IAM l'API

# Travailler avec des certificats IAM de serveur
<a name="examples-iam-server-certificates"></a>

Pour activer les connexions HTTPS à votre site Web ou à votre application AWS, vous avez besoin d'un *certificat de SSL/TLS serveur*. Vous pouvez utiliser un certificat de serveur fourni par un fournisseur externe AWS Certificate Manager ou un certificat que vous avez obtenu auprès d'un fournisseur externe.

Nous vous recommandons de les utiliser ACM pour provisionner, gérer et déployer vos certificats de serveur. ACM Vous pouvez ainsi demander un certificat, le déployer sur vos AWS ressources et nous laisser ACM gérer le renouvellement des certificats pour vous. Les certificats fournis par ACM sont gratuits. Pour plus d'informations ACM, consultez le [guide de AWS Certificate Manager l'utilisateur](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html).

## Obtenir un certificat de serveur
<a name="get-a-server-certificate"></a>

Vous pouvez récupérer un certificat de serveur en appelant la `getServerCertificate` méthode IamClient's et en [GetServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetServerCertificateRequest.html)lui transmettant le nom du certificat.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/GetServerCertificate.java) sur GitHub.

## Lister les certificats de serveur
<a name="list-server-certificates"></a>

Pour répertorier les certificats de votre serveur, appelez la `listServerCertificates` méthode IamClient's avec un [ListServerCertificatesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesRequest.html). Elle renvoie un [ListServerCertificatesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesResponse.html).

Appelez la `serverCertificateMetadataList` méthode de `ListServerCertificateResponse` l'objet renvoyé pour obtenir une liste d'[ServerCertificateMetadata](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ServerCertificateMetadata.html)objets que vous pouvez utiliser pour obtenir des informations sur chaque certificat.

Les résultats peuvent être tronqués. Si la méthode `ListServerCertificateResponse` de l'objet `isTruncated` renvoie `true`, appelez la méthode `ListServerCertificatesResponse` de l'objet `marker` et utilisez le marqueur pour créer une nouvelle demande. Utilisez la nouvelle demande pour appeler à nouveau `listServerCertificates` et obtenir le lot suivant de résultats.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/ListServerCertificates.java) sur GitHub.

## Mettre à jour un certificat de serveur
<a name="update-a-server-certificate"></a>

Vous pouvez mettre à jour le nom ou le chemin d'un certificat de serveur en appelant la `updateServerCertificate` méthode IamClient's. Il faut utiliser un ensemble d'[UpdateServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateServerCertificateRequest.html)objets portant le nom actuel du certificat de serveur et un nouveau nom ou un nouveau chemin.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
     }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/UpdateServerCertificate.java) sur GitHub.

## Supprimer un certificat de serveur
<a name="delete-a-server-certificate"></a>

Pour supprimer un certificat de serveur, appelez la `deleteServerCertificate` méthode IamClient's avec un [DeleteServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DeleteServerCertificateRequest.html)contenant le nom du certificat.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/DeleteServerCertificate.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [Utilisation des certificats de serveur](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_server-certs.html) dans le guide de IAM l'utilisateur
+  [GetServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServerCertificate.html)dans la référence de IAM l'API
+  [ListServerCertificates](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListServerCertificates.html)dans la référence de IAM l'API
+  [UpdateServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateServerCertificate.html)dans la référence de IAM l'API
+  [DeleteServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteServerCertificate.html)dans la référence de IAM l'API
+  [AWS Certificate Manager Guide de l'utilisateur](https://docs.aws.amazon.com/acm/latest/userguide/) 

# Travaillez avec Kinesis
<a name="examples-kinesis"></a>

Cette section fournit des exemples de programmation à l'[Amazon Kinesis](https://docs.aws.amazon.com/kinesis/)aide de la version AWS SDK pour Java 2.x.

Pour plus d'informations Kinesis, consultez le [guide du Amazon Kinesis développeur](https://docs.aws.amazon.com/streams/latest/dev/introduction.html).

Les exemples suivants incluent uniquement le code nécessaire pour démontrer chaque technique. L'[exemple de code complet est disponible sur GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). À partir de là, vous pouvez télécharger un fichier source unique ou cloner le référentiel en local pour obtenir tous les exemples à générer et exécuter.

**Topics**
+ [Abonnez-vous à Amazon Kinesis Data Streams](examples-kinesis-stream.md)

# Abonnez-vous à Amazon Kinesis Data Streams
<a name="examples-kinesis-stream"></a>

Les exemples suivants vous montrent comment récupérer et traiter des données à partir de flux de Amazon Kinesis données à l'aide de `subscribeToShard` cette méthode. Kinesis Data Streams utilise désormais la fonction fanout améliorée et une API de récupération de données HTTP/2 à faible latence, ce qui permet aux développeurs d'exécuter plus facilement plusieurs applications à faible latence et hautes performances sur le même flux de données. Kinesis 

## Configuration
<a name="set-up"></a>

Créez d'abord un Kinesis client asynchrone et un [SubscribeToShardRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardRequest.html)objet. Ces objets sont utilisés dans chacun des exemples suivants pour s'abonner à Kinesis des événements.

 **Importations** 

```
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;
```

 **Code** 

```
        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();
```

## Utiliser l'interface du générateur
<a name="use-the-builder-interface"></a>

Vous pouvez utiliser `builder` cette méthode pour simplifier la création du [SubscribeToShardResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.html).

À l'aide du générateur, vous pouvez définir chaque rappel de cycle de vie avec un appel de méthode au lieu d'implémenter l'intégralité de l'interface.

 **Code** 

```
    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);
    }
```

Pour plus de contrôle sur l'éditeur, vous pouvez utiliser la méthode `publisherTransformer` pour personnaliser l'éditeur.

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) sur GitHub.

## Utiliser un gestionnaire de réponses personnalisé
<a name="use-a-custom-response-handler"></a>

Pour un contrôle total de l'abonné et de l'éditeur, implémentez l'`SubscribeToShardResponseHandler`interface.

Dans cet exemple, vous implémentez la méthode `onEventStream` qui autorise un accès complet à l'éditeur. Cet exemple montre comment transformer l'éditeur en enregistrements d'événement pour impression par l'abonné.

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) sur GitHub.

## Utiliser l'interface visiteur
<a name="use-the-visitor-interface"></a>

Vous pouvez utiliser un objet [Visitor](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.Visitor.html) pour vous abonner à des événements spécifiques que vous souhaitez surveiller.

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) sur GitHub.

## Utiliser un abonné personnalisé
<a name="use-a-custom-subscriber"></a>

Vous pouvez également implémenter votre propre abonné personnalisé pour s'abonner au flux.

Cet extrait de code montre un exemple d'abonné.

 **Code** 

```
    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");
        }
    }
```

Vous pouvez transmettre l'abonné personnalisé à la `subscribe` méthode comme indiqué dans l'extrait de code suivant.

 **Code** 

```
    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);
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) sur GitHub.

## Écrire des enregistrements de données dans un flux Kinesis de données
<a name="write-data-records-into-a-kinesis-data-stream"></a>

Vous pouvez utiliser l'[KinesisClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/KinesisClient.html)objet pour écrire des enregistrements de données dans un flux de Kinesis données à l'aide de la `putRecords` méthode. Pour appeler correctement cette méthode, créez un [PutRecordsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/PutRecordsRequest.html)objet. Vous transmettez le nom du flux de données à la `streamName` méthode. Vous devez également transmettre les données en utilisant la méthode `putRecords` (comme indiqué dans l'exemple de code suivant).

 **Importations** 

```
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;
```

Dans l'exemple de code Java suivant, notez que **StockTrade**l'objet est utilisé comme donnée pour écrire dans le flux de Kinesis données. Avant d'exécuter cet exemple, assurez-vous d'avoir créé le flux de données.

 **Code** 

```
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);
        }
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/kinesis/src/main/java/com/example/kinesis/StockTradesWriter.java) sur GitHub.

## Utiliser une bibliothèque tierce
<a name="use-a-third-party-library"></a>

Vous pouvez utiliser d'autres bibliothèques tierces au lieu d'implémenter un abonné personnalisé. Cet exemple montre comment utiliser l' RxJava implémentation, mais vous pouvez utiliser n'importe quelle bibliothèque qui implémente les interfaces Reactive Streams. Consultez la [page RxJava wiki sur Github](https://github.com/ReactiveX/RxJava/wiki) pour plus d'informations sur cette bibliothèque.

Pour utiliser la bibliothèque, ajoutez-la en tant que dépendance. Si vous utilisez Maven, l'exemple illustre l'extrait POM à utiliser.

 **Entrée POM** 

```
<dependency>
 <groupId>io.reactivex.rxjava2</groupId>
 <artifactId>rxjava</artifactId>
 <version>2.2.21</version>
</dependency>
```

 **Importations** 

```
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;
```

Cet exemple est utilisé RxJava dans la méthode du `onEventStream` cycle de vie. Cet exemple vous donne un accès complet à l'éditeur, qui peut être utilisé pour créer un Rx Flowable.

 **Code** 

```
        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();
```

Vous pouvez également utiliser la méthode `publisherTransformer` avec l'éditeur `Flowable`. Vous devez adapter l'`Flowable`éditeur à un *SdkPublisher*, comme indiqué dans l'exemple suivant.

 **Code** 

```
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
            .builder()
            .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
            .publisherTransformer(p -> SdkPublisher.adapt(Flowable.fromPublisher(p).limit(100)))
            .build();
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamRxJavaEx.java) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [SubscribeToShardEvent](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShardEvent.html)dans la référence de Amazon Kinesis l'API
+  [SubscribeToShard](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShard.html)dans la référence de Amazon Kinesis l'API

# AWS Lambda Fonctions d'appel, de liste et de suppression
<a name="examples-lambda"></a>

Cette section fournit des exemples de programmation avec le client de Lambda service à l'aide de la version AWS SDK pour Java 2.x.

**Topics**
+ [Appel d'une fonction Lambda](#invoke-function)
+ [Liste des fonctions Lambda](#list-function)
+ [Suppression d'une fonction Lambda](#delete-function)

## Appel d'une fonction Lambda
<a name="invoke-function"></a>

Vous pouvez invoquer une Lambda fonction en créant un [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)objet et en invoquant sa `invoke` méthode. Créez un [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)objet pour spécifier des informations supplémentaires telles que le nom de la fonction et la charge utile à transmettre à la Lambda fonction. Les noms des fonctions apparaissent sous la forme *arn:aws:lambda:us-east- 1:123456789012:function* :. HelloFunction Vous pouvez récupérer la valeur en consultant la fonction dans le AWS Management Console.

Pour transmettre des données de charge utile à une fonction, créez un [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)objet contenant des informations. Par exemple, dans l'exemple de code suivant, notez les données JSON transmises à la fonction Lambda .

 **Importations** 

```
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;
```

 **Code** 

L'exemple de code suivant montre comment invoquer une Lambda fonction.

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/LambdaInvoke.java) sur GitHub.

## Liste des fonctions Lambda
<a name="list-function"></a>

Créez un `[Lambda Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html)` objet et invoquez sa `listFunctions` méthode. Cette méthode renvoie un [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)objet. Vous pouvez invoquer la `functions` méthode de cet objet pour renvoyer une liste d'[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)objets. Parcourez la liste pour récupérer des informations sur les fonctions. Par exemple, l'exemple de code Java ci-dessous illustre comment obtenir le nom de chaque fonction.

 **Importations** 

```
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;
```

 **Code** 

L'exemple de code Java suivant illustre comment récupérer une liste de noms de fonctions.

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/ListLambdaFunctions.java) sur GitHub.

## Suppression d'une fonction Lambda
<a name="delete-function"></a>

Créez un [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)objet et invoquez sa `deleteFunction` méthode. Créez un [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)objet et transmettez-le à la `deleteFunction` méthode. Cet objet contient des informations telles que le nom de la fonction à supprimer. Les noms des fonctions apparaissent sous la forme *arn:aws:lambda:us-east- 1:123456789012:function* :. HelloFunction Vous pouvez récupérer la valeur en consultant la fonction dans le AWS Management Console.

 **Importations** 

```
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;
```

 **Code** 

Le code Java suivant montre comment supprimer une Lambda fonction.

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/DeleteFunction.java) sur GitHub.

# Travaillez avec Amazon S3
<a name="examples-s3"></a>

Cette section fournit des informations générales sur l'utilisation d'Amazon S3 à l'aide du AWS SDK for Java 2.x. Cette section complète les [exemples Java v2 d'Amazon S3](java_s3_code_examples.md) présentés dans la section *Exemples de code* de ce guide.

## clients S3 dans le AWS SDK for Java 2.x
<a name="s3-clients"></a>

 AWS SDK for Java 2.x Il fournit différents types de clients S3. Le tableau suivant montre les différences et peut vous aider à déterminer ce qui convient le mieux à vos cas d'utilisation.


**Différents types de clients Amazon S3**  

| Client S3 | Description abrégée | Quand l’utiliser | Limitation/inconvénient | 
| --- | --- | --- | --- | 
|  **AWS Client S3 basé sur CRT** Interface : [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Constructeur : [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/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html) Consultez [Utiliser un client S3 performant : client S3 AWS basé sur CRT](crt-based-s3-client.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  | 
|  **Client asynchrone S3 basé sur Java *avec le multipart activé*** Interface : [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Constructeur : [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/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html) Consultez [Configurer le client asynchrone S3 basé sur Java pour utiliser les transferts parallèles](s3-async-client-multipart.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  | Moins performant que le client S3 AWS basé sur CRT. | 
|  **Client asynchrone S3 basé sur Java *sans* activation du multipart** Interface : [S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) Constructeur : [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/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Aucune optimisation des performances.  | 
|  **Client de synchronisation S3 basé sur Java** Interface : [S3 Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) Constructeur : [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/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Aucune optimisation des performances.  | 

**Note**  
À partir de la version 2.18.x, l'[adressage de type hébergé virtuel est AWS SDK for Java 2.x utilisé pour inclure un remplacement du point](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) de terminaison. Cela s'applique tant que le nom du bucket est une étiquette DNS valide.   
Appelez la [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)méthode `true` dans votre générateur de clients pour forcer le client à utiliser un adressage de type chemin pour les buckets.  
L'exemple suivant montre un client de service configuré avec un remplacement de point de terminaison et utilisant un adressage de type chemin.  

```
S3Client client = S3Client.builder()
                          .region(Region.US_WEST_2)
                          .endpointOverride(URI.create("https://s3.us-west-2.amazonaws.com"))
                          .forcePathStyle(true)
                          .build();
```

**Topics**
+ [Clients S3 dans le SDK](#s3-clients)
+ [Téléchargement de flux vers S3](best-practices-s3-uploads.md)
+ [Pré-signé URLs](examples-s3-presign.md)
+ [Accès interrégional](s3-cross-region.md)
+ [Protection de l'intégrité des données avec des checksums](s3-checksums.md)
+ [Utilisez un client S3 performant](crt-based-s3-client.md)
+ [Configuration de la prise en charge du transfert parallèle](s3-async-client-multipart.md)
+ [Transférer des fichiers et des répertoires](transfer-manager.md)
+ [Notifications d’événements S3](examples-s3-event-notifications.md)

# Chargement de flux vers Amazon S3 à l'aide du AWS SDK for Java 2.x
<a name="best-practices-s3-uploads"></a>

Lorsque vous utilisez un flux pour télécharger du contenu vers S3 à l'aide de [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))ou [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)), vous utilisez une classe d'`RequestBody`usine pour que l'API synchrone fournisse le flux. Pour l'API asynchrone, il s'`AsyncRequestBody`agit de la classe d'usine équivalente.

## Quelles méthodes permettent de télécharger des flux ?
<a name="s3-stream-upload-methods"></a>

Pour l'API synchrone, vous pouvez utiliser les méthodes d'usine suivantes `RequestBody` pour fournir le flux :
+ `[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`Il utilise la méthode `fromInputStream(InputStream inputStream)` d'usine
+ `[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)`

Pour l'API asynchrone, vous pouvez utiliser les méthodes d'usine suivantes : `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)`
  + Vous utilisez le AsyncRequestBodyFromInputStreamConfiguration .Builder pour fournir le flux
+ `[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)`
  + Le résultat `[BlockingInputStreamAsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.html)` contient la méthode `writeInputStream(InputStream inputStream)` que vous pouvez utiliser pour fournir le flux

## Exécution du téléchargement
<a name="s3-upload-stream-perform"></a>

### Si vous connaissez la durée du stream
<a name="s3-stream-upload-supply-content-length"></a>

Comme le montre la signature des méthodes présentées précédemment, la plupart des méthodes acceptent un paramètre de longueur de contenu. 

Si vous connaissez la longueur du contenu en octets, indiquez la valeur exacte :

```
// 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));
```

**Avertissement**  
 Lorsque vous chargez à partir d'un flux d'entrée, si la longueur du contenu que vous avez spécifiée ne correspond pas au nombre d'octets réel, vous pouvez rencontrer :  
Objets tronqués si la longueur spécifiée est trop petite
Échec des téléchargements ou blocage des connexions si la longueur spécifiée est trop grande

### Si vous ne connaissez pas la durée du stream
<a name="s3-stream-upload-unknown-length"></a>

#### Utilisation de l'API synchrone
<a name="s3-upload-unknown-sync-client"></a>

Utilisez le `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;
}
```

Comme le SDK met en mémoire tampon l'intégralité du flux pour calculer la longueur du contenu, vous pouvez rencontrer des problèmes de mémoire avec des flux volumineux. Si vous devez télécharger des flux volumineux avec le client synchrone, pensez à utiliser l'API en plusieurs parties :

##### Téléchargez un flux à l'aide de l'API client synchrone et de l'API en plusieurs parties
<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;
}
```

**Note**  
Dans la plupart des cas d'utilisation, nous recommandons d'utiliser l'API client asynchrone pour les flux de taille inconnue. Cette approche permet des transferts parallèles et offre une interface de programmation plus simple, car le SDK gère la segmentation du flux en plusieurs parties si le flux est volumineux.   
Le client asynchrone S3 standard avec le multipart activé et le client S3 AWS basé sur CRT implémentent cette approche. Nous présentons des exemples de cette approche dans la section suivante.

#### Utilisation de l'API asynchrone
<a name="s3-stream-upload-unknown-async-client"></a>

Vous pouvez fournir `null` l'`contentLength`argument au `fromInputStream(InputStream inputStream, Long contentLength, ExecutorService executor)`

**Example en utilisant le client asynchrone AWS basé sur 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 en utilisant le client asynchrone standard avec le multipart activé :**  

```
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;
}
```

# Travaillez avec des documents Amazon S3 pré-signés URLs
<a name="examples-s3-presign"></a>

Les documents pré-signés URLs fournissent un accès temporaire aux objets S3 privés sans que les utilisateurs aient besoin d' AWS informations d'identification ou d'autorisations. 

Par exemple, supposons qu'Alice ait accès à un objet S3 et qu'elle souhaite partager temporairement l'accès à cet objet avec Bob. Alice peut générer une requête GET pré-signée à partager avec Bob afin qu'il puisse télécharger l'objet sans avoir besoin d'accéder aux informations d'identification d'Alice. Vous pouvez générer des requêtes présignées URLs pour HTTP GET et HTTP PUT.

## Générez une URL pré-signée pour un objet, puis téléchargez-le (requête GET)
<a name="get-presignedobject"></a>

L'exemple suivant se compose de deux parties.
+ Partie 1 : Alice génère l'URL pré-signée d'un objet.
+ Partie 2 : Bob télécharge l'objet à l'aide de l'URL pré-signée.

### Partie 1 : Génération de l'URL
<a name="get-presigned-object-part1"></a>

Alice possède déjà un objet dans un compartiment S3. Elle utilise le code suivant pour générer une chaîne d'URL que Bob pourra utiliser dans une requête GET ultérieure.

#### Importations
<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();
        }
    }
```

### Partie 2 : Télécharger l'objet
<a name="get-presigned-object-part2"></a>

Bob utilise l'une des trois options de code suivantes pour télécharger l'objet. Il pourrait également utiliser un navigateur pour exécuter la requête GET.

#### Utiliser le JDK `HttpURLConnection` (depuis la 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();
    }
```

#### Utiliser le JDK `HttpClient` (depuis la 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();
    }
```

#### Utilisation `SdkHttpClient` depuis le SDK pour 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();
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedGetUrlAndRetrieve.java) et [testez](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedGetUrlTests.java) GitHub.

## Générez une URL pré-signée pour un téléchargement, puis téléchargez un fichier (requête PUT)
<a name="put-presignedobject"></a>

L'exemple suivant se compose de deux parties.
+ Partie 1 : Alice génère l'URL pré-signée pour télécharger un objet.
+ Partie 2 : Bob télécharge un fichier à l'aide de l'URL pré-signée.

### Partie 1 : Génération de l'URL
<a name="put-presigned-object-part1"></a>

Alice possède déjà un compartiment S3. Elle utilise le code suivant pour générer une chaîne d'URL que Bob pourra utiliser dans une requête PUT ultérieure.

#### Importations
<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();
        }
    }
```

### Partie 2 : Chargement d'un objet de fichier
<a name="put-presigned-object-part2"></a>

Bob utilise l'une des trois options de code suivantes pour charger un fichier.

#### Utiliser le JDK `HttpURLConnection` (depuis la 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);
        }
    }
```

#### Utiliser le JDK `HttpClient` (depuis la 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);
        }
    }
```

#### Utilisation `SdkHttpClient` depuis le SDK pour 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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java) et [testez](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedPutUrlTests.java) GitHub.

# Accès entre régions pour Amazon S3
<a name="s3-cross-region"></a>

Lorsque vous travaillez avec des buckets Amazon Simple Storage Service (Amazon S3), vous connaissez généralement Région AWS le compartiment correspondant. La région avec laquelle vous travaillez est déterminée lorsque vous créez le client S3. 

Cependant, il peut arriver que vous deviez travailler avec un compartiment spécifique, mais vous ne savez pas s'il se trouve dans la même région que celle définie pour le client S3. 

Au lieu de passer d'autres appels pour déterminer la région du compartiment, vous pouvez utiliser le SDK pour permettre l'accès aux compartiments S3 dans différentes régions.

## Configuration
<a name="s3-cross-region-setup"></a>

Support pour l'accès interrégional est devenu disponible avec la version `2.20.111` du SDK. Utilisez cette version ou une version ultérieure dans votre fichier de build Maven pour la `s3` dépendance, comme indiqué dans l'extrait suivant.

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
```

Ensuite, lorsque vous créez votre client S3, activez l'accès entre régions comme indiqué dans l'extrait de code. Par défaut, l'accès n'est pas activé.

```
S3AsyncClient client = S3AsyncClient.builder()
                                    .crossRegionAccessEnabled(true)
                                    .build();
```

## Comment le SDK fournit un accès interrégional
<a name="s3-cross-region-routing"></a>

Lorsque vous faites référence à un compartiment existant dans une demande, par exemple lorsque vous utilisez la `putObject` méthode, le SDK lance une demande auprès de la région configurée pour le client. 

Si le compartiment n'existe pas dans cette région spécifique, la réponse d'erreur inclut la région dans laquelle réside le compartiment. Le SDK utilise ensuite la région appropriée dans une deuxième demande.

Pour optimiser les futures demandes adressées au même compartiment, le SDK met en cache ce mappage de région dans le client.

## Considérations
<a name="s3-cross-region-considerations"></a>

Lorsque vous activez l'accès au compartiment entre régions, sachez que le premier appel d'API peut entraîner une augmentation de la latence si le compartiment ne se trouve pas dans la région configurée par le client. Cependant, les appels suivants bénéficient des informations de région mises en cache, ce qui améliore les performances.

Lorsque vous activez l'accès entre régions, l'accès au compartiment n'est pas affecté. L'utilisateur doit être autorisé à accéder au bucket, quelle que soit la région dans laquelle il réside.

# Protection de l'intégrité des données avec des checksums
<a name="s3-checksums"></a>

Amazon Simple Storage Service (Amazon S3) permet de spécifier une somme de contrôle lorsque vous chargez un objet. Lorsque vous spécifiez une somme de contrôle, elle est stockée avec l'objet et peut être validée lors du téléchargement de l'objet.

Les checksums fournissent une couche supplémentaire d'intégrité des données lorsque vous transférez des fichiers. Avec les checksums, vous pouvez vérifier la cohérence des données en confirmant que le fichier reçu correspond au fichier d'origine. Pour plus d'informations sur les checksums avec Amazon S3, consultez le [guide de l'utilisateur d'Amazon Simple Storage Service](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html), y compris les [algorithmes pris en charge](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#using-additional-checksums).

Vous avez la possibilité de choisir l'algorithme qui répond le mieux à vos besoins et de laisser le SDK calculer le checksum. Vous pouvez également fournir une valeur de somme de contrôle précalculée à l'aide de l'un des algorithmes pris en charge. 

**Note**  
À partir de la version 2.30.0 du AWS SDK for Java 2.x, le SDK fournit des protections d'intégrité par défaut en calculant automatiquement une somme de `CRC32` contrôle pour les téléchargements. Le SDK calcule cette somme de contrôle si vous ne fournissez pas de valeur de somme de contrôle précalculée ou si vous ne spécifiez pas d'algorithme que le SDK doit utiliser pour calculer une somme de contrôle.   
Le SDK fournit également des paramètres globaux pour les protections de l'intégrité des données que vous pouvez définir en externe, que vous pouvez consulter dans le [Guide de référence AWS SDKs et sur les outils](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html).

Nous discutons des sommes de contrôle en deux phases de demande : le téléchargement d'un objet et le téléchargement d'un objet. 

## Charger un objet
<a name="use-service-S3-checksum-upload"></a>

 Lorsque vous téléchargez un objet avec la `putObject` méthode et que vous fournissez un algorithme de somme de contrôle, le SDK calcule la somme de contrôle pour l'algorithme spécifié. 

L'extrait de code suivant montre une demande de téléchargement d'un objet avec une `SHA256` somme de contrôle. Lorsque le SDK envoie la demande, il calcule le `SHA256` checksum et télécharge l'objet. Amazon S3 valide l'intégrité du contenu en calculant le checksum et en le comparant au checksum fourni par le SDK. Amazon S3 enregistre ensuite le checksum avec l'objet.

```
public void putObjectWithChecksum() {
        s3Client.putObject(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA256),
            RequestBody.fromString("This is a test"));
}
```

Si vous ne fournissez pas d'algorithme de somme de contrôle avec la demande, le comportement de somme de contrôle varie en fonction de la version du SDK que vous utilisez, comme indiqué dans le tableau suivant.

**Comportement de somme de contrôle lorsqu'aucun algorithme de somme de contrôle n'est fourni**


| Version du SDK Java | Comportement de Checksum | 
| --- | --- | 
| antérieur à 2.30.0 | Le SDK ne calcule pas automatiquement une somme de contrôle basée sur le CRC et ne la fournit pas dans la demande. | 
| 2.30.0 ou version ultérieure | Le SDK utilise l'`CRC32`algorithme pour calculer le checksum et le fournit dans la demande. Amazon S3 valide l'intégrité du transfert en calculant sa propre somme de `CRC32` contrôle et en la comparant à la somme de contrôle fournie par le SDK. Si les sommes de contrôle correspondent, la somme de contrôle est enregistrée avec l'objet. | 

### Utiliser une valeur de somme de contrôle précalculée
<a name="use-service-S3-checksum-upload-pre"></a>

Une valeur de somme de contrôle précalculée fournie avec la demande désactive le calcul automatique par le SDK et utilise la valeur fournie à la place.

L'exemple suivant montre une demande avec une somme de SHA256 contrôle précalculée.

```
    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)));
    }
```

Si Amazon S3 détermine que la valeur de la somme de contrôle est incorrecte pour l'algorithme spécifié, le service renvoie une réponse d'erreur.

### Chargements partitionnés
<a name="use-service-S3-checksum-upload-multi"></a>

Vous pouvez également utiliser des checksums pour les téléchargements partitionnés.

 Le SDK pour Java 2.x propose deux options pour utiliser des checksums avec des téléchargements partitionnés. La première option utilise le`S3TransferManager`. 

L'exemple de gestionnaire de transfert suivant indique l' SHA1 algorithme pour le téléchargement.

```
    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();
    }
```

Si vous ne fournissez pas d'algorithme de somme de contrôle lorsque vous utilisez le gestionnaire de transfert pour les téléchargements, le SDK calcule automatiquement la somme de contrôle en fonction de cet algorithme. `CRC32` Le SDK effectue ce calcul pour toutes les versions du SDK.

La deuxième option utilise l'[`S3Client`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) (ou l'[`S3AsyncClient`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)) pour effectuer le téléchargement partitionné. Si vous spécifiez une somme de contrôle avec cette approche, vous devez spécifier l'algorithme à utiliser lors du lancement du téléchargement. Vous devez également spécifier l’algorithme pour chaque demande d’article et fournir la somme de contrôle calculée pour chaque article après son chargement.

```
    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()));
    }
```

[Le code des exemples complets et des](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PerformMultiPartUpload.java) [tests](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/test/java/com/example/s3/PerformMultiPartUploadTests.java) se trouve dans le référentiel d'exemples de GitHub code.

## Télécharger un objet
<a name="use-service-S3-checksum-download"></a>

Lorsque vous utilisez la méthode [GetObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest)) pour télécharger un objet, le SDK valide automatiquement la somme de contrôle la valeur de la clé est. `ChecksumMode` `enabled` lorsque la `checksumMode` méthode du générateur pour le `GetObjectRequest` est définie sur`ChecksumMode.ENABLED`. 

La demande contenue dans l'extrait suivant demande au SDK de valider la somme de contrôle dans la réponse en calculant la somme de contrôle et en comparant les valeurs.

```
    public GetObjectResponse getObjectWithChecksum() {
        return s3Client.getObject(b -> b
                        .bucket(bucketName)
                        .key(key)
                        .checksumMode(ChecksumMode.ENABLED))
                .response();
    }
```

**Note**  
Si l'objet n'a pas été chargé avec une somme de contrôle, aucune validation n'a lieu. 

## Autres options de calcul de la somme de contrôle
<a name="S3-checsum-calculation-options"></a>

**Note**  
Pour vérifier l'intégrité des données transmises et identifier toute erreur de transmission, nous encourageons les utilisateurs à conserver les paramètres par défaut du SDK pour les options de calcul de la somme de contrôle. Par défaut, le SDK ajoute cette vérification importante pour de nombreuses opérations S3, notamment `PutObject` et`GetObject`.

Toutefois, si votre utilisation d'Amazon S3 nécessite une validation minimale par somme de contrôle, vous pouvez désactiver de nombreux contrôles en modifiant les paramètres de configuration par défaut. 

### Désactiver le calcul automatique de la somme de contrôle sauf si cela est nécessaire
<a name="S3-minimize-checksum-calc-global"></a>

Vous pouvez désactiver le calcul automatique de la somme de contrôle par le SDK pour les opérations qui le prennent en charge, par exemple `PutObject` et. `GetObject` Certaines opérations S3 nécessitent toutefois un calcul de somme de contrôle ; vous ne pouvez pas désactiver le calcul de somme de contrôle pour ces opérations.

Le SDK fournit des paramètres distincts pour le calcul d'une somme de contrôle pour la charge utile d'une demande et pour la charge utile d'une réponse.

La liste suivante décrit les paramètres que vous pouvez utiliser pour minimiser les calculs de somme de contrôle dans les différentes étendues.
+ **Champ d'application de toutes les applications** : en modifiant les paramètres des variables d'environnement ou d'un profil dans AWS `config` les `credentials` fichiers partagés, toutes les applications peuvent utiliser ces paramètres. Ces paramètres affectent tous les clients de service dans toutes les applications du AWS SDK, sauf s'ils sont remplacés au niveau de l'application ou du client de service.
  + Ajoutez les paramètres dans un profil :

    ```
    [default]
    request_checksum_calculation = WHEN_REQUIRED
    response_checksum_validation = WHEN_REQUIRED
    ```
  + Ajoutez des variables d'environnement :

    ```
    AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
    AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED
    ```
+ **Champ d'application actuel** : vous pouvez définir la propriété système Java sur pour limiter le `aws.requestChecksumCalculation` calcul `WHEN_REQUIRED` de la somme de contrôle. La propriété système correspondante pour les réponses est`aws.responseChecksumValidation`.

  Ces paramètres affectent tous les clients du service SDK de l'application, sauf s'ils sont remplacés lors de la création du client de service.

  Définissez la propriété du système au début de votre application :

  ```
  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.
      }
  }
  ```
+ **Champ d'application du client de service S3 unique** : vous pouvez configurer un seul client de service S3 pour calculer le montant minimum de checksums à l'aide des méthodes de création :

  ```
  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. 
      }
  // ...
  }
  ```

### Utilisez le `LegacyMd5Plugin` pour une MD5 compatibilité simplifiée
<a name="S3-checksum-legacy-md5"></a>

Parallèlement à la publication du comportement des CRC32 checksum avec la version 2.30.0, le SDK a cessé de calculer les MD5 checksums pour les opérations requises.

Si vous avez besoin d'un ancien comportement de MD5 somme de contrôle pour les opérations S3, vous pouvez utiliser le`LegacyMd5Plugin`, qui a été publié avec la version 2.31.32 du SDK.

Cela `LegacyMd5Plugin` est particulièrement utile lorsque vous devez maintenir la compatibilité avec des applications qui dépendent du comportement de MD5 somme de contrôle existant, en particulier lorsque vous travaillez avec des fournisseurs de stockage tiers compatibles S3, tels que ceux utilisés avec les connecteurs de système de fichiers S3A (Apache Spark, Iceberg).

Pour l'utiliser`LegacyMd5Plugin`, ajoutez-le à votre générateur de clients S3 :

```
// For synchronous S3 client.
S3Client s3Client = S3Client.builder()
                           .addPlugin(LegacyMd5Plugin.create())
                           .build();

// For asynchronous S3 client.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .build();
```

Si vous souhaitez ajouter des sommes de MD5 contrôle aux opérations qui nécessitent des sommes de contrôle et que vous souhaitez éviter d'ajouter des sommes de contrôle par défaut du SDK pour les opérations qui prennent en charge les sommes de contrôle mais ne sont pas obligatoires, vous pouvez activer les options et comme. `ClientBuilder` `requestChecksumCalculation` `responseChecksumValidation` `WHEN_REQUIRED` Cela ajoutera les sommes de contrôle par défaut du SDK uniquement aux opérations nécessitant des sommes de contrôle :

```
// 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();
```

Cette configuration est particulièrement utile lorsque vous travaillez avec des systèmes de stockage tiers compatibles S3 qui ne prennent peut-être pas entièrement en charge les nouveaux algorithmes de somme de contrôle, mais qui nécessitent tout de même des MD5 sommes de contrôle pour certaines opérations.

# Utiliser un client S3 performant : client S3 AWS basé sur CRT
<a name="crt-based-s3-client"></a>

Le client S3 AWS basé sur CRT, basé sur le [AWS Common Runtime (CRT)](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html), est un client asynchrone S3 alternatif. [Il transfère des objets vers et depuis Amazon Simple Storage Service (Amazon S3) avec des performances et une fiabilité améliorées en utilisant automatiquement l'API de [téléchargement en plusieurs parties d'Amazon S3 et les extractions](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) par plage d'octets.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range) 

Le client S3 AWS basé sur CRT améliore la fiabilité des transferts en cas de défaillance du réseau. La fiabilité est améliorée en réessayant les différentes parties défaillantes d'un transfert de fichiers sans recommencer le transfert depuis le début.

En outre, le client S3 AWS basé sur CRT offre un regroupement de connexions amélioré et un équilibrage de charge du système de noms de domaine (DNS), ce qui améliore également le débit.

Vous pouvez utiliser le client S3 AWS basé sur CRT à la place du client asynchrone S3 standard du SDK et profiter immédiatement de son débit amélioré.

**Important**  
Le client S3 AWS basé sur CRT ne prend actuellement pas en charge la [collecte de métriques du SDK](metrics.md) au niveau du client ni au niveau des demandes.

**AWS Composants du SDK basés sur le CRT**

Le client *S3 AWS * basé sur CRT, décrit dans cette rubrique, et le client *HTTP AWS * basé sur CRT sont des composants différents du SDK. 

Le **client S3 AWS basé sur CRT** est une implémentation de l'AsyncClientinterface [S3](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) et est utilisé pour travailler avec le service Amazon S3. Il s'agit d'une alternative à l'implémentation Java de l'`S3AsyncClient`interface et offre plusieurs avantages.

Le [client HTTP AWS CRT](http-configuration-crt.md) est une implémentation de l'[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)interface et est utilisé pour les communications HTTP générales. Il s'agit d'une alternative à l'implémentation Netty de l'`SdkAsyncHttpClient`interface et offre plusieurs avantages.

Bien que les deux composants utilisent des bibliothèques issues du [AWS Common Runtime](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html), le client S3 AWS basé sur CRT utilise la [bibliothèque aws-c-s 3](https://github.com/awslabs/aws-c-s3) et prend en charge les fonctionnalités de l'API de [téléchargement partitionné S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html). Le client HTTP AWS CRT étant destiné à un usage général, il ne prend pas en charge les fonctionnalités de l'API de téléchargement partitionné S3.

## Ajoutez des dépendances pour utiliser le client S3 AWS basé sur CRT
<a name="crt-based-s3-client-depend"></a>

Pour utiliser le client S3 AWS basé sur CRT, ajoutez les deux dépendances suivantes à votre fichier de projet Maven. L'exemple montre les versions minimales à utiliser. Recherchez dans le référentiel central Maven les versions les plus récentes des artefacts [s3](https://central.sonatype.com/artifact/software.amazon.awssdk/s3) et [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>
```

## Création d'une instance du client S3 AWS basé sur CRT
<a name="crt-based-s3-client-create"></a>

 Créez une instance du client S3 AWS basé sur CRT avec les paramètres par défaut, comme indiqué dans l'extrait de code suivant.

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
```

Pour configurer le client, utilisez le générateur de clients AWS CRT. Vous pouvez passer du client asynchrone S3 standard au client AWS CRT en modifiant la méthode du générateur.

```
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();
```

**Note**  
Certains paramètres du générateur standard ne sont peut-être pas actuellement pris en charge dans le générateur client AWS CRT. Obtenez le constructeur standard en appelant`S3AsyncClient#builder()`.

## Utiliser le client S3 AWS basé sur CRT
<a name="crt-based-s3-client-use"></a>

Utilisez le client S3 AWS basé sur CRT pour appeler les opérations d'API Amazon S3. L'exemple suivant illustre les [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))opérations [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))et disponibles via le AWS SDK pour 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();
```

## Téléchargement de flux de taille inconnue
<a name="crt-stream-unknown-size"></a>

L'un des principaux avantages du client S3 AWS AWS basé sur CRT est sa capacité à gérer efficacement des flux d'entrée de taille inconnue. Cela est particulièrement utile lorsque vous devez télécharger des données à partir d'une source dont la taille totale ne peut pas être déterminée à l'avance.

```
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;
}
```

Cette fonctionnalité permet d'éviter les problèmes courants liés aux téléchargements traditionnels, où une spécification de longueur de contenu incorrecte peut entraîner la troncation d'objets ou l'échec des téléchargements.

## Limitations relatives à la configuration
<a name="crt-based-s3-client-limitations"></a>

Le client S3 AWS basé sur CRT et le client asynchrone S3 basé sur Java [offrent des fonctionnalités comparables](examples-s3.md#s3-clients), le client S3 basé AWS sur CRT offrant un avantage en termes de performances. Cependant, le client S3 AWS basé sur CRT ne possède pas les paramètres de configuration que possède le client asynchrone S3 basé sur Java. Ces paramètres sont les suivants :
+ *Configuration au niveau du client :* délai d'expiration des tentatives d'appel d'API, intercepteurs d'exécution de compression, éditeurs de métriques, attributs d'exécution personnalisés, options avancées personnalisées, service d'exécution planifié personnalisé, en-têtes personnalisés
+ *Configuration au niveau de la demande :* signataires personnalisés, délai d'expiration des tentatives d'appel d'API

Pour une liste complète des différences de configuration, consultez la référence de l'API.


| Client asynchrone S3 basé sur Java | AWS Client S3 basé sur CRT | 
| --- | --- | 
| Configurations au niveau du client[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Configurations au niveau de la demande[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | Configurations au niveau du client[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Configurations au niveau de la demande[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | 

# Configurer le client asynchrone S3 basé sur Java pour utiliser les transferts parallèles
<a name="s3-async-client-multipart"></a>

Depuis la version 2.27.5, le client asynchrone S3 standard basé sur Java prend en charge les transferts parallèles automatiques (chargements partitionnés et téléchargements). Vous configurez la prise en charge des transferts parallèles lorsque vous créez le client asynchrone S3 basé sur Java. 

Cette section explique comment activer les transferts parallèles et comment personnaliser la configuration.

## Créez une instance de `S3AsyncClient`
<a name="s3-async-client-multipart-create"></a>

Lorsque vous créez une `S3AsyncClient` instance sans appeler aucune des `multipart*` méthodes du [générateur](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html), les transferts parallèles ne sont pas activés. Chacune des instructions suivantes crée un client asynchrone S3 basé sur Java sans prise en charge des chargements partitionnés et des téléchargements.

### Créez *sans support* en plusieurs parties
<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();
```

### Créez *avec un support* en plusieurs parties
<a name="s3-async-client-mp-on"></a>

Pour activer les transferts parallèles avec les paramètres par défaut, appelez `multipartEnabled` le générateur et `true` transmettez-le comme indiqué dans l'exemple suivant.

**Example**  

```
S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartEnabled(true)
        .build();
```

La valeur par défaut est de 8 MiB pour les paramètres `thresholdInBytes` et`minimumPartSizeInBytes`.

Si vous personnalisez les paramètres partitionnés, les transferts parallèles sont automatiquement activés comme indiqué ci-dessous.

**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();
```

## Téléchargement de flux de taille inconnue
<a name="java-async-client-stream-unknown-size"></a>

Le client asynchrone S3 basé sur Java avec le multipart activé peut gérer efficacement les flux d'entrée dont la taille totale n'est pas connue à l'avance :

```
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;
}
```

Cette approche permet d'éviter les problèmes qui peuvent survenir lors de la spécification manuelle d'une longueur de contenu incorrecte, tels que des objets tronqués ou des échecs de téléchargement.

# Transférez des fichiers et des répertoires avec Amazon S3 Transfer Manager
<a name="transfer-manager"></a>

Amazon S3 Transfer Manager est un utilitaire de transfert de fichiers open source de haut niveau pour AWS SDK for Java 2.x. Utilisez-le pour transférer des fichiers et des répertoires depuis et vers Amazon Simple Storage Service (Amazon S3). 

[Lorsqu'il est construit sur le [client S3 AWS basé sur CRT ou sur le client asynchrone S3](crt-based-s3-client.md)[standard basé sur Java avec le multipart activé](s3-async-client-multipart.md), le gestionnaire de transfert S3 peut tirer parti des améliorations de performances telles que l'API de téléchargement en [plusieurs parties](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) et les extractions par plage d'octets.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range) 

Avec le gestionnaire de transfert S3, vous pouvez également suivre la progression d'un transfert en temps réel et le suspendre pour une exécution ultérieure.

## Mise en route
<a name="transfer-manager-prerequisites"></a>

### Ajoutez des dépendances à votre fichier de compilation
<a name="transfer-manager-add-dependency"></a>

Pour utiliser le gestionnaire de transfert S3 avec des performances multiparties améliorées, configurez votre fichier de build avec les dépendances nécessaires.

------
#### [ 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 [Dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom). 2 [Dernière version](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 [Dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

------

### Création d'une instance du gestionnaire de transfert S3
<a name="transfer-manager-create"></a>

Pour activer le transfert parallèle, vous devez transmettre un client S3 AWS basé sur CRT OU un client asynchrone S3 basé sur Java avec le multipart activé. Les exemples suivants montrent comment configurer un gestionnaire de transfert S3 avec des paramètres personnalisés. 

------
#### [ 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 ]

Si la `aws-crt` dépendance n'est pas incluse dans le fichier de compilation, le gestionnaire de transfert S3 est basé sur le client asynchrone S3 standard basé sur Java utilisé dans le SDK pour Java 2.x. 

**Configuration personnalisée du client S3 : nécessite l'activation du mode multipartie**

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
                .multipartEnabled(true)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

**Aucune configuration du client S3 - le support multipartie est automatiquement activé**

```
S3TransferManager transferManager = S3TransferManager.create();
```

------

## Charger un fichier dans un compartiment S3
<a name="transfer-manager-upload"></a>

L'exemple suivant montre un exemple de téléchargement de fichier ainsi que l'utilisation facultative de a [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), qui enregistre la progression du téléchargement.

Pour charger un fichier sur Amazon S3 à l'aide du gestionnaire de transfert S3, transmettez un [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)objet à `S3TransferManager` la méthode [uploadFile](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadFile(software.amazon.awssdk.transfer.s3.model.UploadFileRequest)).

L'[FileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileUpload.html)objet renvoyé par la `uploadFile` méthode représente le processus de téléchargement. Une fois la demande terminée, l'[CompletedFileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileUpload.html)objet contient des informations sur le téléchargement.

```
    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!
        */
    }
```

### Importations
<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;
```

## Télécharger un fichier depuis un compartiment S3
<a name="transfer-manager-download"></a>

L'exemple suivant montre un exemple de téléchargement ainsi que l'utilisation facultative de a [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), qui enregistre la progression du téléchargement.

Pour télécharger un objet depuis un compartiment S3 à l'aide du gestionnaire de transfert S3, créez un [DownloadFileRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadFileRequest.html)objet et transmettez-le à la méthode [DownloadFile](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadFile(software.amazon.awssdk.transfer.s3.model.DownloadFileRequest)).

L'[FileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileDownload.html)objet renvoyé par la `downloadFile` méthode `S3TransferManager`'s représente le transfert de fichier. Une fois le téléchargement terminé, il [CompletedFileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileDownload.html)contient l'accès aux informations relatives au téléchargement.

```
    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!
        */
    }
```

### Importations
<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;
```

## Copier un objet Amazon S3 dans un autre compartiment
<a name="transfer-manager-copy"></a>

L'exemple suivant montre comment copier un objet avec le gestionnaire de transfert S3.

Pour commencer à copier un objet d'un compartiment S3 vers un autre compartiment, créez une [CopyObjectRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/CopyObjectRequest.html)instance de base.

Ensuite, insérez les éléments de base `CopyObjectRequest` dans un [CopyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CopyRequest.html)fichier utilisable par le gestionnaire de transfert S3. 

L'`Copy`objet renvoyé par la `copy` méthode `S3TransferManager`'s représente le processus de copie. Une fois le processus de copie terminé, l'[CompletedCopy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedCopy.html)objet contient les détails de la réponse.

```
    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();
    }
```

**Note**  
Pour effectuer une copie entre régions avec le gestionnaire de transfert S3, activez-le `crossRegionAccessEnabled` sur le générateur de clients S3 AWS basé sur CRT, comme indiqué dans l'extrait suivant.  

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .crossRegionAccessEnabled(true)
                .build();

S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

### Importations
<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;
```

## Charger un répertoire local dans un compartiment S3
<a name="transfer-manager-upload_directory"></a>

L'exemple suivant montre comment télécharger un répertoire local dans S3.

Commencez par appeler la méthode [UploadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadDirectory(software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest)) de l'`S3TransferManager`instance, en lui transmettant un [UploadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadDirectoryRequest.html).

L'[DirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryUpload.html)objet représente le processus de téléchargement, qui génère un [CompletedDirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryUpload.html)lorsque la demande est terminée. L'`CompleteDirectoryUpload`objet contient des informations sur les résultats du transfert, notamment les fichiers qui n'ont pas pu être transférés.

```
    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();
    }
```

### Importations
<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;
```

## Télécharger des objets du compartiment S3 dans un répertoire local
<a name="transfer-manager-download_directory"></a>

Vous pouvez télécharger les objets d'un compartiment S3 dans un répertoire local, comme illustré dans l'exemple suivant.

Pour télécharger les objets d'un compartiment S3 vers un répertoire local, commencez par appeler la méthode [DownloadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadDirectory(software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest)) du gestionnaire de transfert, en transmettant un [DownloadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadDirectoryRequest.html).

L'[DirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryDownload.html)objet représente le processus de téléchargement, qui génère un [CompletedDirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryDownload.html)lorsque la demande est terminée. L'`CompleteDirectoryDownload`objet contient des informations sur les résultats du transfert, notamment les fichiers qui n'ont pas pu être transférés.

```
    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();
    }
```

### Importations
<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;
```

## Voir des exemples complets
<a name="transfer-manager-example-location"></a>

[GitHub contient le code complet](https://github.com/awsdocs/aws-doc-sdk-examples/tree/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/transfermanager) pour tous les exemples de cette page.

# Travaillez avec les notifications d'événements S3
<a name="examples-s3-event-notifications"></a>

Pour vous aider à surveiller l'activité dans vos compartiments, Amazon S3 peut envoyer des notifications lorsque certains événements se produisent. Le guide de l'utilisateur Amazon S3 fournit des informations sur les [notifications qu'un bucket peut envoyer](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html#notification-how-to-overview). 

Vous pouvez configurer un bucket pour envoyer des événements vers quatre destinations possibles à l'aide du SDK for Java : 
+ Rubriques Amazon Simple Notification Service
+ Files d'attente Amazon Simple Queue Service
+ AWS Lambda fonctions
+ Amazon EventBridge

Lorsque vous configurez un compartiment auquel envoyer des événements EventBridge, vous avez la possibilité de configurer une EventBridge règle pour répartir le même événement vers plusieurs destinations. Lorsque vous configurez votre bucket pour qu'il soit envoyé directement vers l'une des trois premières destinations, un seul type de destination peut être spécifié pour chaque événement.

Dans la section suivante, vous découvrirez comment configurer un compartiment à l'aide du SDK pour Java afin d'envoyer des notifications d'événements S3 de deux manières : directement à une file d'attente Amazon SQS et à. EventBridge

La dernière section explique comment utiliser l'API S3 Event Notifications pour travailler avec les notifications de manière orientée objet.

## Configuration d'un bucket à envoyer directement à une destination
<a name="s3-event-conf-bucket-direct"></a>

L'exemple suivant configure un compartiment pour envoyer des notifications lorsque des événements de *création d'objets* ou de *balisage d'objets* se produisent par rapport à un compartiment.

```
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)
    );
}
```

Le code ci-dessus définit une file d'attente pour recevoir deux types d'événements. De manière pratique, `queueConfigurations` cette méthode vous permet de définir plusieurs destinations de file d'attente si nécessaire. Dans `notificationConfiguration` cette méthode, vous pouvez également définir des destinations supplémentaires, telles qu'une ou plusieurs rubriques Amazon SNS ou une ou plusieurs fonctions Lambda. L'extrait suivant montre un exemple avec deux files d'attente et trois types de destinations.

```
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)
        );
```

Le GitHub référentiel d'exemples de code contient l'[exemple complet permettant](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java) d'envoyer des notifications d'événements S3 directement à une file d'attente.

## Configurer un bucket à envoyer à EventBridge
<a name="s3-event-conf-bucket-eventbridge"></a>

L'exemple suivant configure un bucket auquel envoyer des notifications. 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());
```

Lorsque vous configurez un compartiment auquel envoyer des événements EventBridge, vous indiquez simplement la EventBridge destination, et non les types d'événements ni la destination finale vers laquelle les événements EventBridge seront envoyés. Vous configurez les cibles et les types d'événements ultimes à l'aide du EventBridge client du SDK Java.

Le code suivant montre comment configurer EventBridge pour répartir les événements *créés par un objet* dans une rubrique et une file d'attente.

```
   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;
    }
```

Pour l'utiliser EventBridge dans votre code Java, ajoutez une dépendance à l'`eventbridge`artefact à votre fichier Maven`pom.xml`.

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>eventbridge</artifactId>
</dependency>
```

Le GitHub référentiel d'exemples de code contient l'[exemple complet permettant](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PutBucketS3EventNotificationEventBridge.java) d'envoyer des notifications d'événements S3 à, EventBridge puis à une rubrique et à une file d'attente.

## Utiliser l'API S3 Event Notifications pour traiter les événements
<a name="s3-event-notification-read"></a>

Une fois qu'une destination a reçu des événements de notification S3, vous pouvez les traiter de manière orientée objet à l'aide de l'API S3 Event Notifications. Vous pouvez utiliser l'API S3 Event Notifications pour travailler avec les notifications d'événements envoyées directement à une cible (comme indiqué dans le [premier exemple](#s3-event-conf-bucket-direct)), mais pas avec les notifications EventBridge acheminées. Les notifications d'événements S3 sont envoyées par des buckets pour EventBridge contenir une [structure différente](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ev-events.html#ev-events-list) que l'API S3 Event Notifications ne gère pas actuellement.

### Ajouter une dépendance
<a name="s3-event-notifications-dep"></a>

L'API S3 Event Notifications a été publiée avec la version 2.25.11 du SDK pour Java 2.x.

Pour utiliser l'API S3 Event Notifications, ajoutez l'élément de dépendance requis à votre Maven, `pom.xml` comme indiqué dans l'extrait suivant.

```
<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 [Dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

### Utilisez la `S3EventNotification` classe
<a name="s3-event-notifications-use"></a>

#### Création d'une `S3EventNotification` instance à partir d'une chaîne JSON
<a name="s3-event-notifications-use-from-json"></a>

Pour convertir une chaîne JSON en `S3EventNotification` objet, utilisez les méthodes statiques de la `S3EventNotification` classe, comme indiqué dans l'exemple suivant.

```
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();                                                                                                   
    }
}
```

Dans cet exemple, la `fromJson` méthode convertit la chaîne JSON en `S3EventNotification` objet. Les champs manquants dans la chaîne JSON se traduiront par `null` des valeurs dans les champs d'objet Java correspondants et tous les champs supplémentaires dans le JSON seront ignorés.

D'autres APIs informations relatives à un enregistrement de notification d'événement peuvent être trouvées dans la référence de l'API pour`[S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html)`.

#### Convertir une `S3EventNotification` instance en chaîne JSON
<a name="s3-event-notifications-use-to-json"></a>

Utilisez la méthode `toJson` (or`toJsonPretty`) pour convertir un `S3EventNotification` objet en chaîne JSON, comme illustré dans l'exemple suivant.

```
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);
    }
}
```

Les champs pour `GlacierEventData``ReplicationEventData`,`IntelligentTieringEventData`, et `LifecycleEventData` sont exclus du JSON s'ils le sont`null`. `null`Les autres champs seront sérialisés en tant que`null`.

Voici un exemple de sortie de la `toJsonPretty` méthode pour un événement de balisage d'objets 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
      }
    }
  } ]
}
```

Un [exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/75c3daadf750406156fc87fa30ee499a206b4a36/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java#L117) est disponible dans GitHub lequel il montre comment utiliser l'API pour traiter les notifications reçues par une file d'attente Amazon SQS.

## Traitez les événements S3 dans Lambda avec les bibliothèques Java : et AWS SDK for Java 2.x `aws-lambda-java-events`
<a name="s3-event-notif-processing-options"></a>

Au lieu d'utiliser le SDK pour Java 2.x pour traiter les notifications d'événements Amazon S3 dans une fonction Lambda, vous pouvez utiliser `[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)` la bibliothèque en version 3.x.x. AWS gère la `aws-lambda-java-events` bibliothèque de manière indépendante, et elle a ses propres exigences de dépendance. La `aws-lambda-java-events` bibliothèque fonctionne uniquement avec les événements S3 dans les fonctions Lambda, tandis que le SDK pour Java 2.x fonctionne avec les événements S3 dans les fonctions Lambda, Amazon SNS et Amazon SQS.

Les deux approches modélisent la charge utile des notifications d'événements JSON d'une manière orientée objet avec une approche similaire. APIs Le tableau suivant montre les différences notables entre l'utilisation des deux approches.


****  

|  | AWS SDK pour Java | aws-lambda-java-events bibliothèque | 
| --- | --- | --- | 
| Dénomination du package |  `software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification`  | com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification | 
| RequestHandler paramètre |  Écrivez l'`RequestHandler`implémentation de votre fonction Lambda pour recevoir une chaîne 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>  | Écrivez l'RequestHandlerimplémentation de votre fonction Lambda pour recevoir un S3Event objet :<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> | 
| Dépendances de 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>  | 

# Travaillez avec Amazon Simple Notification Service
<a name="examples-simple-notification-service"></a>

Avec Amazon Simple Notification Service, vous pouvez facilement envoyer des messages de notification en temps réel de vos applications aux abonnés via plusieurs canaux de communication. Cette rubrique décrit comment exécuter certaines des fonctions de base de Amazon SNS.

## Créer une rubrique
<a name="sns-create-topic"></a>

Un **sujet** est un regroupement logique de canaux de communication qui définit les systèmes auxquels envoyer un message, par exemple en diffusant un message AWS Lambda et en envoyant un webhook HTTP. Vous envoyez des messages à Amazon SNS, puis ils sont distribués aux canaux définis dans le sujet. Les messages sont alors disponibles pour les abonnés.

Pour créer un sujet, créez d'abord un [CreateTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicRequest.html)objet, avec le nom du sujet défini à l'aide de la `name()` méthode du générateur. Envoyez ensuite l'objet de demande à Amazon SNS en utilisant la `createTopic()` méthode du [SnsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/SnsClient.html). Vous pouvez capturer le résultat de cette demande sous forme d'[CreateTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicResponse.html)objet, comme illustré dans l'extrait de code suivant.

 **Importations** 

```
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;
```

 **Code** 

```
    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 "";
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/CreateTopic.java) sur GitHub.

## Listez vos Amazon SNS sujets
<a name="sns-crelistate-topics"></a>

Pour récupérer la liste de vos Amazon SNS sujets existants, créez un [ListTopicsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsRequest.html)objet. Envoyez ensuite l'objet de demande à Amazon SNS en utilisant la `listTopics()` méthode du`SnsClient`. Vous pouvez capturer le résultat de cette demande sous forme d'[ListTopicsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsResponse.html)objet.

L'extrait de code suivant affiche le code d'état HTTP de la demande et une liste des Amazon Resource Names (ARNs) pour vos Amazon SNS sujets.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/ListTopics.java) sur GitHub.

## Abonner un point de terminaison à une rubrique
<a name="sns-subscribe-endpoint-topic"></a>

Après avoir créé une rubrique, vous pouvez configurer les canaux de communication qui deviendront des points de terminaison pour cette rubrique. Les messages sont distribués à ces points de terminaison après les avoir Amazon SNS reçus.

Pour configurer un canal de communication en tant que point de terminaison pour une rubrique, abonnez ce point de terminaison à la rubrique. Pour commencer, créez un [SubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html)objet. Spécifiez le canal de communication (par exemple, `lambda` ou`email`) en tant que`protocol()`. Définissez l'emplacement `endpoint()` de sortie approprié (par exemple, l'ARN d'une Lambda fonction ou une adresse e-mail), puis définissez l'ARN du sujet auquel vous souhaitez vous abonner en tant que`topicArn()`. Envoyez l'objet de demande à Amazon SNS en utilisant la `subscribe()` méthode du`SnsClient`. Vous pouvez capturer le résultat de cette demande sous forme d'[SubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeResponse.html)objet.

L'extrait de code suivant montre comment abonner une adresse e-mail à une rubrique.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/SubscribeEmail.java) sur GitHub.

## Publier un message dans une rubrique
<a name="sns-publish-message-topic"></a>

Après avoir configuré une rubrique et un ou plusieurs points de terminaison, vous pouvez y publier un message. Pour commencer, créez un [PublishRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishRequest.html)objet. Spécifiez le `message()` à envoyer et l'ARN de la rubrique (`topicArn()`) à laquelle l'envoyer. Envoyez ensuite l'objet de demande à Amazon SNS en utilisant la `publish()` méthode du`SnsClient`. Vous pouvez capturer le résultat de cette demande sous forme d'[PublishResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishResponse.html)objet.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
         }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/PublishTopic.java) sur GitHub.

## Désabonner un point de terminaison à une rubrique
<a name="sns-unsubscribe-endpoint-topic"></a>

Vous pouvez supprimer les canaux de communication configurés en tant que points de terminaison pour une rubrique. Après cela, la rubrique elle-même continue d'exister et de diffuser des messages à tous les autres points de terminaison configurés pour cette rubrique.

Pour supprimer un canal de communication en tant que point de terminaison pour une rubrique, annulez l’abonnement du point de terminaison à la rubrique. Pour commencer, créez un [UnsubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeRequest.html)objet et définissez l'ARN du sujet dont vous souhaitez vous désabonner comme étant le`subscriptionArn()`. Ensuite, envoyez l'objet de demande à SNS en utilisant la méthode `unsubscribe()` du `SnsClient`. Vous pouvez capturer le résultat de cette demande sous forme d'[UnsubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeResponse.html)objet.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/Unsubscribe.java) sur GitHub.

## Supprimer une rubrique
<a name="sns-delete-topic"></a>

Pour supprimer un Amazon SNS sujet, créez d'abord un [DeleteTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicRequest.html)objet avec l'ARN du sujet défini comme `topicArn()` méthode dans le générateur. Envoyez ensuite l'objet de demande à Amazon SNS en utilisant la `deleteTopic()` méthode du`SnsClient`. Vous pouvez capturer le résultat de cette demande sous forme d'[DeleteTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicResponse.html)objet, comme illustré dans l'extrait de code suivant.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
        }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/DeleteTopic.java) sur GitHub.

Pour plus d’informations, consultez le [Manuel du développeur Amazon Simple Notification Service](https://docs.aws.amazon.com/sns/latest/dg/).

# Travaillez avec Amazon Simple Queue Service
<a name="examples-sqs"></a>

Cette section fournit des exemples de programmation à l'[Amazon Simple Queue Service](https://docs.aws.amazon.com/sqs/)aide de la version AWS SDK pour Java 2.x.

Les exemples suivants incluent uniquement le code nécessaire pour démontrer chaque technique. L'[exemple de code complet est disponible sur GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). À partir de là, vous pouvez télécharger un fichier source unique ou cloner le référentiel en local pour obtenir tous les exemples à générer et exécuter.

**Topics**
+ [Utiliser le traitement automatique des demandes par lots](sqs-auto-batch.md)
+ [Opérations sur les files](examples-sqs-message-queues.md)
+ [Opérations relatives aux messages](examples-sqs-messages.md)

# Utilisez le traitement automatique des demandes par lots pour Amazon SQS avec AWS SDK for Java 2.x
<a name="sqs-auto-batch"></a>

L'API Automatic Request Batching pour Amazon SQS est une bibliothèque de haut niveau qui fournit un moyen efficace de regrouper et de mettre en mémoire tampon les demandes pour les opérations SQS. En utilisant l'API de traitement par lots, vous réduisez le nombre de demandes adressées à SQS, ce qui améliore le débit et minimise les coûts. 

Comme les méthodes de l'API par lots correspondent aux `[SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)` méthodes (`sendMessage`,,,),`changeMessageVisibility`,`deleteMessage`,,`receiveMessage`,,,,,,, vous pouvez utiliser l'API par lots en remplacement avec un minimum de modifications. 

Cette rubrique explique comment configurer et utiliser l'API Automatic Request Batching pour Amazon SQS.

## Vérifiez les prérequis
<a name="sqs-auto-batch-requirements"></a>

Vous devez utiliser la version *2.28.0* ou ultérieure du SDK pour Java 2.x pour avoir accès à l'API de traitement par lots. Votre Maven `pom.xml` doit au moins contenir les éléments suivants.

```
<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 [Dernière version](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)

## Création d'un gestionnaire de lots
<a name="sqs-auto-batch-create"></a>

L'API de traitement automatique des demandes par lots est implémentée par l'[SqsAsyncBatchManager](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html)interface. Vous pouvez créer une instance du gestionnaire de plusieurs manières.

### Configuration par défaut en utilisant `SqsAsyncClient`
<a name="sqs-batch-manager-create-default"></a>

Le moyen le plus simple de créer un gestionnaire de lots consiste à appeler la méthode d'`batchManager`usine sur une [SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)instance existante. L'approche simple est illustrée dans l'extrait suivant. 

```
SqsAsyncClient asyncClient = SqsAsyncClient.create();
SqsAsyncBatchManager sqsAsyncBatchManager = asyncClient.batchManager();
```

Lorsque vous utilisez cette approche, l'`SqsAsyncBatchManager`instance utilise les valeurs par défaut indiquées dans le tableau de la [Remplacer les paramètres de configuration pour `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) section. En outre, l'`SqsAsyncBatchManager`instance utilise `ExecutorService` l'`SqsAsyncClient`instance à partir de laquelle elle a été créée.

### Configuration personnalisée en utilisant `SqsAsyncBatchManager.Builder`
<a name="sqs-batch-manager-create-custom"></a>

Pour des cas d'utilisation plus avancés, vous pouvez personnaliser le gestionnaire de lots à l'aide du [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). En utilisant cette approche pour créer une `SqsAsyncBatchManager` instance, vous pouvez affiner le comportement de traitement par lots. L'extrait suivant montre un exemple d'utilisation du générateur pour personnaliser le comportement de traitement par lots.

```
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();
```

Lorsque vous utilisez cette approche, vous pouvez ajuster les paramètres de l'`BatchOverrideConfiguration`objet présentés dans le tableau de la [Remplacer les paramètres de configuration pour `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) section. Vous pouvez également fournir une personnalisation [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)pour le gestionnaire de lots en utilisant cette approche.

## Envoyer des messages
<a name="sqs-auto-batch-send"></a>

Pour envoyer des messages avec le gestionnaire de lots, utilisez la `[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))` méthode. Le SDK met en mémoire tampon les demandes et les envoie sous forme de lot lorsque les `sendRequestFrequency` valeurs `maxBatchSize` or sont atteintes.

L'exemple suivant montre une `sendMessage` demande immédiatement suivie d'une autre demande. Dans ce cas, le SDK envoie les deux messages en un seul lot.

```
// 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();
```

## Modifier le délai de visibilité des messages
<a name="sqs-auto-batch-change-vis"></a>

Vous pouvez modifier le délai de visibilité des messages d'un lot à l'aide de [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))cette méthode. Le SDK met en mémoire tampon les demandes et les envoie sous forme de lot lorsque les `sendRequestFrequency` valeurs `maxBatchSize` or sont atteintes.

L'exemple suivant montre comment appeler la `changeMessageVisibility` méthode.

```
CompletableFuture<ChangeMessageVisibilityResponse> futureOne =
    sqsAsyncBatchManager.changeMessageVisibility(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
ChangeMessageVisibilityResponse response = futureOne.join();
```

## Supprimer des messages
<a name="sqs-auto-batch-delete"></a>

Vous pouvez supprimer des messages par lots à l'aide de [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))cette méthode. Le SDK met en mémoire tampon les demandes et les envoie sous forme de lot lorsque les `sendRequestFrequency` valeurs `maxBatchSize` or sont atteintes.

L'exemple suivant montre comment appeler la `deleteMessage` méthode.

```
CompletableFuture<DeleteMessageResponse> futureOne = 
    sqsAsyncBatchManager.deleteMessage(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
DeleteMessageResponse response = futureOne.join();
```

## Recevoir des messages
<a name="sqs-auto-batch-receive"></a>

### Utiliser les paramètres par défaut
<a name="sqs-auto-batch-receive-default-settings"></a>

Lorsque vous interrogez la `[SqsAsyncBatchManager\$1receiveMessage](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#receiveMessage(java.util.function.Consumer))` méthode dans votre application, le gestionnaire de lots extrait les messages de sa mémoire tampon interne, que le SDK met automatiquement à jour en arrière-plan.

L'exemple suivant montre comment appeler la `receiveMessage` méthode.

```
CompletableFuture<ReceiveMessageResponse> responseFuture = 
    sqsAsyncBatchManager.receiveMessage(r -> r.queueUrl("queueUrl"));
```

### Utiliser des paramètres personnalisés
<a name="sqs-auto-batch-receive-custom-settings"></a>

Si vous souhaitez personnaliser davantage la demande, par exemple en définissant des temps d'attente personnalisés et en spécifiant le nombre de messages à récupérer, vous pouvez personnaliser la demande comme indiqué dans l'exemple suivant.

```
CompletableFuture<ReceiveMessageResponse> response = 
    sqsAsyncBatchManager.receiveMessage(r -> 
        r.queueUrl("queueUrl")
         .waitTimeSeconds(5)
         .visibilityTimeout(20));
```

**Note**  
Si vous appelez `receiveMessage` avec un `[ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)` qui inclut l'un des paramètres suivants, le SDK contourne le gestionnaire de lots et envoie une demande asynchrone `receiveMessage` normale :  
`messageAttributeNames`
`messageSystemAttributeNames`
`messageSystemAttributeNamesWithStrings`
`overrideConfiguration`

## Remplacer les paramètres de configuration pour `SqsAsyncBatchManager`
<a name="sqs-auto-batch-config-settings"></a>

Vous pouvez ajuster les paramètres suivants lorsque vous créez une `SqsAsyncBatchManager` instance. La liste de paramètres suivante est disponible sur le [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).


| Paramètre | Description | Valeur par défaut | 
| --- | --- | --- | 
| maxBatchSize | Nombre maximum de demandes par lot pour chaque SendMessageBatchRequestChangeMessageVisibilityBatchRequest, ouDeleteMessageBatchRequest. La valeur maximale est 10. | 10 | 
| sendRequestFrequency |  Durée avant l'envoi d'un lot, sauf si `maxBatchSize` elle est atteinte plus tôt. Des valeurs plus élevées peuvent réduire les demandes mais augmenter le temps de latence.  | 200 ms | 
| receiveMessageVisibilityTimeout | Délai de visibilité pour les messages. S'il n'est pas défini, la valeur par défaut de la file d'attente est utilisée. | Par défaut de la file d'attente | 
| receiveMessageMinWaitDuration | Temps d'attente minimal pour les receiveMessage demandes. Évitez de mettre à 0 pour éviter le gaspillage du processeur. | 50 ms | 
| receiveMessageSystemAttributeNames | Liste des [noms d'attributs système](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/MessageSystemAttributeName.html) à demander pour les receiveMessage appels. | Aucune | 
| receiveMessageAttributeNames | Liste des [noms d'attributs](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-message-attributes) à demander pour les receiveMessage appels. | Aucune | 

# Travailler avec les files d'attente de Amazon Simple Queue Service messages
<a name="examples-sqs-message-queues"></a>

Une *file de messages* est le conteneur logique utilisé pour envoyer des messages de manière fiable Amazon Simple Queue Service. Il existe deux types de files d'attente : *standard* et *FIFO* (premier entré, premier sorti). Pour en savoir plus sur les files d'attente et les différences entre ces types, consultez le [guide du Amazon Simple Queue Service développeur](https://docs.aws.amazon.com//AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html).

Cette rubrique décrit comment créer, répertorier, supprimer et obtenir l'URL d'une Amazon Simple Queue Service file d'attente à l'aide du AWS SDK pour Java.

La `sqsClient` variable utilisée dans les exemples suivants peut être créée à partir de l'extrait de code suivant.

```
SqsClient sqsClient = SqsClient.create();
```

Lorsque vous créez un en `SqsClient` utilisant la `create()` méthode statique, le SDK configure la région en utilisant la chaîne de fournisseurs de régions par [défaut et les informations d'identification en utilisant la chaîne de fournisseurs](region-selection.md#default-region-provider-chain) d'informations [d'identification par défaut](credentials-chain.md).

## Création d’une file d’attente
<a name="sqs-create-queue"></a>

Utilisez la `SqsClient’s` `createQueue` méthode et fournissez un `[CreateQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/CreateQueueRequest.html)` objet qui décrit les paramètres de la file d'attente, comme indiqué dans l'extrait de code suivant.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
            CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
                .queueName(queueName)
                .build();

            sqsClient.createQueue(createQueueRequest);
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L52) sur GitHub.

## Répertorier les files d'attente
<a name="sqs-list-queues"></a>

Pour répertorier les Amazon Simple Queue Service files d'attente pour votre compte, appelez la `SqsClient’s` `listQueues` méthode avec un `[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)` objet.

Lorsque vous utilisez la forme de la [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())méthode qui ne prend aucun paramètre, le service renvoie *toutes les files d'attente, jusqu'à 1 000 files d'attente*. 

Vous pouvez fournir un préfixe de nom de file d'attente à l'`[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)`objet pour limiter les résultats aux files d'attente correspondant à ce préfixe, comme indiqué dans le code suivant.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
        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);
        }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L79) sur GitHub.

## Obtenir l'URL d'une file d'attente
<a name="sqs-get-queue-url"></a>

Le code suivant montre comment obtenir l'URL d'une file d'attente en appelant la `SqsClient’s` `getQueueUrl` méthode avec un `[GetQueueUrlRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/GetQueueUrlRequest.html)` objet.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
            GetQueueUrlResponse getQueueUrlResponse =
                sqsClient.getQueueUrl(GetQueueUrlRequest.builder().queueName(queueName).build());
            String queueUrl = getQueueUrlResponse.queueUrl();
            return queueUrl;
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L70) sur GitHub.

## Suppression d’une file d’attente
<a name="sqs-delete-queue"></a>

Fournissez l'[URL](#sqs-get-queue-url) de la file d'attente vers l'`[DeleteQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/DeleteQueueRequest.html)`objet. Appelez ensuite la `SqsClient’s` `deleteQueue` méthode pour supprimer une file d'attente comme indiqué dans le code suivant.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
    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);
        }
    }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/6240df86c5f17eae1e23d1139d1435c7dc4b2a11/javav2/example_code/sqs/src/main/java/com/example/sqs/DeleteQueue.java#L48) sur GitHub.

## En savoir plus
<a name="more-information"></a>
+  [CreateQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html)dans la référence de Amazon Simple Queue Service l'API
+  [GetQueueUrl](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueUrl.html)dans la référence de Amazon Simple Queue Service l'API
+  [ListQueues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html)dans la référence de Amazon Simple Queue Service l'API
+  [DeleteQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html)dans la référence de Amazon Simple Queue Service l'API

# Envoyer, recevoir et supprimer Amazon Simple Queue Service des messages
<a name="examples-sqs-messages"></a>

Un message est une portion de données qui peut être envoyée et reçue par des composants distribués. Les messages sont toujours livrés à l'aide d'une [file d'attente SQS](examples-sqs-message-queues.md).

La `sqsClient` variable utilisée dans les exemples suivants peut être créée à partir de l'extrait de code suivant.

```
SqsClient sqsClient = SqsClient.create();
```

Lorsque vous créez un en `SqsClient` utilisant la `create()` méthode statique, le SDK configure la région en utilisant la chaîne de fournisseurs de régions par [défaut et les informations d'identification en utilisant la chaîne de fournisseurs](region-selection.md#default-region-provider-chain) d'informations [d'identification par défaut](credentials-chain.md).

## Envoyer un message
<a name="sqs-message-send"></a>

Ajoutez un seul message à une Amazon Simple Queue Service file d'attente en appelant la `sendMessage` méthode SqsClient client. Fournissez un [SendMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageRequest.html)objet contenant l'[URL](examples-sqs-message-queues.md#sqs-get-queue-url) de la file d'attente, le corps du message et la valeur de délai facultative (en secondes).

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
            sqsClient.sendMessage(SendMessageRequest.builder()
                .queueUrl(queueUrl)
                .messageBody("Hello world!")
                .delaySeconds(10)
                .build());

            sqsClient.sendMessage(sendMsgRequest);
```

## Envoyer plusieurs messages dans une demande
<a name="sqs-messages-send-multiple"></a>

Envoyez plusieurs messages dans une seule demande à l'aide de la méthode `sendMessageBatch` d' SqsClient . Cette méthode utilise un [SendMessageBatchRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequest.html)qui contient l'URL de la file d'attente et une liste de messages à envoyer. (Chaque message est un [SendMessageBatchRequestEntry](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequestEntry.html).) Vous pouvez aussi retarder l'envoi d'un message spécifique en définissant une valeur de retard sur le message.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
            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);
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L133) sur GitHub.

## Extraction des messages
<a name="sqs-messages-receive"></a>

Récupérez tous les messages qui sont actuellement dans la file d'attente en appelant la méthode `receiveMessage` d' SqsClient . Cette méthode utilise un [ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)qui contient l'URL de la file d'attente. Vous pouvez également spécifier le nombre maximal de messages à renvoyer. Les messages sont renvoyés sous la forme d'une liste d'objets [Message](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/Message.html).

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
        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;
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L148) sur GitHub.

## Supprimer un message après réception
<a name="sqs-messages-delete"></a>

Après avoir reçu un message et traité son contenu, supprimez-le de la file d'attente en envoyant le descripteur de réception du message et l'URL de la file d'attente à la `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))méthode.

 **Importations** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Code** 

```
        try {
            for (Message message : messages) {
                DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                        .queueUrl(queueUrl)
                        .receiptHandle(message.receiptHandle())
                        .build();
                sqsClient.deleteMessage(deleteMessageRequest);
            }
```

Voir l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L187) sur GitHub.

## Plus d'informations
<a name="more-info"></a>
+  [Comment fonctionnent les Amazon Simple Queue Service files d'attente](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html) dans le guide du Amazon Simple Queue Service développeur
+  [SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)dans la référence de Amazon Simple Queue Service l'API
+  [SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)dans la référence de Amazon Simple Queue Service l'API
+  [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)dans la référence de Amazon Simple Queue Service l'API
+  [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)dans la référence de Amazon Simple Queue Service l'API

# Travaillez avec Amazon Transcribe
<a name="examples-transcribe"></a>

L'exemple suivant montre comment le streaming bidirectionnel fonctionne avec Amazon Transcribe. Le streaming bidirectionnel implique qu'un flux de données soit à la fois envoyé au service et reçu en temps réel. L'exemple utilise la transcription Amazon Transcribe en continu pour envoyer un flux audio et recevoir un flux de texte transcrit en temps réel.

Consultez la section [Transcription en streaming](https://docs.aws.amazon.com//transcribe/latest/dg/streaming.html) dans le guide du Amazon Transcribe développeur pour en savoir plus sur cette fonctionnalité.

Consultez [Getting Started](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html) dans le guide du Amazon Transcribe développeur pour commencer à utiliser Amazon Transcribe.

## Configurez le microphone
<a name="set-up-the-microphone"></a>

Ce code utilise le package javax.sound.sampled pour créer un flux en streaming audio à partir d'un périphérique d'entrée.

 **Code** 

```
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;
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/Microphone.java) sur GitHub.

## Création d'un éditeur
<a name="create-a-publisher"></a>

Ce code implémente un éditeur qui publie les données audio à partir du flux Amazon Transcribe audio.

 **Code** 

```
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();
        }
    }
}
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/AudioStreamPublisher.java) sur GitHub.

## Créez le client et lancez le stream
<a name="create-the-client-and-start-the-stream"></a>

Dans la méthode principale, créez une demande d'objet, démarrez le flux d'entrée audio et instanciez l'éditeur avec l'entrée audio.

Vous devez également créer un [StartStreamTranscriptionResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/transcribestreaming/model/StartStreamTranscriptionResponseHandler.html)pour spécifier comment gérer la réponse de Amazon Transcribe.

Ensuite, utilisez la `startStreamTranscription` méthode TranscribeStreamingAsyncClient's pour démarrer le streaming bidirectionnel.

 **Importations** 

```
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;
```

 **Code** 

```
    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);
         }
    }
```

Consultez l'[exemple complet](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/BidirectionalStreaming.java) sur GitHub.

## En savoir plus
<a name="more-info"></a>
+  [Comment cela fonctionne](https://docs.aws.amazon.com//transcribe/latest/dg/how-it-works.html) dans le guide du Amazon Transcribe développeur.
+  [Pour démarrer avec le streaming audio](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html), consultez le guide du Amazon Transcribe développeur.