

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Chiamata Servizi AWS dal AWS SDK for Java 2.x
<a name="work-with-services"></a>

Questa sezione fornisce brevi tutorial e linee guida su come lavorare con select. Servizi AWS Per un set completo di esempi, consulta la sezione [Esempi di codice.](java_code_examples.md)

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

# Lavora con CloudWatch
<a name="examples-cloudwatch"></a>

Questa sezione fornisce esempi di programmazione di [Amazon CloudWatch](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) utilizzando AWS SDK per Java 2.x.

 Amazon CloudWatch monitora le tue risorse Amazon Web Services (AWS) e le applicazioni su cui esegui AWS in tempo reale. Puoi utilizzarlo CloudWatch per raccogliere e tenere traccia delle metriche, che sono variabili che puoi misurare per le tue risorse e applicazioni. CloudWatch gli allarmi inviano notifiche o apportano automaticamente modifiche alle risorse che stai monitorando in base a regole da te definite.

Gli esempi seguenti includono solo il codice necessario per dimostrare ciascuna tecnica. Il [codice di esempio completo è disponibile su. GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2) Da qui puoi scaricare un singolo file sorgente o clonare l'archivio localmente per ottenere tutti gli esempi da creare ed eseguire.

**Topics**
+ [Ottieni metriche da CloudWatch](examples-cloudwatch-get-metrics.md)
+ [Pubblica dati metrici personalizzati su CloudWatch](examples-cloudwatch-publish-custom-metrics.md)
+ [Lavora con gli CloudWatch allarmi](examples-cloudwatch-create-alarms.md)
+ [Usa Amazon CloudWatch Events](examples-cloudwatch-send-events.md)

# Ottieni metriche da CloudWatch
<a name="examples-cloudwatch-get-metrics"></a>

## Elencazione dei parametri
<a name="listing-metrics"></a>

Per elencare le CloudWatch metriche, crea un metodo [ListMetricsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsRequest.html)e chiama il CloudWatchClient metodo's. `listMetrics` Puoi utilizzare `ListMetricsRequest` per filtrare i parametri restituiti in base a spazio dei nomi, nome parametro o dimensioni.

**Nota**  
Un elenco di metriche e dimensioni pubblicate dai AWS servizi è disponibile nel [riferimento alle Amazon CloudWatch metriche e alle dimensioni](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) nella Guida per l' Amazon CloudWatch utente.

 **Importazioni** 

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

 **Codice** 

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

Le metriche vengono restituite in un [ListMetricsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/ListMetricsResponse.html)chiamando il relativo metodo. `getMetrics`

I risultati possono essere *paginati*. Per recuperare il batch di risultati successivo, chiama `nextToken` sull'oggetto di risposta e utilizza il valore del token per creare un nuovo oggetto richiesta. Quindi, chiama nuovamente il metodo `listMetrics` con una nuova richiesta.

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [ListMetrics](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_ListMetrics.html)nell' Amazon CloudWatch API Reference

# Pubblica dati metrici personalizzati su CloudWatch
<a name="examples-cloudwatch-publish-custom-metrics"></a>

Alcuni AWS servizi pubblicano [le proprie metriche](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html) in namespace che iniziano con "`AWS`" Puoi anche pubblicare dati metrici personalizzati utilizzando il tuo spazio dei nomi (purché non inizi con "«). `AWS`

## Pubblicare dati dei parametri personalizzati
<a name="cwid1"></a>

Per pubblicare i tuoi dati metrici, chiama il metodo's con a. CloudWatchClient `putMetricData` [PutMetricDataRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricDataRequest.html) `PutMetricDataRequest`Devono includere lo spazio dei nomi personalizzato da utilizzare per i dati e le informazioni sul punto dati stesso in un oggetto. [MetricDatum](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/MetricDatum.html)

**Nota**  
Non è possibile specificare uno spazio dei nomi che inizia con "». `AWS` I namespace che iniziano con "`AWS`" sono riservati all'uso da parte dei prodotti. Amazon Web Services 

 **Importazioni** 

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

 **Codice** 

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

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Usa le Amazon CloudWatch metriche](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/working_with_metrics.html) nella Guida per l' Amazon CloudWatch utente.
+  [AWS Namespace nella Guida per l'utente](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html). Amazon CloudWatch 
+  [PutMetricData](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricData.html)nell'API Reference. Amazon CloudWatch 

# Lavora con gli CloudWatch allarmi
<a name="examples-cloudwatch-create-alarms"></a>

## Creazione di un allarme
<a name="create-an-alarm"></a>

Per creare un allarme basato su una CloudWatch metrica, chiama il `putMetricAlarm` metodo CloudWatchClient's con una [PutMetricAlarmRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/PutMetricAlarmRequest.html)compilazione delle condizioni di allarme.

 **Importazioni** 

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

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java) su. GitHub

## Elencare allarmi
<a name="list-alarms"></a>

Per elencare gli CloudWatch allarmi che hai creato, chiama il `describeAlarms` metodo CloudWatchClient's con un [DescribeAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsRequest.html)che puoi usare per impostare le opzioni per il risultato.

 **Importazioni** 

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

 **Codice** 

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

L'elenco degli allarmi può essere ottenuto `MetricAlarms` chiamando il comando [DescribeAlarmsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DescribeAlarmsResponse.html)che viene restituito da. `describeAlarms`

I risultati possono essere *paginati*. Per recuperare il batch di risultati successivo, chiama `nextToken` sull'oggetto di risposta e utilizza il valore del token per creare un nuovo oggetto richiesta. Quindi, chiama nuovamente il metodo `describeAlarms` con una nuova richiesta.

**Nota**  
Puoi anche recuperare gli allarmi per una metrica specifica utilizzando il metodo's. CloudWatchClient `describeAlarmsForMetric` L'uso è simile a `describeAlarms`.

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java) su. GitHub

## Eliminare allarmi
<a name="delete-alarms"></a>

Per eliminare gli CloudWatch allarmi, chiama il `deleteAlarms` metodo CloudWatchClient's [DeleteAlarmsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/model/DeleteAlarmsRequest.html)contenente uno o più nomi di allarmi che desideri eliminare.

 **Importazioni** 

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

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Uso degli Amazon CloudWatch allarmi](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) nella Guida per l' Amazon CloudWatch utente
+  [PutMetricAlarm](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_PutMetricAlarm.html)nell' Amazon CloudWatch API Reference
+  [DescribeAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)nell' Amazon CloudWatch API Reference
+  [DeleteAlarms](https://docs.aws.amazon.com//AmazonCloudWatch/latest/APIReference/API_DeleteAlarms.html)nell' Amazon CloudWatch API Reference

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

 CloudWatch Events fornisce un flusso quasi in tempo reale di eventi di sistema che descrivono le modifiche nelle AWS risorse relative a Amazon EC2 istanze, Lambda funzioni, Kinesis flussi, Amazon ECS attività, macchine a Step Functions stati, Amazon SNS argomenti, Amazon SQS code o destinazioni integrate. Puoi abbinare gli eventi e instradarli verso una o più funzioni o stream target utilizzando regole semplici.

Amazon EventBridge è l'[evoluzione](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cwe-now-eb.html) di CloudWatch Events. Entrambi i servizi utilizzano la stessa API, quindi puoi continuare a utilizzare il [client CloudWatch Events](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudwatch/CloudWatchClient.html) fornito dall'SDK o migrare all'SDK per la funzionalità [EventBridge client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/eventbridge/EventBridgeClient.html) for CloudWatch Events di Java. CloudWatch [La documentazione della Events User Guide](https://docs.aws.amazon.com/eventbridge/latest/userguide/index.html) e i [riferimenti all'API](https://docs.aws.amazon.com/eventbridge/latest/APIReference/index.html) sono ora disponibili nei siti di documentazione. EventBridge 

## Aggiunta di eventi
<a name="add-events"></a>

Per aggiungere CloudWatch eventi personalizzati, chiamate il `CloudWatchEventsClient’s` `putEvents` metodo con 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)oggetto che contiene uno o più [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)oggetti che forniscono dettagli su ogni evento. Puoi specificare diversi parametri per la voce, ad esempio l'origine e il tipo di evento, le risorse associate all'evento e così via.

**Nota**  
Puoi specificare un massimo di 10 eventi per chiamata a `putEvents`.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutEvents.java) su GitHub.

## Aggiungere regole
<a name="add-rules"></a>

Per creare o aggiornare una regola, chiamate il `CloudWatchEventsClient’s` `putRule` metodo con a [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)con il nome della regola e parametri opzionali come il [modello di evento](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html), il IAM ruolo da associare alla regola e un'[espressione di pianificazione](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html) che descriva la frequenza con cui la regola viene eseguita.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutRule.java) su. GitHub

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

I target sono le risorse che vengono invocate quando una regola viene attivata. Gli obiettivi di esempio includono Amazon EC2 istanze, Lambda funzioni, Kinesis flussi, Amazon ECS attività, macchine a Step Functions stati e destinazioni integrate.

Per aggiungere un obiettivo a una regola, chiama il `CloudWatchEventsClient’s` `putTargets` metodo [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)contenente la regola da aggiornare e un elenco di obiettivi da aggiungere alla regola.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutTargets.java) su GitHub.

## Ulteriori informazioni
<a name="more-information"></a>
+  [Aggiungere eventi con PutEvents](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html) la Amazon EventBridge User Guide
+  [Pianifica le espressioni per le regole](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html#eb-create-scheduled-rule-schedule) nella Amazon EventBridge User Guide
+  [Tipi di eventi indicati CloudWatch Events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html) nella Amazon EventBridge User Guide
+  [Modelli di eventi](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html) nella Amazon EventBridge User Guide
+  [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)nell'Amazon EventBridge API Reference
+  [PutTargets](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html)nell'Amazon EventBridge API Reference
+  [PutRule](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html)nell'Amazon EventBridge API Reference

# AWS servizi di database e AWS SDK for Java 2.x
<a name="examples-databases"></a>

AWS [offre diversi tipi di database: relazionali, chiave-valore, in memoria, documentali e molti altri.](https://aws.amazon.com/products/databases/) Il supporto dell'SDK for Java 2.x varia a seconda della natura del servizio di database in uso. AWS

Alcuni servizi di database, ad esempio il servizio [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/Welcome.html), dispongono di un APIs servizio Web per AWS la gestione della risorsa (database) e di un APIs servizio Web per interagire con i dati. [Nell'SDK for Java 2.x questi tipi di servizi dispongono di client di servizio dedicati, ad esempio Dynamo. DBClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)

Altri servizi di database dispongono di servizi Web APIs che interagiscono con la risorsa, come l'API [Amazon DocumentDB](https://docs.aws.amazon.com/documentdb/latest/developerguide/api-reference.html) (per la gestione di cluster, istanze e risorse), ma non dispongono di un'API di servizio Web per l'utilizzo dei dati. L'SDK for Java 2.x ha un'interfaccia [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html)corrispondente per lavorare con la risorsa. Tuttavia, è necessaria un'altra API Java, come [MongoDB per Java, per](https://www.mongodb.com/developer/languages/java/) lavorare con i dati.

Utilizza gli esempi seguenti per scoprire come utilizzare i client di servizio SDK for Java 2.x con i diversi tipi di database.

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


| Lavorare con i dati | Lavorare con il database | 
| --- |--- |
| Client di servizio SDK: [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | Client di servizio SDK: [DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html) | 
| Esempio: applicazione [REST React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) che utilizza DynamoDB | [CreateTableEsempi ListTables:](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb),, DeleteTable | 
| Esempi: [diversi esempi di DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) |  | 
|  | 
| --- |
| Client di servizio SDK: [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html) |  | 
| Esempio: applicazione [REST React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app) che utilizza DynamoDB |  | 
| Esempi: [diversi esempi di DynamoDB](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb) (nomi che iniziano con «Enhanced») |  | 

Vedi [altri esempi di DynamoDB](examples-dynamodb.md) nella sezione degli esempi di codice guidati di questa guida.

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


|  Lavorare con i dati  |  Lavorare con il database  | 
| --- | --- | 
| API non SDK: JDBC, versione SQL specifica del database; il codice gestisce le connessioni al database o un pool di connessioni. | Client di servizio SDK: [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Esempio: applicazione [REST React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_rds_item_tracker) che utilizza MySQL | [Esempi RdsClient :](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) diversi esempi | 

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


|  Lavorare con i dati  |  Lavorare con il database  | 
| --- | --- | 
| Client di servizio SDK: [RedshiftDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshiftdata/RedshiftDataClient.html) | Client di servizio SDK: [RedshiftClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/redshift/RedshiftClient.html) | 
| Esempi: [diversi RedshiftDataClient ](https://github.com/awsdocs/aws-doc-sdk-examples/blob/c682a07a1e6abce793e3c32ef3b9661fa723d0ff/javav2/example_code/redshift/src/main/java/com/example/scenario/RedshiftScenario.java) esempi | Esempi: [diversi RedshiftClient esempi](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/redshift/src/main/java/com/example/redshift) | 
| Esempio: applicazione [REST React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/CreatingSpringRedshiftRest) che utilizza RedshiftDataClient |  | 

## Esempi di Amazon Aurora Serverless v2
<a name="examples-db-aurora-sv1"></a>


|  Lavorare con i dati  |  Lavorare con il database  | 
| --- | --- | 
| Client di servizio SDK: [RdsDataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rdsdata/RdsDataClient.html) | Client di servizio SDK: [RdsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rds/RdsClient.html) | 
| Esempio: applicazione [REST React/Spring](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/Creating_Spring_RDS_Rest) che utilizza RdsDataClient | [Esempi: diversi esempi RdsClient ](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/rds/src/main/java/com/example/rds) | 

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


|  Lavorare con i dati  |  Lavorare con il database  | 
| --- | --- | 
| API non SDK: libreria Java specifica per MongoDB (ad esempio MongoDB per [Java); il codice gestisce le connessioni](https://www.mongodb.com/developer/languages/java/) al database o un pool di connessioni. | Client di servizio SDK: [DocDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/docdb/DocDbClient.html) | 
| Esempi: [DocumentDB (Mongo) Developer Guide](https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html#connect_programmatically-tls_enabled) (seleziona la scheda 'Java') |  | 

# Lavora con DynamoDB
<a name="examples-dynamodb"></a>

[DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) è un servizio di database NoSQL completamente gestito che offre prestazioni veloci e prevedibili con una scalabilità perfetta. Questa sezione mostra come lavorare con DynamoDB utilizzando la versione 2.x. AWS SDK per Java 

## Scegli il tuo client DynamoDB
<a name="ddb-clients-overview"></a>

L'SDK offre due approcci principali per lavorare con DynamoDB:

Client di basso livello (`DynamoDbClient`)  
Fornisce accesso diretto alle operazioni di DynamoDB con il pieno controllo su richieste e risposte. Usa questo client quando hai bisogno di un controllo preciso o lavori con schemi dinamici.

Client avanzato () `DynamoDbEnhancedClient`  
Offre una programmazione orientata agli oggetti con mappatura automatica tra oggetti Java ed elementi DynamoDB. Fornisce inoltre funzionalità orientate ai documenti per lavorare con dati simili a JSON che non seguono uno schema fisso. Utilizzate questo client quando lavorate con modelli di dati ben definiti o dati di tipo documento.

## Configurazione dei client DynamoDB
<a name="ddb-configuration-setup"></a>

Prima di lavorare con DynamoDB, configura il client per prestazioni e affidabilità ottimali.

### Comprendere il comportamento di ripetizione dei tentativi di DynamoDB
<a name="ddb-retry-behavior"></a>

I client DynamoDB utilizzano un numero massimo di tentativi predefinito di 8, che è superiore a quello degli altri client. Servizio AWS Questo numero più elevato di tentativi aiuta a gestire la natura distribuita di DynamoDB e i limiti temporanei di capacità. Per ulteriori informazioni sulle strategie di ripetizione dei tentativi, consulta. [Configurare il comportamento dei tentativi in AWS SDK for Java 2.x](retry-strategy.md)

### Ottimizza le prestazioni con endpoint basati su account
<a name="ddb-account-based-endpoints-v2"></a>

DynamoDB [AWS offre endpoint basati su account](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.SDKOverview.html#Programming.SDKs.endpoints) che migliorano le prestazioni utilizzando l'ID dell'account per semplificare AWS il routing delle richieste. 

Per utilizzare questa funzionalità, è necessaria la versione 2.28.4 o successiva di. AWS SDK for Java 2.x Puoi trovare l'ultima versione nel repository centrale di [Maven](https://central.sonatype.com/artifact/software.amazon.awssdk/bom/versions). Le versioni SDK supportate utilizzano automaticamente i nuovi endpoint.

Per disattivare il routing basato sull'account, scegli una di queste opzioni:
+ Configurare un client `AccountIdEndpointMode` di servizio DynamoDB con set to. `DISABLED`
+ Imposta una variabile di ambiente.
+ Imposta una proprietà del sistema JVM.
+ Aggiorna l'impostazione del file di AWS configurazione condiviso.

L'esempio seguente mostra come disabilitare il routing basato sull'account configurando un client di servizio DynamoDB:

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

Per ulteriori informazioni sulle altre opzioni di configurazione, consulta Endpoint [basati su account](https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html) nella and Tools Reference Guide. AWS SDKs 

## Cosa viene trattato in questo argomento
<a name="ddb-topics-overview"></a>

Le seguenti sezioni mostrano come lavorare con DynamoDB:
+ [Lavora con le tabelle in DynamoDB](examples-dynamodb-tables.md)- Creare, descrivere, aggiornare ed eliminare tabelle
+ [Lavora con gli elementi in DynamoDB](examples-dynamodb-items.md)- Aggiungi, recupera e aggiorna singoli elementi
+ [Mappa gli oggetti Java sugli elementi DynamoDB con AWS SDK for Java 2.x](dynamodb-enhanced-client.md)- Utilizza la mappatura degli oggetti e i dati orientati ai documenti con Enhanced Client

Per ulteriori esempi di codice DynamoDB, consulta Esempi di codice [DynamoDB nella Code Examples Library](java_dynamodb_code_examples.md). AWS 

# Lavora con le tabelle in DynamoDB
<a name="examples-dynamodb-tables"></a>

Le tabelle sono i contenitori per tutti gli elementi di un DynamoDB database. Prima di poter aggiungere o rimuovere dati da DynamoDB, è necessario creare una tabella.

Per ogni tabella, devi definire:
+ Un *nome* di tabella unico per il tuo account e la tua regione.
+ Una *chiave primaria* per la quale ogni valore deve essere univoco; due item nella tabella non possono avere lo stesso valore della chiave primaria.

  La chiave primaria può essere *semplice*, costituita da una singola chiave di partizione (HASH), o *composita*, costituita da una chiave di partizione e una di ordinamento (RANGE).

  A ogni valore chiave è associato un *tipo di dati*, enumerato dalla classe. [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) Il valore della chiave può essere binario (B), numerico (N) o una stringa (S). Per ulteriori informazioni, consulta [Regole di denominazione e tipi di dati](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) nella Guida per gli sviluppatori. Amazon DynamoDB 
+  Il *throughput assegnato* è costituito da valori che definiscono il numero di unità di capacità di lettura/scrittura prenotati per la tabella.
**Nota**  
 [Amazon DynamoDB i prezzi](https://aws.amazon.com/dynamodb/pricing/) si basano sui valori di throughput assegnati che imposti sulle tabelle, quindi prenota solo la capacità che ritieni necessaria per la tabella.

  Il throughput assegnato per una tabella può essere modificato in qualsiasi momento, pertanto puoi modificare la capacità in base alle esigenze.

## Creare una tabella
<a name="dynamodb-create-table"></a>

Usa il `DynamoDbClient’s` `createTable` metodo per creare una nuova DynamoDB tabella. È necessario costruire gli attributi della tabella e uno schema della tabella, entrambi utilizzati per identificare la chiave primaria della tabella. Inoltre, occorre fornire i valori del throughput assegnato iniziali e un nome della tabella.

**Nota**  
Se esiste già una tabella con il nome scelto, `[DynamoDbException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)` viene generata a.

### Creazione di una tabella con una chiave primaria semplice
<a name="dynamodb-create-table-simple"></a>

Questo codice crea una tabella con un attributo che è la chiave primaria semplice della tabella. l'esempio utilizza `[AttributeDefinition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeDefinition.html)` e `[KeySchemaElement](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/KeySchemaElement.html)` oggetti per. [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)

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java) su. GitHub

### Creazione di una tabella con una chiave primaria composita
<a name="dynamodb-create-table-composite"></a>

L'esempio seguente crea una tabella con due attributi. Entrambi gli attributi vengono utilizzati per la chiave primaria composita.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTableCompositeKey.java) su GitHub.

## Elencare tabelle
<a name="dynamodb-list-tables"></a>

È possibile elencare le tabelle in una particolare regione chiamando il `DynamoDbClient’s` `listTables` metodo.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, [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)viene generata a.

 **Importazioni** 

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

 **Codice** 

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

Per impostazione predefinita, vengono restituite fino a 100 tabelle per chiamata: da utilizzare `lastEvaluatedTableName` sull'[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)oggetto restituito per ottenere l'ultima tabella valutata. Puoi utilizzare questo valore per avviare la visualizzazione dell'elenco dopo l'ultimo valore restituito dalla visualizzazione dell'elenco precedente.

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/ListTables.java) su. GitHub

## Descrizione di (recupero delle informazioni su) una tabella
<a name="dynamodb-describe-table"></a>

Utilizzate il `DynamoDbClient’s` `describeTable` metodo per ottenere informazioni su una tabella.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, [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)viene generata a.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DescribeTable.java) su. GitHub

## Modifica (aggiornamento) di una tabella
<a name="dynamodb-update-table"></a>

È possibile modificare i valori di throughput assegnati alla tabella in qualsiasi momento chiamando il `DynamoDbClient’s` `updateTable` metodo.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)viene generata a.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateTable.java) su. GitHub

## Eliminazione di una tabella
<a name="dynamodb-delete-table"></a>

Per eliminare una tabella, chiama `DynamoDbClient’s` `deleteTable` method e fornisci il nome della tabella.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)viene generata a.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteTable.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Linee guida per l'utilizzo delle tabelle](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html) nella Guida per Amazon DynamoDB gli sviluppatori
+  [Utilizzo delle tabelle DynamoDB nella](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html) Guida per gli Amazon DynamoDB sviluppatori

# Lavora con gli elementi in DynamoDB
<a name="examples-dynamodb-items"></a>

*In DynamoDB, un elemento è una raccolta di *attributi*, ognuno dei quali ha un *nome* e un valore.* Un valore attributo può essere un tipo scalare, set o documento. Per ulteriori informazioni, consulta [Regole di denominazione e tipi di dati](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) nella Guida per gli Amazon DynamoDB sviluppatori.

## Recuperare (ottenere) un item da una tabella
<a name="dynamodb-get-item"></a>

Chiama il `getItem` metodo DynamoDbClient's e passagli un [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)oggetto con il nome della tabella e il valore della chiave primaria dell'elemento desiderato. Restituisce un [GetItemResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemResponse.html)oggetto con tutti gli attributi di quell'elemento. Puoi specificare una o più [espressioni di proiezione](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) in `GetItemRequest` per recuperare attributi specifici.

È possibile utilizzare il `item()` metodo dell'`GetItemResponse`oggetto restituito per recuperare una [mappa](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) di coppie chiave (String [AttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html)) e valore () associate all'elemento.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/GetItem.java) su. GitHub

## Recupero (Get) di una voce da una tabella utilizzando il client asincrono
<a name="id1ddb"></a>

Invocate il `getItem` metodo di DynamoDbAsyncClient e passategli un [GetItemRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/GetItemRequest.html)oggetto con il nome della tabella e il valore della chiave primaria dell'elemento desiderato.

È possibile restituire un'istanza di [raccolta](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html) con tutti gli attributi per tale voce (fare riferimento all'esempio seguente).

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/bc964a243276990f05c180618ea8b34777c68f0e/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/DynamoDBAsyncGetItem.java) su. GitHub

## Aggiunta di un nuovo item a una tabella
<a name="dynamodb-add-item"></a>

Creare una [mappa](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Map.html) di coppie chiave-valore che rappresentino gli attributi della voce. Queste devono includere valori per i campi chiave primaria della tabella. Se l'elemento identificato dalla chiave primaria esiste già, i relativi campi vengono *aggiornati* dalla richiesta.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)viene generata a.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/PutItem.java) su. GitHub

## Aggiornamento di un item esistente in una tabella
<a name="dynamodb-update-item"></a>

È possibile aggiornare un attributo per una voce che esiste già in una tabella utilizzando il metodo `updateItem` di DynamoDbClient, fornendo un nome di tabella, un valore chiave primaria e una mappa di campi da aggiornare.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, o se l'elemento identificato dalla chiave primaria che hai passato non esiste, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)viene generato a.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/UpdateItem.java) su. GitHub

## Aggiornamento di una voce (item) esistente in una tabella
<a name="dynamodb-delete-item"></a>

È possibile eliminare un elemento esistente in una tabella utilizzando il `deleteItem` metodo DynamoDbClient's e fornendo un nome di tabella oltre al valore della chiave primaria.

**Nota**  
Se la tabella denominata non esiste per il tuo account e la tua regione, o se l'elemento identificato dalla chiave primaria che hai passato non esiste, [ResourceNotFoundException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/ResourceNotFoundException.html)viene generato un.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f4eaf2b2971805cfb2b87a8e5ab408f83169432e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/DeleteItem.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Linee guida per l'utilizzo degli elementi](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/best-practices.html) nella Guida per gli Amazon DynamoDB sviluppatori
+  [Utilizzo degli elementi contenuti DynamoDB nella](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/WorkingWithItems.html) Guida per gli Amazon DynamoDB sviluppatori

# Mappa gli oggetti Java sugli elementi DynamoDB con 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) è una libreria di alto livello che è il successore della classe di SDK for `DynamoDBMapper` Java v1.x. Offre un modo semplice per mappare le classi lato client alle tabelle DynamoDB. Le relazioni tra le tabelle e le classi di dati corrispondenti vengono definite nel codice. Dopo aver definito queste relazioni, è possibile eseguire in modo intuitivo varie operazioni di creazione, lettura, aggiornamento o eliminazione (CRUD) su tabelle o elementi in DynamoDB.

L'API Enhanced Client di DynamoDB include anche [l'API Enhanced Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) che consente di lavorare con elementi di tipo documento che non seguono uno schema definito. 

**Topics**
+ [Inizia a usare l'API DynamoDB Enhanced Client](ddb-en-client-getting-started.md)
+ [Scopri le basi dell'API DynamoDB Enhanced Client](ddb-en-client-use.md)
+ [Usa funzionalità di mappatura avanzate](ddb-en-client-adv-features.md)
+ [Lavora con documenti JSON con l'API Enhanced Document per DynamoDB](ddb-en-client-doc-api.md)
+ [Usa le estensioni per personalizzare le operazioni di DynamoDB Enhanced Client](ddb-en-client-extensions.md)
+ [Usa l'API DynamoDB Enhanced Client in modo asincrono](ddb-en-client-async.md)
+ [Annotazioni di classi di dati](ddb-en-client-anno-index.md)

# Inizia a usare l'API DynamoDB Enhanced Client
<a name="ddb-en-client-getting-started"></a>

Il seguente tutorial presenta le nozioni di base necessarie per lavorare con l'API DynamoDB Enhanced Client.

## Aggiungi dipendenze
<a name="ddb-en-client-gs-dep"></a>

Per iniziare a utilizzare l'API DynamoDB Enhanced Client nel tuo progetto, aggiungi una dipendenza dall'artefatto Maven. `dynamodb-enhanced` Questo è illustrato negli esempi seguenti. 

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

Esegui una ricerca nell'archivio centrale di Maven per la [versione più recente](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) e sostituiscila *<VERSION>* con questo valore.

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

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

Esegui una ricerca nell'archivio centrale di Maven per la [versione più recente](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) e sostituiscila con questo valore. *<VERSION>*

------

# Genera un `TableSchema` da una classe di dati
<a name="ddb-en-client-gs-tableschema"></a>

A `[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)` consente al client avanzato di mappare i valori degli attributi DynamoDB da e verso le classi lato client. In questo tutorial, imparerai a conoscere `TableSchema` i file derivati da una classe di dati statici e generati dal codice utilizzando un builder.

## Usa una classe di dati annotata
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

L'SDK for Java 2.x include [un set di](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html) annotazioni che è possibile utilizzare con una classe di dati per generare `TableSchema` rapidamente un file per mappare le classi alle tabelle.

[Inizia creando una classe di dati conforme alle specifiche. JavaBean ](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf) La specifica richiede che una classe disponga di un costruttore pubblico senza argomenti e che disponga di getter e setter per ogni attributo della classe. Includi un'annotazione a livello di classe per indicare che la classe di dati è una. `DynamoDbBean` Inoltre, includi almeno un'`DynamoDbPartitionKey`annotazione sul getter o setter per l'attributo chiave primaria. 

È possibile applicare [annotazioni a livello di attributo a](ddb-en-client-anno-index.md) getter o setter, ma non a entrambi.

**Nota**  
Il termine `property` viene normalmente utilizzato per un valore incapsulato in un. JavaBean Tuttavia, questa guida utilizza `attribute` invece il termine, per coerenza con la terminologia utilizzata da DynamoDB.

La `Customer` classe seguente mostra le annotazioni che collegano la definizione della classe a una tabella 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 + "]";
    }
}
```

Dopo aver creato una classe di dati annotata, usatela per creare la`TableSchema`, come mostrato nel seguente frammento.

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

A `TableSchema` è progettato per essere statico e immutabile. Di solito puoi istanziarlo al momento del caricamento della classe.

Il metodo static `TableSchema.fromBean()` factory analizza il bean per generare la mappatura degli attributi (proprietà) delle classi di dati da e verso gli attributi DynamoDB.

Per un esempio di utilizzo di un modello di dati composto da diverse classi di dati, consultate la classe nella `Person` sezione. [Lavora con attributi che sono bean, mappe, elenchi e set](ddb-en-client-adv-features-nested.md)

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

Puoi saltare il costo dell'introspezione dei bean se definisci lo schema della tabella nel codice. Se codifichi lo schema, la tua classe non ha bisogno di seguire gli standard di JavaBean denominazione né di essere annotata. L'esempio seguente utilizza un generatore ed è equivalente all'esempio di `Customer` classe che utilizza le annotazioni.

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

# Crea un client avanzato e `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## Crea un client avanzato
<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, o la sua controparte asincrona [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html), è il punto di partenza per lavorare con l'API DynamoDB Enhanced Client.

Il client avanzato richiede uno standard per eseguire il lavoro. `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)` L'API offre due modi per creare un'`DynamoDbEnhancedClient`istanza. La prima opzione, mostrata nel frammento seguente, crea uno standard `DynamoDbClient` con le impostazioni predefinite raccolte dalle impostazioni di configurazione.

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

Se desideri configurare il client standard sottostante, puoi fornirlo al metodo builder del client avanzato, come mostrato nel seguente frammento.

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

## Creazione di un'Istanza `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

Pensate 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)come alla rappresentazione lato client di una tabella DynamoDB che utilizza la funzionalità di mappatura fornita da a. `TableSchema` La `DynamoDbTable` classe fornisce metodi per le operazioni CRUD che consentono di interagire con una singola tabella DynamoDB.

`DynamoDbTable<T>`è una classe generica che accetta un argomento di tipo singolo, sia che si tratti di una classe personalizzata o di un argomento `EnhancedDocument` quando si lavora con elementi di tipo documento. Questo tipo di argomento stabilisce la relazione tra la classe utilizzata e la singola tabella DynamoDB.

Utilizzate il metodo `table()` factory di `DynamoDbEnhancedClient` per creare un'`DynamoDbTable`istanza, come mostrato nel frammento seguente.

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

`DynamoDbTable`le istanze sono candidate per essere utilizzate singleton perché sono immutabili e possono essere utilizzate in tutta l'applicazione.

Il codice ora ha una rappresentazione in memoria di una tabella DynamoDB che può funzionare con le istanze. `Customer` La tabella DynamoDB effettiva potrebbe esistere o meno. Se la tabella denominata esiste `Customer` già, puoi iniziare a eseguire operazioni CRUD su di essa. Se non esiste, utilizzate l'`DynamoDbTable`istanza per creare la tabella come illustrato nella sezione successiva.

# Se necessario, creare una tabella DynamoDB
<a name="ddb-en-client-gs-ddbtable"></a>

Dopo aver creato un'`DynamoDbTable`istanza, utilizzala per creare una *sola volta* una tabella in DynamoDB.

## Crea un codice di esempio per la tabella
<a name="ddb-en-client-gs-ddbtable-createex"></a>

L'esempio seguente crea una tabella DynamoDB basata sulla `Customer` classe di dati. 

Questo esempio crea una tabella DynamoDB con il `Customer` nome, identico al nome della classe, ma il nome della tabella può essere qualcos'altro. Qualunque sia il nome dato alla tabella, è necessario utilizzare questo nome in altre applicazioni per lavorare con la tabella. Fornite questo nome al `table()` metodo ogni volta che create un altro `DynamoDbTable` oggetto per lavorare con la tabella DynamoDB sottostante.

[Il parametro Java lambda`builder`, passato al `createTable` metodo consente di personalizzare la tabella.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) In questo esempio, viene configurato il [throughput assegnato](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual). Se desideri utilizzare le impostazioni predefinite quando crei una tabella, salta il generatore, come mostrato nel frammento seguente.

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

Quando vengono utilizzate le impostazioni predefinite, i valori per il throughput assegnato non vengono impostati. [Al contrario, la modalità di fatturazione per la tabella è impostata su richiesta.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand)

L'esempio utilizza anche un `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)` prima di tentare di stampare il nome della tabella ricevuto nella risposta. La creazione di una tabella richiede del tempo. Pertanto, l'utilizzo di un cameriere significa che non è necessario scrivere una logica che interroghi il servizio DynamoDB per verificare se la tabella esiste prima di utilizzarla.

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

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

**Nota**  
I nomi degli attributi di una tabella DynamoDB iniziano con una lettera minuscola quando la tabella viene generata da una classe di dati. Se desideri che il nome dell'attributo della tabella inizi con una lettera maiuscola, usa l'[`@DynamoDbAttribute(NAME)`annotazione](ddb-en-client-adv-features-inex-attr.md) e fornisci il nome che desideri come parametro.

# Esegui operazioni
<a name="ddb-en-client-gs-use"></a>

Dopo aver creato la tabella, utilizzate l'`DynamoDbTable`istanza per eseguire operazioni sulla tabella DynamoDB. 

Nell'esempio seguente, un singleton `DynamoDbTable<Customer>` viene passato come parametro insieme a un'istanza della [classe di `Customer` dati](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) per aggiungere un nuovo elemento alla tabella.

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

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

Prima di inviare l'`customer`oggetto al servizio DynamoDB, registrate l'output del metodo `toString()` dell'oggetto per confrontarlo con quello inviato dal client avanzato.

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

La registrazione a livello di cavo mostra il payload della richiesta generata. Il client avanzato ha generato la rappresentazione di basso livello dalla classe di dati. L'`regDate`attributo, che è un `Instant` tipo in Java, è rappresentato come una stringa DynamoDB.

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

# Lavora con una tabella esistente
<a name="ddb-en-client-gs-existingtable"></a>

La sezione precedente mostrava come creare una tabella DynamoDB a partire da una classe di dati Java. Se disponi già di una tabella esistente e desideri utilizzare le funzionalità del client avanzato, puoi creare una classe di dati Java per lavorare con la tabella. È necessario esaminare la tabella DynamoDB e aggiungere le annotazioni necessarie alla classe di dati. 

Prima di lavorare con una tabella esistente, chiamate il metodo. `DynamoDbEnhanced.table()` Ciò è stato fatto nell'esempio precedente con la seguente dichiarazione.

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

Dopo la restituzione dell'`DynamoDbTable`istanza, potete iniziare subito a lavorare con la tabella sottostante. Non è necessario ricreare la tabella chiamando il `DynamoDbTable.createTable()` metodo.

L'esempio seguente lo dimostra recuperando immediatamente un'`Customer`istanza dalla tabella 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());
```

**Importante**  
Il nome della tabella utilizzato nel `table()` metodo deve corrispondere al nome della tabella DynamoDB esistente.

# Scopri le basi dell'API DynamoDB Enhanced Client
<a name="ddb-en-client-use"></a>

[Questo argomento illustra le funzionalità di base dell'API DynamoDB Enhanced Client e la confronta con l'API client DynamoDB standard.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html)

Se non conosci l'API DynamoDB Enhanced Client, ti consigliamo di seguire il tutorial [introduttivo per familiarizzare con le](ddb-en-client-getting-started.md) classi fondamentali.

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

Le tabelle DynamoDB memorizzano gli elementi. A seconda del caso d'uso, gli elementi sul lato Java possono assumere la forma di dati strutturati staticamente o di strutture create dinamicamente. 

Se il tuo caso d'uso richiede elementi con un set coerente di attributi, usa [classi annotate](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean) o usa un [builder](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-builder) per generare i tipi statici appropriati. `TableSchema` 

In alternativa, se devi archiviare elementi costituiti da strutture diverse, crea un. `DocumentTableSchema` `DocumentTableSchema`fa parte dell'[API Enhanced Document](ddb-en-client-doc-api.md) e richiede solo una chiave primaria tipizzata staticamente e funziona con le `EnhancedDocument` istanze per contenere gli elementi di dati. [L'API Enhanced Document è trattata in un altro argomento.](ddb-en-client-doc-api.md)

## Tipi di attributi per le classi del modello di dati
<a name="ddb-en-client-use-types"></a>

Sebbene DynamoDB [supporti un numero limitato di tipi di attributi rispetto al rich type system di](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) Java, l'API DynamoDB Enhanced Client fornisce meccanismi per convertire i membri di una classe Java da e verso i tipi di attributi DynamoDB.

I tipi di attributi (proprietà) delle classi di dati Java devono essere tipi di oggetti, non primitivi. Ad esempio, utilizzate `Long` sempre tipi di dati `Integer` oggetto, non `long` e `int` primitivi.

[Per impostazione predefinita, l'API DynamoDB Enhanced Client supporta convertitori di attributi per un gran numero di tipi, [come Integer[,](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html) String](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html) e Instant. [BigDecimal](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/BigDecimalAttributeConverter.html)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/InstantAsStringAttributeConverter.html) L'elenco viene visualizzato nelle [classi di implementazione note](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html) dell'interfaccia. AttributeConverter L'elenco include molti tipi e raccolte come mappe, elenchi e set.

Per memorizzare i dati per un tipo di attributo che non è supportato di default o non è conforme alla JavaBean convenzione, puoi scrivere un'`AttributeConverter`implementazione personalizzata per eseguire la conversione. Vedi la sezione sulla conversione degli attributi per un [esempio](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example).

Per memorizzare i dati per un tipo di attributo la cui classe è conforme alla specifica Java beans (o una [classe di dati immutabile](ddb-en-client-use-immut.md)), puoi adottare due approcci. 
+ Se avete accesso al file sorgente, potete annotare la classe con `@DynamoDbBean` (o). `@DynamoDbImmutable` La sezione che illustra gli attributi annidati mostra [esempi](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-anno) di utilizzo di classi annotate.
+ Se non hai accesso al file sorgente della classe di JavaBean dati per l'attributo (o non vuoi annotare il file sorgente di una classe a cui hai accesso), puoi usare l'approccio builder. Questo crea uno schema tabellare senza definire le chiavi. Quindi, puoi annidare questo schema di tabella all'interno di un altro schema di tabella per eseguire la mappatura. La sezione degli attributi nidificati contiene un [esempio](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-map-builder) che mostra l'uso di schemi nidificati.

### Valori nulli
<a name="ddb-en-client-use-types-nulls"></a>

Quando si utilizza il `putItem` metodo, il client avanzato non include gli attributi con valori nulli di un oggetto dati mappato nella richiesta a DynamoDB.

Il comportamento predefinito dell'SDK per `updateItem` le richieste rimuove gli attributi dall'elemento in DynamoDB che sono impostati su null nell'oggetto inviato nel metodo. `updateItem` Se intendi aggiornare alcuni valori degli attributi e mantenere invariati gli altri, hai due opzioni.
+ Recuperate l'elemento (utilizzando`getItem`) prima di apportare modifiche ai valori. Utilizzando questo approccio, l'SDK invia tutti i valori vecchi e aggiornati a DynamoDB.
+ Usa `[IgnoreNullsMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/IgnoreNullsMode.html).SCALAR_ONLY` o `IgnoreNullsMode.MAPS_ONLY` quando crei la richiesta per aggiornare l'elemento. Entrambe le modalità ignorano le proprietà con valori nulli nell'oggetto che rappresentano gli attributi scalari in DynamoDB. L'[Aggiorna gli elementi che contengono tipi complessi](ddb-en-client-adv-features-nested.md#ddb-en-client-adv-features-nested-updates)argomento di questa guida contiene ulteriori informazioni sui `IgnoreNullsMode` valori e su come lavorare con tipi complessi.

L'esempio seguente illustra `ignoreNullsMode()` il `updateItem()` metodo.

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

## Metodi di base di DynamoDB Enhanced Client
<a name="ddb-en-client-use-basic-ops"></a>

I metodi di base del client avanzato si associano alle operazioni del servizio DynamoDB da cui prendono il nome. Gli esempi seguenti mostrano la variante più semplice di ciascun metodo. È possibile personalizzare ogni metodo passando un oggetto di richiesta avanzato. Gli oggetti di richiesta avanzati offrono la maggior parte delle funzionalità disponibili nel client DynamoDB standard. Sono completamente documentati nell'API Reference. AWS SDK for Java 2.x 

L'esempio utilizza quanto [Classe `Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) mostrato in precedenza.

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

## Confronta DynamoDB Enhanced Client con il client DynamoDB standard
<a name="ddb-en-client-use-compare"></a>

[Entrambi i APIs client DynamoDB, standard [e](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/package-summary.html) avanzato, consentono di lavorare con le tabelle DynamoDB per eseguire operazioni CRUD (creazione, lettura, aggiornamento ed eliminazione) a livello di dati.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/package-summary.html) La differenza tra i client sta nel modo in cui ciò viene realizzato. APIs Utilizzando il client standard, si lavora direttamente con attributi di dati di basso livello. L'API client avanzata utilizza classi Java familiari e si collega all'API di basso livello dietro le quinte.

Sebbene entrambi i client APIs supportino operazioni a livello di dati, il client DynamoDB standard supporta anche operazioni a livello di risorsa. Le operazioni a livello di risorsa gestiscono il database, come la creazione di backup, l'elenco delle tabelle e l'aggiornamento delle tabelle. L'API client avanzata supporta un numero selezionato di operazioni a livello di risorsa come la creazione, la descrizione e l'eliminazione di tabelle.

Per illustrare i diversi approcci utilizzati dai due client APIs, i seguenti esempi di codice mostrano la creazione della stessa `ProductCatalog` tabella utilizzando il client standard e il client avanzato.

### Confronto: crea una tabella utilizzando il 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))
);
```

### Confronta: crea una tabella utilizzando il DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs2"></a>

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

Il client avanzato utilizza la seguente classe di dati annotati. Il DynamoDB Enhanced Client mappa i tipi di dati Java ai tipi di dati DynamoDB per un codice meno dettagliato e più facile da seguire. `ProductCatalog`è un esempio di utilizzo di una classe immutabile con DynamoDB Enhanced Client. [L'uso delle classi Immutabili per le classi di dati mappate viene discusso più avanti in questo argomento.](ddb-en-client-use-immut.md)

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

I due esempi di codice seguenti di scrittura in batch illustrano la verbosità e la mancanza di sicurezza dei tipi quando si utilizza il client standard anziché il client avanzato.

### Confronto: Scrittura in batch utilizzando il 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());
    }
```

### Confronto: Scrittura in batch utilizzando il DynamoDB Enhanced Client
<a name="ddb-en-client-use-compare-cs5"></a>

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

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

# Lavora con classi di dati immutabili
<a name="ddb-en-client-use-immut"></a>

La funzionalità di mappatura dell'API DynamoDB Enhanced Client funziona con classi di dati immutabili. Una classe immutabile ha solo getter e richiede una classe builder che l’SDK utilizza per creare istanze della classe. Invece di utilizzare l'`@DynamoDbBean`annotazione come mostrato nella [classe Customer](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust), le classi immutabili utilizzano l'`@DynamoDbImmutable`annotazione, che accetta un parametro che indica la classe builder da utilizzare.

La classe seguente è una versione immutabile di. `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); }
    }
}
```

È necessario soddisfare i seguenti requisiti quando si annota una classe di dati con. `@DynamoDbImmutable`

1. Ogni metodo che non sostituisce `Object.class` e con cui non è stato annotato `@DynamoDbIgnore` deve essere un getter per un attributo della tabella DynamoDB.

1. Ogni getter deve avere un setter corrispondente con distinzione tra maiuscole e minuscole nella classe builder.

1. Deve essere soddisfatta solo una delle seguenti condizioni di costruzione.
   + La classe builder deve avere un costruttore pubblico predefinito.
   + La classe di dati deve avere un metodo statico pubblico denominato `builder()` che non accetta parametri e restituisce un'istanza della classe builder. Questa opzione è mostrata nella classe immutable`Customer`.

1.  La classe builder deve avere un metodo pubblico denominato `build()` che non accetta parametri e restituisce un'istanza della classe immutabile. 

Per crearne uno `TableSchema` per la tua classe immutabile, usa il `fromImmutableClass()` metodo on `TableSchema` come mostrato nel seguente frammento.

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

Proprio come è possibile creare una tabella DynamoDB da una classe mutabile, è possibile crearne una da una classe immutabile con *una* chiamata singola a of, come illustrato nel seguente esempio `DynamoDbTable` di `createTable()` snippet.

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

## Usa librerie di terze parti, come Lombok
<a name="ddb-en-client-use-immut-lombok"></a>

Le librerie di terze parti, come [Project Lombok](https://projectlombok.org/), aiutano a generare codice standard associato a oggetti immutabili. L'API DynamoDB Enhanced Client funziona con queste librerie purché le classi di dati seguano le convenzioni descritte in questa sezione. 

L'esempio seguente mostra la classe immutabile `CustomerImmutable` con annotazioni Lombok. Nota come la `onMethod` funzionalità di Lombok copia le annotazioni DynamoDB basate su attributi, ad esempio, sul codice generato. `@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;
}
```

# Usa espressioni e condizioni
<a name="ddb-en-client-expressions"></a>

[Le espressioni nell'API DynamoDB Enhanced Client sono rappresentazioni Java delle espressioni DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html)

L'API DynamoDB Enhanced Client utilizza tre tipi di espressioni:

[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)  
La `Expression` classe viene utilizzata quando si definiscono condizioni e filtri.

[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)  
Questo tipo di espressione rappresenta [le condizioni chiave per le](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions) operazioni di interrogazione.

[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)  
Questa classe consente di scrivere espressioni di [aggiornamento di DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) ed è attualmente utilizzata nel framework di estensione quando si aggiorna un elemento.

## Anatomia delle espressioni
<a name="ddb-en-client-expressions-compoonents"></a>

Un'espressione è composta dai seguenti elementi:
+ Un'espressione stringa (obbligatoria). La stringa contiene un'espressione logica DynamoDB con nomi segnaposto per i nomi e i valori degli attributi.
+ Una mappa dei valori delle espressioni (in genere richiesta).
+ Una mappa dei nomi delle espressioni (opzionale).

Utilizzate un builder per generare un `Expression` oggetto che assuma la seguente forma generale.

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

`Expression`Di solito richiede una mappa di valori di espressione. La mappa fornisce i valori per i segnaposto nell'espressione stringa. La chiave della mappa è costituita dal nome del segnaposto preceduto da due punti (`:`) e il valore della mappa è un'istanza di. [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 dispone di metodi pratici per generare un'`AttributeValue`istanza da un valore letterale. In alternativa, è possibile utilizzare il `AttributeValue.Builder` per generare un'`AttributeValue`istanza.

Il seguente frammento mostra una mappa con due voci dopo la riga di commento 2. La stringa passata al `expression()` metodo, mostrata dopo la riga di commento 1, contiene i segnaposto che DynamoDB risolve prima di eseguire l'operazione. *Questo frammento non contiene una mappa di nomi di espressioni, perché price è un nome di attributo consentito.*

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

Se il nome di un attributo nella tabella DynamoDB è una parola riservata, inizia con un numero o contiene uno spazio, è necessaria una mappa dei nomi delle espressioni per. `Expression`

Ad esempio, se il nome dell'attributo era `1price` al posto dell'`price`esempio di codice precedente, l'esempio dovrebbe essere modificato come mostrato nell'esempio seguente.

```
        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 segnaposto per il nome di un'espressione inizia con il simbolo del cancelletto ()`#`. Una voce per la mappa dei nomi delle espressioni utilizza il segnaposto come chiave e il nome dell'attributo come valore. La mappa viene aggiunta al generatore di espressioni con il metodo. `expressionNames()` DynamoDB risolve il nome dell'attributo prima di eseguire l'operazione.

I valori di espressione non sono necessari se una funzione viene utilizzata nell'espressione stringa. Un esempio di funzione di espressione è`attribute_exists(<attribute_name>)`.

L'esempio seguente crea un file `Expression` che utilizza una funzione [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions). La stringa di espressione in questo esempio non utilizza segnaposto. Questa espressione può essere utilizzata in un'`putItem`operazione per verificare se nel database esiste già un elemento con un valore dell'`movie`attributo uguale all'attributo dell'`movie`oggetto dati.

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

La DynamoDB Developer Guide contiene informazioni complete sulle espressioni di [basso livello utilizzate](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html) con DynamoDB.

## Espressioni condizionali e condizionali
<a name="ddb-en-client-expressions-cond"></a>

Quando si utilizzano i `deleteItem()` metodi`putItem()`,`updateItem()`, e anche quando si utilizzano operazioni di transazione e batch, si utilizzano `[Expression](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html)` oggetti per specificare le condizioni che DynamoDB deve soddisfare per procedere con l'operazione. Queste espressioni sono denominate espressioni condizionali. Per un esempio, vedi l'espressione di condizione utilizzata nel `addDeleteItem()` metodo (dopo la riga di commento 1) dell'[esempio di transazione](ddb-en-client-use-multiop-trans.md#ddb-en-client-use-multiop-trans-writeitems-opcondition) mostrato in questa guida.

Quando si utilizzano i `query()` metodi, una condizione viene espressa come a [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html). La `QueryConditional` classe dispone di diversi metodi statici di convenienza che aiutano a scrivere i criteri che determinano quali elementi leggere da DynamoDB.

Per alcuni esempi di`QueryConditionals`, consultate il primo esempio di codice della [`Query`esempi di metodi](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-query-example) sezione di questa guida.

## Espressioni filtro
<a name="ddb-en-client-expressions-filter"></a>

Le espressioni di filtro vengono utilizzate nelle operazioni di scansione e interrogazione per filtrare gli elementi restituiti. 

Un'espressione di filtro viene applicata dopo che tutti i dati sono stati letti dal database, quindi il costo di lettura è lo stesso che se non ci fosse alcun filtro. [La *Amazon DynamoDB Developer* Guide contiene ulteriori informazioni sull'uso delle espressioni di filtro per le operazioni di interrogazione [e scansione](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression).](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.FilterExpression)

L'esempio seguente mostra un'espressione di filtro aggiunta a una richiesta di scansione. I criteri limitano gli articoli restituiti agli articoli con un prezzo compreso tra 8,00 e 80,00€ inclusi.

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

## Espressioni di aggiornamento
<a name="ddb-en-client-expressions-update"></a>

Il metodo di DynamoDB Enhanced Client `updateItem()` fornisce un modo standard per aggiornare gli elementi in DynamoDB. [Tuttavia, quando hai bisogno di maggiori funzionalità, [UpdateExpressions](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/update/UpdateExpression.html)fornisci una rappresentazione sicura dei tipi della sintassi delle espressioni di aggiornamento di DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html) Ad esempio, è possibile utilizzare `UpdateExpressions` per aumentare i valori senza prima leggere elementi da DynamoDB o aggiungere singoli membri a un elenco. Le espressioni di aggiornamento sono attualmente disponibili nelle estensioni personalizzate per il `updateItem()` metodo.

Per un esempio che utilizza le espressioni di aggiornamento, consultate l'[esempio di estensione personalizzata](ddb-en-client-extensions-custom.md) in questa guida.

Ulteriori informazioni sulle espressioni di aggiornamento sono disponibili nella [Amazon DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html).

# Lavora con risultati impaginati: scansioni e interrogazioni
<a name="ddb-en-client-use-multirecord"></a>

*I `scan` `batch` metodi `query` e dell'API DynamoDB Enhanced Client restituiscono risposte con una o più pagine.* Una pagina contiene uno o più elementi. Il codice può elaborare la risposta per pagina o elaborare singoli elementi.

Una risposta impaginata restituita dal client sincrono restituisce un [PageIterable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PageIterable.html)oggetto, mentre una risposta restituita dal `DynamoDbEnhancedClient` client asincrono restituisce un oggetto. `DynamoDbEnhancedAsyncClient` [PagePublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PagePublisher.html)

Questa sezione esamina l'elaborazione dei risultati impaginati e fornisce esempi che utilizzano la scansione e l'interrogazione. APIs

## Esegui la scansione di una tabella
<a name="ddb-en-client-use-multirecord-scan"></a>

Il [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))metodo dell'SDK corrisponde all'operazione [DynamoDB con lo stesso nome](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html). L'API DynamoDB Enhanced Client offre le stesse opzioni, ma utilizza un modello a oggetti familiare e gestisce l'impaginazione al posto tuo.

Innanzitutto, esploriamo l'`PageIterable`interfaccia esaminando il `scan` metodo della classe di mappatura sincrona,. [DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)

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

L'esempio seguente mostra il `scan` metodo che utilizza un'[espressione](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html) per filtrare gli elementi restituiti. [ProductCatalog](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)È l'oggetto modello che è stato mostrato in precedenza.

L'espressione di filtro mostrata dopo la riga di commento 2 limita gli `ProductCatalog` articoli che vengono restituiti a quelli con un valore di prezzo compreso tra 8,00 e 80,00 inclusi.

Questo esempio esclude anche `isbn` i valori utilizzando il `attributesToProject` metodo mostrato dopo la riga di commento 1.

Dopo la riga di commento 3, l'`PageIterable`oggetto,`pagedResults`, viene restituito dal `scan` metodo. Il `stream` metodo di `PageIterable` restituisce 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)oggetto, che è possibile utilizzare per elaborare le pagine. In questo esempio, il numero di pagine viene contato e registrato.

A partire dalla riga di commento 4, l'esempio mostra due varianti di accesso agli `ProductCatalog` elementi. La versione successiva alla riga di commento 4a scorre attraverso ogni pagina e ordina e registra gli elementi su ogni pagina. La versione successiva alla riga di commento 4b salta l'iterazione della pagina e accede direttamente agli elementi.

L'`PageIterable`interfaccia offre diversi modi per elaborare i risultati grazie alle sue due interfacce principali: e. [https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html) `Iterable`porta i `spliterator` metodi`forEach`, `iterator` e `SdkIterable` porta il `stream` metodo.

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

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

Il `scan` metodo asincrono restituisce i risultati come oggetto. `PagePublisher` L'`PagePublisher`interfaccia dispone di due `subscribe` metodi che è possibile utilizzare per elaborare le pagine di risposta. Un `subscribe` metodo proviene dall'interfaccia `org.reactivestreams.Publisher` principale. Per elaborare le pagine utilizzando questa prima opzione, passate un'`[Subscriber](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Subscriber.html)`istanza al `subscribe` metodo. Il primo esempio che segue mostra l'uso del `subscribe` metodo.

Il secondo `subscribe` metodo proviene dall'[SdkPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)interfaccia. Questa versione di `subscribe` accetta a [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)anziché a`Subscriber`. Questa variazione di `subscribe` metodo è illustrata nel secondo esempio che segue.

L'esempio seguente mostra la versione asincrona del `scan` metodo che utilizza la stessa espressione di filtro mostrata nell'esempio precedente. 

Dopo la riga di commento 3, `DynamoDbAsyncTable.scan` restituisce un oggetto. `PagePublisher` Nella riga successiva, il codice crea un'istanza dell'`org.reactivestreams.Subscriber`interfaccia`ProductCatalogSubscriber`, che sottoscrive la riga 4 `PagePublisher` dopo il commento.

L'`Subscriber`oggetto raccoglie gli `ProductCatalog` elementi da ogni pagina del `onNext` metodo dopo la riga di commento 8 nell'esempio di `ProductCatalogSubscriber` classe. Gli elementi sono memorizzati nella `List` variabile privata e vi si accede nel codice di chiamata con il `ProductCatalogSubscriber.getSubscribedItems()` metodo. Viene chiamato dopo la riga di commento 5.

Dopo aver recuperato l'elenco, il codice ordina tutti gli `ProductCatalog` articoli in base al prezzo e registra ogni articolo.

La `ProductCatalogSubscriber` classe [CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)in the blocca il thread chiamante fino a quando tutti gli elementi non sono stati aggiunti all'elenco prima di continuare dopo la riga di commento 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;
        }
    }
```

Il seguente esempio di frammento utilizza la versione del `PagePublisher.subscribe` metodo che accetta una riga `Consumer` successiva al commento 6. Il parametro Java lambda utilizza le pagine, che elaborano ulteriormente ogni elemento. In questo esempio, ogni pagina viene elaborata e gli elementi di ogni pagina vengono ordinati e quindi registrati.

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

Il `items` metodo di `PagePublisher` decodifica le istanze del modello in modo che il codice possa elaborare direttamente gli elementi. Questo approccio è illustrato nel frammento seguente.

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

## Eseguire una query su una tabella
<a name="ddb-en-client-use-multirecord-query"></a>

È possibile utilizzare il DynamoDB Enhanced Client per interrogare la tabella e recuperare più elementi che soddisfano criteri specifici. Il [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))metodo trova gli elementi in base ai valori della chiave primaria utilizzando le `@DynamoDbSortKey` annotazioni `@DynamoDbPartitionKey` opzionali definite nella classe di dati.

Il `query()` metodo richiede un valore di chiave di partizione e accetta facoltativamente le condizioni della chiave di ordinamento per perfezionare ulteriormente i risultati. Come l'`scan`API, le query restituiscono un `PageIterable` per le chiamate sincrone e un per le chiamate asincrone. `PagePublisher`

### `Query`esempi di metodi
<a name="ddb-en-client-use-multirecord-query-example"></a>

L'esempio di codice del `query()` metodo che segue utilizza la `MovieActor` classe. La classe di dati definisce una chiave primaria composita composta dall'**`movie`**attributo come chiave di partizione e dall'**`actor`**attributo come chiave di ordinamento. 

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

Gli esempi di codice che seguono eseguono una query sui seguenti elementi.

#### Elementi nella `MovieActor` tabella
<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'}
```

Il codice seguente definisce due `QueryConditional` istanze: `keyEqual` (dopo la riga di commento 1) e `sortGreaterThanOrEqualTo` (dopo la riga di commento 1a).

#### Interroga gli elementi per chiave di partizione
<a name="keyEqual-query-conditional-example"></a>

L'`keyEqual`istanza abbina gli elementi con un valore della chiave di partizione pari a. **`movie01`** 

Questo esempio definisce anche un'espressione di filtro dopo la riga di commento 2 che filtra qualsiasi elemento che non ha un **`actingschoolname`**valore.

`QueryEnhancedRequest`Combina la condizione chiave e l'espressione di filtro per la query.

```
    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 — Emissione utilizzando l'`keyEqual`interrogazione condizionale**  
Di seguito è riportato l'output dell'esecuzione del metodo. L'output mostra gli elementi con un `movieName` valore di **movie01** e non visualizza alcun elemento `actingSchoolName` uguale a. **`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'}
```

#### Interroga gli elementi per chiave di partizione e chiave di ordinamento
<a name="sort-type-query-conditional-example"></a>

`sortGreaterThanOrEqualTo``QueryConditional`**Perfeziona la corrispondenza della chiave di partizione (**movie01**) aggiungendo una condizione di chiave di ordinamento per valori maggiori o uguali a actor2.**

[`QueryConditional`i metodi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html) che iniziano con `sort` richiedono che il valore della chiave di partizione corrisponda e perfezionano ulteriormente la query mediante un confronto basato sul valore della chiave di ordinamento. `Sort`nel nome del metodo non significa che i risultati siano ordinati, ma che per il confronto verrà utilizzato un valore di chiave di ordinamento.

Nel frammento seguente, modifichiamo la richiesta di query mostrata in precedenza dopo la riga di commento 3. Questo frammento sostituisce la query condizionale «KeyEqual» con la query condizionale "sortGreaterThanOrEqualTo" definita dopo la riga di commento 1a. Il codice seguente rimuove anche l'espressione del filtro.

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

**Example — Emissione utilizzando la `sortGreaterThanOrEqualTo` query condizionale**  
L'output seguente mostra i risultati dell'interrogazione. **La query restituisce gli elementi con un `movieName` valore uguale a **movie01** e solo gli elementi che hanno un `actorName` valore maggiore o uguale a actor2.** Poiché rimuoviamo il filtro, la query restituisce gli elementi che non hanno alcun valore per l'attributo. `actingSchoolName`  

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

# Esegui operazioni in batch
<a name="ddb-en-client-use-multiop-batch"></a>

[L'API DynamoDB Enhanced Client offre due metodi batch [`batchGetItem`, () e (](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))

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

Con [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))questo metodo, è possibile recuperare fino a 100 singoli elementi su più tabelle in un'unica richiesta complessiva. L'esempio seguente utilizza le classi di [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)dati [`Customer`](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust)e mostrate in precedenza.

Nell'esempio dopo le righe 1 e 2, create `[ReadBatch](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ReadBatch.html)` oggetti che successivamente aggiungete come parametri al `batchGetItem()` metodo dopo la riga di commento 3. 

Il codice dopo la riga di commento 1 crea il batch da leggere dalla `Customer` tabella. Il codice dopo la riga di commento 1a mostra l'uso di un `[GetItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/GetItemEnhancedRequest.Builder.html)` builder che accetta un valore di chiave primaria e un valore di chiave di ordinamento per specificare l'elemento da leggere. Se la classe di dati ha una chiave composita, è necessario fornire sia il valore della chiave di partizione che il valore della chiave di ordinamento. 

A differenza di specificare i valori chiave per richiedere un elemento, è possibile utilizzare una classe di dati per richiedere un elemento, come mostrato dopo la riga di commento 1b. L'SDK estrae i valori chiave dietro le quinte prima di inviare la richiesta.

[Quando si specifica l'elemento utilizzando l'approccio basato su chiavi, come mostrato nelle due istruzioni successive a 2a, è anche possibile specificare che DynamoDB deve eseguire una lettura fortemente coerente.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html) Quando viene utilizzato, il `consistentRead()` metodo deve essere utilizzato su tutti gli elementi richiesti per la stessa tabella.

Per recuperare gli elementi trovati da DynamoDB, utilizzate `[resultsForTable() ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#resultsForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` il metodo mostrato dopo la riga di commento 4. Chiamate il metodo per ogni tabella che è stata letta nella richiesta. `resultsForTable()`restituisce un elenco di elementi trovati che è possibile elaborare utilizzando qualsiasi `java.util.List` metodo. Questo esempio registra ogni elemento.

Per scoprire elementi che DynamoDB non ha elaborato, utilizzate l'approccio dopo la riga di commento 5. La `BatchGetResultPage` classe utilizza il `[unprocessedKeysForTable()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchGetResultPage.html#unprocessedKeysForTable(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource))` metodo che consente di accedere a ogni chiave non elaborata. Il [riferimento all'BatchGetItem API](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html) contiene ulteriori informazioni sulle situazioni che generano elementi non elaborati.

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

Si supponga che i seguenti elementi siano presenti nelle due tabelle prima di eseguire il codice di esempio.

### Elementi nelle tabelle
<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'}
```

L'output seguente mostra gli elementi restituiti e registrati dopo la riga di commento 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'}
```

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

Il `batchWriteItem()` metodo inserisce o elimina più elementi in una o più tabelle. È possibile specificare fino a 25 singole operazioni di inserimento o eliminazione nella richiesta. L'esempio seguente utilizza le classi [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)e [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)model mostrate in precedenza.

`WriteBatch`gli oggetti vengono creati dopo le righe di commento 1 e 2. Per la `ProductCatalog` tabella, il codice inserisce un elemento ed elimina un elemento. Per la `MovieActor` tabella dopo la riga di commento 2, il codice inserisce due elementi e ne elimina uno.

Il `batchWriteItem` metodo viene chiamato dopo la riga di commento 3. Il `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteItemEnhancedRequest.Builder.html)` parametro fornisce le richieste batch per ogni tabella.

L'`[BatchWriteResult](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/BatchWriteResult.html)`oggetto restituito fornisce metodi separati per ogni operazione per visualizzare le richieste non elaborate. Il codice dopo la riga di commento 4a fornisce le chiavi per le richieste di cancellazione non elaborate e il codice dopo la riga di commento 4b fornisce gli elementi put non elaborati.

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

I seguenti metodi di supporto forniscono gli oggetti del modello per le operazioni di inserimento ed eliminazione.

### Metodi di supporto
<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.     }
```

Si supponga che le tabelle contengano i seguenti elementi prima di eseguire il codice di esempio.

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

Al termine del codice di esempio, le tabelle contengono gli elementi seguenti.

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

Si noti nella `MovieActor` tabella che l'elemento del `Blue Jasmine` filmato è stato sostituito con l'elemento utilizzato nella richiesta put acquisita tramite il metodo `getMovieActorBlanchettPartial()` helper. Se non è stato fornito un valore dell'attributo data bean, il valore nel database viene rimosso. Questo è il motivo per cui il risultato `actingSchoolName` è nullo per l'elemento del `Blue Jasmine` filmato.

**Nota**  
[Sebbene la documentazione dell'API suggerisca che è possibile utilizzare espressioni condizionali e che la capacità consumata e le metriche di raccolta possano essere restituite con richieste di immissione ed [eliminazione](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/DeleteItemEnhancedRequest.html) individuali, questo non è il caso in uno scenario di scrittura in batch.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PutItemEnhancedRequest.html) Per migliorare le prestazioni delle operazioni in batch, queste singole opzioni vengono ignorate.

# Esegui operazioni di transazione
<a name="ddb-en-client-use-multiop-trans"></a>

L'API DynamoDB Enhanced Client fornisce `transactGetItems()` i metodi e. `transactWriteItems()` I metodi di transazione dell'SDK for Java forniscono atomicità, coerenza, isolamento e durabilità (ACID) nelle tabelle DynamoDB, aiutandoti a mantenere la correttezza dei dati nelle tue applicazioni.

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

Il `[transactGetItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactGetItems(java.util.function.Consumer))` metodo accetta fino a 100 richieste individuali di articoli. Tutti gli elementi vengono letti in un'unica transazione atomica. L'*Amazon DynamoDB Developer* Guide contiene informazioni sulle [condizioni che causano il fallimento di `transactGetItems()` un metodo](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txgetitems) e anche sul livello di isolamento utilizzato durante le chiamate. `[transactGetItem()](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-isolation)`

Dopo la riga di commento 1 nell'esempio seguente, il codice chiama il `transactGetItems()` metodo con un `[builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html)` parametro. Il builder `[addGetItem()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactGetItemsEnhancedRequest.Builder.html#addGetItem(software.amazon.awssdk.enhanced.dynamodb.MappedTableResource,T))` viene richiamato tre volte con un oggetto dati che contiene i valori chiave che l'SDK utilizzerà per generare la richiesta finale.

La richiesta restituisce un elenco di `[Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html)` oggetti dopo la riga di commento 2. L'elenco di documenti restituito contiene istanze di [Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Document.html) non nulle dei dati degli articoli nello stesso ordine richiesto. Il `[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))` metodo converte un oggetto non tipizzato in un `Document` oggetto Java digitato se sono stati restituiti i dati dell'elemento, altrimenti restituisce 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());
        }
    }
```

Le tabelle DynamoDB contengono i seguenti elementi prima dell'esecuzione dell'esempio di codice.

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

Viene registrato il seguente output. Se un elemento viene richiesto ma non viene trovato, non viene restituito, come nel caso della richiesta per il film denominato`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'}
```

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

`[transactWriteItems()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))`Accetta fino a 100 azioni di inserimento, aggiornamento o eliminazione in una singola transazione atomica su più tabelle. La *Amazon DynamoDB Developer* Guide contiene dettagli sulle restrizioni e le condizioni di errore del funzionamento del servizio [DynamoDB sottostante](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems).

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

Nell'esempio seguente, sono richieste quattro operazioni per due tabelle. Le classi del modello corrispondenti [`ProductCatalog`](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)e [`MovieActor`](ddb-en-client-use-multirecord.md#ddb-en-client-use-movieactor-class)sono state mostrate in precedenza.

Ciascuna delle tre operazioni possibili (put, update ed delete) utilizza un parametro di richiesta dedicato per specificare i dettagli. 

Il codice dopo la riga di commento 1 mostra la semplice variazione del metodo. `addPutItem()` Il metodo accetta un `[MappedTableResource](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/MappedTableResource.html)` oggetto e l'istanza dell'oggetto dati da inserire. L'istruzione dopo la riga di commento 2 mostra la variante che accetta un'`[TransactPutItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactPutItemEnhancedRequest.html)`istanza. Questa variante consente di aggiungere altre opzioni nella richiesta, ad esempio un'espressione di condizione. Un [esempio](#ddb-en-client-use-multiop-trans-writeitems-opcondition) successivo mostra un'espressione di condizione per una singola operazione.

Viene richiesta un'operazione di aggiornamento dopo la riga di commento 3. `[TransactUpdateItemEnhancedRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/TransactUpdateItemEnhancedRequest.Builder.html)`ha un `ignoreNulls()` metodo che consente di configurare ciò che l'SDK fa con `null` i valori sull'oggetto del modello. Se il `ignoreNulls()` metodo restituisce true, l'SDK non rimuove i valori degli attributi della tabella per gli attributi degli oggetti dati che sono. `null` Se il `ignoreNulls()` metodo restituisce false, l'SDK richiede al servizio DynamoDB di rimuovere gli attributi dall'elemento nella tabella. Il valore predefinito per `ignoreNulls` è false.

L'istruzione dopo la riga di commento 4 mostra la variazione di una richiesta di eliminazione che richiede un oggetto dati. Il client avanzato estrae i valori chiave prima di inviare la richiesta 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())
        );
    }
```

I seguenti metodi di supporto forniscono gli oggetti dati per i parametri. `add*Item`

#### Metodi di supporto
<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;
    }
```

Le tabelle DynamoDB contengono i seguenti elementi prima dell'esecuzione dell'esempio di codice.

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

I seguenti elementi sono presenti nelle tabelle al termine dell'esecuzione del codice.

```
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'elemento sulla riga 2 è stato eliminato e le righe 3 e 5 mostrano gli elementi che sono stati inseriti. La riga 4 mostra l'aggiornamento della riga 1. Il `price` valore è l'unico valore che è cambiato sull'elemento. Se `ignoreNulls()` avesse restituito false, la riga 4 sarebbe simile alla riga seguente.

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

### Esempio di controllo delle condizioni
<a name="ddb-en-client-use-multiop-trans-writeitems-checkcond"></a>

L'esempio seguente mostra l'uso di un controllo delle condizioni. Un controllo delle condizioni viene utilizzato per verificare l'esistenza di un elemento o per verificare la condizione di attributi specifici di un elemento nel database. L'articolo registrato nel controllo delle condizioni non può essere utilizzato in un'altra operazione della transazione.

**Nota**  
Non è possibile fare riferimento allo stesso item con diverse operazioni all'interno della stessa transazione. Ad esempio, non è possibile eseguire un controllo delle condizioni e anche tentare di aggiornare lo stesso articolo nella stessa transazione.

L'esempio mostra una per ogni tipo di operazione in una richiesta transazionale di scrittura di elementi. Dopo la riga di commento 2, il `addConditionCheck()` metodo fornisce la condizione che fallisce la transazione se il `conditionExpression` parametro restituisce un risultato positivo. `false` L'espressione di condizione restituita dal metodo mostrato nel blocco Helper methods verifica se l'anno di premiazione del film non `Sophie's Choice` è uguale a. `1982` In caso affermativo, l'espressione restituisce `false` e la transazione ha esito negativo.

Questa guida illustra in modo approfondito [le espressioni](ddb-en-client-expressions.md) in un altro argomento.

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

I seguenti metodi di supporto vengono utilizzati nell'esempio di codice precedente.

#### Metodi di supporto
<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;
    }
```

Le tabelle DynamoDB contengono i seguenti elementi prima dell'esecuzione dell'esempio di codice.

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

I seguenti elementi sono presenti nelle tabelle al termine dell'esecuzione del codice.

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

Gli elementi rimangono invariati nelle tabelle perché la transazione non è riuscita. Il `actingYear` valore del filmato `Sophie's Choice` è`1982`, come mostrato nella riga 2 degli elementi della tabella prima della chiamata del `transactWriteItem()` metodo.

Per acquisire le informazioni di annullamento della transazione, racchiudi la chiamata al `transactWriteItems()` metodo in un `try` blocco e `catch` il [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). Dopo la riga di commento 4 dell'esempio, il codice registra ogni `[CancellationReason](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/CancellationReason.html)` oggetto. Poiché il codice che segue la riga di commento 3 dell'esempio specifica che devono essere restituiti i valori per l'elemento che ha causato il fallimento della transazione, nel registro vengono visualizzati i valori non elaborati del database per l'elemento del `Sophie's Choice` filmato.

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

### Esempio di condizione di operazione singola
<a name="ddb-en-client-use-multiop-trans-writeitems-opcondition"></a>

L'esempio seguente mostra l'uso di una condizione su una singola operazione in una richiesta di transazione. L'operazione di eliminazione dopo la riga di commento 1 contiene una condizione che verifica il valore dell'elemento di destinazione dell'operazione rispetto al database. In questo esempio, l'espressione condizionale creata con il metodo helper dopo la riga di commento 2 specifica che l'elemento deve essere eliminato dal database se l'anno di recitazione del film non è uguale al 2013.

[Le espressioni](ddb-en-client-expressions.md) vengono discusse più avanti in questa guida.

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

I seguenti metodi di supporto vengono utilizzati nell'esempio di codice precedente.

#### Metodi di supporto
<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;
    }
```

Le tabelle DynamoDB contengono i seguenti elementi prima dell'esecuzione dell'esempio di codice.

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

I seguenti elementi sono presenti nelle tabelle al termine dell'esecuzione del codice.

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

Gli elementi rimangono invariati nelle tabelle perché la transazione non è riuscita. Il `actingYear` valore del filmato `Blue Jasmine` è quello `2013` mostrato alla riga 2 dell'elenco degli elementi prima dell'esecuzione dell'esempio di codice.

Le seguenti righe vengono registrate nella 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)
```

# Usa indici secondari
<a name="ddb-en-client-use-secindex"></a>

Gli indici secondari migliorano l'accesso ai dati definendo chiavi alternative da utilizzare nelle operazioni di interrogazione e scansione. Gli indici secondari globali (GSI) hanno una chiave di partizione e una chiave di ordinamento che possono essere diverse da quelle della tabella di base. Al contrario, gli indici secondari locali (LSI) utilizzano la chiave di partizione dell'indice primario.

## Annota la classe di dati con annotazioni dell'indice secondario
<a name="ddb-en-client-use-secindex-annomodel"></a>

Gli attributi che partecipano agli indici secondari richiedono l'annotazione `@DynamoDbSecondaryPartitionKey` o`@DynamoDbSecondarySortKey`.

La classe seguente mostra le annotazioni per due indici. Il nome GSI *SubjectLastPostedDateIndex*utilizza l'`Subject`attributo per la chiave di partizione e il `LastPostedDateTime` per la chiave di ordinamento. L'LSI denominato *ForumLastPostedDateIndex*utilizza la `ForumName` come chiave di partizione e `LastPostedDateTime` come chiave di ordinamento.

Si noti che l'`Subject`attributo ha un duplice ruolo. È la chiave di ordinamento della chiave primaria e la chiave di partizione del GSI denominato. *SubjectLastPostedDateIndex*

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

La `MessageThread` classe è adatta all'uso come classe di dati per la [tabella Thread di esempio](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AppendixSampleTables.html) nella *Amazon DynamoDB Developer Guide*.

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

## Crea l'indice
<a name="ddb-en-client-use-secindex-confindex"></a>

A partire dalla versione 2.20.86 dell'SDK for Java, il `createTable()` metodo genera automaticamente indici secondari dalle annotazioni delle classi di dati. Per impostazione predefinita, tutti gli attributi della tabella di base vengono copiati in un indice e i valori di throughput assegnati sono 20 unità di capacità di lettura e 20 unità di capacità di scrittura.

Tuttavia, se si utilizza una versione SDK precedente alla 2.20.86, è necessario creare l'indice insieme alla tabella, come mostrato nell'esempio seguente. Questo esempio crea i due indici per la tabella. `Thread` Il parametro [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html) dispone di metodi per configurare entrambi i tipi di indici, come illustrato dopo le righe di commento 1 e 2. Utilizzate il `indexName()` metodo del generatore di indici per associare i nomi degli indici specificati nelle annotazioni delle classi di dati al tipo di indice desiderato.

Questo codice configura tutti gli attributi della tabella in modo che finiscano in entrambi gli indici dopo le righe di commento 3 e 4. Ulteriori informazioni sulle [proiezioni degli attributi](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Projections) sono disponibili nella *Amazon DynamoDB Developer* Guide.

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

## Esegui una query utilizzando un indice
<a name="ddb-en-client-use-secindex-query"></a>

L’esempio seguente esegue una query sull’indice globale secondario *ForumLastPostedDateIndex*.

Dopo la riga di commento 2, create un [QueryConditional](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html)oggetto che è necessario quando si chiama il [DynamoDbIndexmetodo.query ()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbIndex.html#query(java.util.function.Consumer)). 

Si ottiene un riferimento all'indice che si desidera interrogare dopo la riga di commento 3 inserendo il nome dell'indice. Dopo la riga di commento 4, si chiama il `query()` metodo sull'indice che passa l'`QueryConditional`oggetto. 

È inoltre possibile configurare la query per restituire tre valori di attributo, come mostrato dopo la riga di commento 5. Se non `attributesToProject()` viene chiamata, la query restituisce tutti i valori degli attributi. Notate che i nomi degli attributi specificati iniziano con lettere minuscole. Questi nomi di attributi corrispondono a quelli utilizzati nella tabella, non necessariamente ai nomi degli attributi della classe di dati.

Dopo la riga di commento 6, scorri i risultati e registra ogni elemento restituito dalla query, inoltre memorizzalo nell'elenco per restituirlo al chiamante.

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

I seguenti elementi sono presenti nel database prima dell'esecuzione della query.

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

Le istruzioni di registrazione alle righe 1 e 6 generano il seguente output della console.

```
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 query ha restituito elementi con un `forumName` valore di *Forum02* e un `lastPostedDateTime` valore maggiore o uguale a 2023.03.31.* I risultati mostrano `message` valori con una stringa vuota sebbene `message` gli attributi abbiano valori nell'indice. Questo perché l'attributo message non è stato proiettato dal codice dopo la riga di commento 5. 

# Usa funzionalità di mappatura avanzate
<a name="ddb-en-client-adv-features"></a>

Scopri le funzionalità avanzate dello schema delle tabelle nell'API DynamoDB Enhanced Client.

## Comprendi i tipi di schemi delle tabelle
<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)`è l'interfaccia per la funzionalità di mappatura dell'API DynamoDB Enhanced Client. Può mappare un oggetto di dati da e verso una mappa di. [AttributeValues](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/AttributeValue.html) Un `TableSchema` oggetto deve conoscere la struttura della tabella che sta mappando. Queste informazioni sulla struttura vengono memorizzate in 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)oggetto.

L'API client avanzata ha diverse implementazioni di`TableSchema`, che seguono. 

### Schema di tabella generato da classi annotate
<a name="ddb-en-client-adv-features-schema-mapped"></a>

È un'operazione moderatamente costosa creare una a `TableSchema` partire da classi annotate, quindi consigliamo di farlo una sola volta, all'avvio dell'applicazione.

 [ BeanTableSchema ](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.html)   
Questa implementazione è costruita sulla base degli attributi e delle annotazioni di una classe bean. Un esempio di questo approccio è illustrato nella [sezione Guida introduttiva](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean).  
Se a non `BeanTableSchema` si comporta come previsto, abilita la registrazione di debug per. `software.amazon.awssdk.enhanced.dynamodb.beans`

[ImmutableTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchema.html)  
Questa implementazione è costruita da una classe di dati immutabile. Questo approccio è descritto nella sezione. [Lavora con classi di dati immutabili](ddb-en-client-use-immut.md)

### Schema di tabella generato con un builder
<a name="ddb-en-client-adv-features-schema-static"></a>

`TableSchema`I seguenti sono creati a partire dal codice utilizzando un builder. Questo approccio è meno costoso dell'approccio che utilizza classi di dati annotate. L'approccio builder evita l'uso di annotazioni e non richiede standard di denominazione. JavaBean 

[StaticTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchema.html)  
Questa implementazione è progettata per classi di dati mutabili. La sezione introduttiva di questa guida ha dimostrato come [generare un file `StaticTableSchema` utilizzando un builder](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)  
Analogamente a come si crea un`StaticTableSchema`, si genera un'implementazione di questo tipo `TableSchema` utilizzando un [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticImmutableTableSchema.html) da utilizzare con classi di dati immutabili.

### Schema di tabella per dati senza schema fisso
<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)  
A differenza di altre implementazioni di`TableSchema`, non si definiscono gli attributi per un'`DocumentTableSchema`istanza. Di solito, si specificano solo chiavi primarie e fornitori di convertitori di attributi. Un'`EnhancedDocument`istanza fornisce gli attributi creati da singoli elementi o da una stringa JSON.

# Includi o escludi gli attributi in modo esplicito
<a name="ddb-en-client-adv-features-inex-attr"></a>

L'API DynamoDB Enhanced Client offre annotazioni per escludere gli attributi delle classi di dati dal diventare attributi su una tabella. Con l'API, puoi anche utilizzare un nome di attributo diverso dal nome dell'attributo della classe di dati.

## Escludi gli attributi
<a name="ddb-en-client-adv-features-inex-attr-ex"></a>

Per ignorare gli attributi che non devono essere mappati su una tabella DynamoDB, contrassegna l'attributo con l'annotazione. `@DynamoDbIgnore`

```
private String internalKey;

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

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

Per modificare il nome di un attributo utilizzato nella tabella DynamoDB, contrassegnalo con `@DynamoDbAttribute` l'annotazione e fornisci un nome diverso.

```
private String internalKey;

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

# Controlla la conversione degli attributi
<a name="ddb-en-client-adv-features-conversion"></a>

Per impostazione predefinita, uno schema tabellare fornisce convertitori per molti tipi Java comuni tramite un'implementazione predefinita dell'`[AttributeConverterProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverterProvider.html)`interfaccia. È possibile modificare il comportamento predefinito generale con un’implementazione `AttributeConverterProvider` personalizzata. Inoltre, è possibile modificare il convertitore per un singolo attributo.

Per un elenco dei convertitori disponibili, consultate l'[AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html)interfaccia Java doc.

## Fornisci fornitori di convertitori di attributi personalizzati
<a name="ddb-en-client-adv-features-conversion-prov"></a>

È possibile fornire una singola `AttributeConverterProvider` o una catena di messaggi ordinati `AttributeConverterProvider` tramite l'`@DynamoDbBean``(converterProviders = {…})`annotazione. Qualsiasi personalizzazione `AttributeConverterProvider` deve estendere l'`AttributeConverterProvider`interfaccia.

Tieni presente che se fornisci la tua catena di fornitori di convertitori di attributi, sostituirai il provider di convertitori predefinito,`DefaultAttributeConverterProvider`. Se si desidera utilizzare la funzionalità di`DefaultAttributeConverterProvider`, è necessario includerla nella catena. 

È anche possibile annotare il bean con un array `{}` vuoto. Ciò disabilita l'uso di qualsiasi fornitore di convertitori di attributi, incluso quello predefinito. In questo caso tutti gli attributi che devono essere mappati devono avere un proprio convertitore di attributi.

Il frammento seguente mostra un singolo fornitore di convertitori.

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

}
```

Il seguente frammento mostra l'uso di una catena di fornitori di convertitori. Poiché l'SDK predefinito viene fornito per ultimo, ha la priorità più bassa.

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

}
```

I generatori di schemi di tabelle statiche hanno un `attributeConverterProviders()` metodo che funziona allo stesso modo. Questo è mostrato nel frammento seguente.

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

## Sovrascrivi la mappatura di un singolo attributo
<a name="ddb-en-client-adv-features-conversion-single"></a>

Per sovrascrivere il modo in cui viene mappato un singolo attributo, fornisci un `AttributeConverter` per l'attributo. Questa aggiunta sostituisce tutti i convertitori forniti `AttributeConverterProviders` nello schema della tabella. Questo aggiunge un convertitore personalizzato solo per quell'attributo. Altri attributi, anche quelli dello stesso tipo, non utilizzeranno quel convertitore a meno che non sia specificato esplicitamente per quegli altri attributi.

L'`@DynamoDbConvertedBy`annotazione viene utilizzata per specificare la `AttributeConverter` classe personalizzata, come mostrato nel frammento seguente.

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

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

I costruttori di schemi statici hanno un metodo di creazione di attributi equivalente. `attributeConverter()` Questo metodo accetta un'istanza di an `AttributeConverter` come illustrato di seguito.

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

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

Questo esempio mostra un'`AttributeConverterProvider`implementazione che fornisce un convertitore di attributi per [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)gli oggetti. 

La `SimpleUser` classe seguente contiene un attributo denominato `lastUsedCookie` che è un'istanza di`HttpCookie`.

Il parametro delle `@DynamoDbBean` annotazioni elenca le due `AttributeConverterProvider` classi che forniscono convertitori.

------
#### [ 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`Nell'esempio seguente viene fornita un'istanza di un. `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);
        }
    }
```

### Codice di conversione
<a name="ddb-en-client-adv-features-conversion-example-code"></a>

Nel `transformFrom()` metodo della `HttpCookieConverter` classe seguente, il codice riceve un'`HttpCookie`istanza e la trasforma in una mappa DynamoDB memorizzata come attributo.

Il `transformTo()` metodo riceve un parametro di mappa DynamoDB, quindi richiama `HttpCookie` il costruttore che richiede un nome e un valore.

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

# Modifica il comportamento di aggiornamento degli attributi
<a name="ddb-en-client-adv-features-upd-behavior"></a>

*È possibile personalizzare il comportamento di aggiornamento dei singoli attributi quando si esegue un'operazione di aggiornamento.* [Alcuni esempi di operazioni di aggiornamento nell'API DynamoDB Enhanced Client [sono updateItem](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#updateItem(T)) () e (). transactWriteItems](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html#transactWriteItems(java.util.function.Consumer))

Ad esempio, immaginate di voler memorizzare un timestamp *creato su* un vostro record. Tuttavia, desideri che il suo valore venga scritto solo se non esiste alcun valore esistente per l'attributo già nel database. In questo caso, si utilizza il comportamento di `[WRITE\$1IF\$1NOT\$1EXISTS](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html#WRITE_IF_NOT_EXISTS)` aggiornamento.

L'esempio seguente mostra l'annotazione che aggiunge il comportamento all'`createdOn`attributo.

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

È possibile dichiarare lo stesso comportamento di aggiornamento quando si crea uno schema di tabella statico, come mostrato nell'esempio seguente dopo la riga di commento 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();
```

# Appiattisci gli attributi di altre classi
<a name="ddb-en-client-adv-features-flatmap"></a>

Se gli attributi della tabella sono distribuiti tra diverse classi Java, tramite ereditarietà o composizione, l'API Enhanced Client di DynamoDB fornisce supporto per riunire gli attributi in un'unica classe.

## Usa l'ereditarietà
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

Se le tue classi utilizzano l'ereditarietà, usa i seguenti approcci per appiattire la gerarchia.

### Usa fagioli annotati
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

Per l'approccio all'annotazione, entrambe le classi devono contenere l'`@DynamoDbBean`annotazione e una classe deve contenere una o più annotazioni chiave primarie.

Di seguito vengono illustrati esempi di classi di dati che hanno una relazione di ereditarietà.

------
#### [ Standard data class ]

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

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

@DynamoDbBean
public abstract class GenericRecord {
    private String id;
    private String createdDate;

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

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

[`onMethod`L'opzione](https://projectlombok.org/features/experimental/onX) di Lombok copia le annotazioni DynamoDB basate sugli attributi, ad esempio, sul codice generato. `@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;
}
```

------

### Usa schemi statici
<a name="ddb-en-client-adv-features-flatmap-inheritance-static"></a>

Per l'approccio allo schema statico, utilizzate il `extend()` metodo del generatore per comprimere gli attributi della classe principale nella classe figlia. Questo è mostrato dopo la riga di commento 1 nell'esempio seguente.

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

Il precedente esempio di schema statico utilizza le seguenti classi di dati. Poiché la mappatura viene definita quando si crea lo schema statico della tabella, le classi di dati non richiedono annotazioni.

#### Classi di dati
<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;
}
```

------

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

Se le tue classi usano la composizione, usa i seguenti approcci per appiattire la gerarchia.

### Usa fagioli annotati
<a name="ddb-en-client-adv-features-flatmap-comp-anno"></a>

L'`@DynamoDbFlatten`annotazione appiattisce la classe contenuta.

I seguenti esempi di classi di dati utilizzano l'`@DynamoDbFlatten`annotazione per aggiungere efficacemente tutti gli attributi della `GenericRecord` classe contenuta alla classe. `Customer`

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

------

Puoi usare l'annotazione flatten per appiattire tutte le diverse classi idonee di cui hai bisogno. Vengono applicati i vincoli seguenti:
+ Tutti i nomi degli attributi devono essere unici dopo essere stati appiattiti.
+ Non deve mai esserci più di una chiave di partizione, chiave di ordinamento o nome di tabella.

### Usa schemi statici
<a name="ddb-en-client-adv-features-flatmap-comp-static"></a>

Quando crei uno schema di tabella statico, usa il `flatten()` metodo del generatore. Fornite anche i metodi getter e setter che identificano la classe contenuta.

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

Il precedente esempio di schema statico utilizza le seguenti classi di dati.

#### Classi di dati
<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;
}
```

------

Puoi utilizzare il modello builder per appiattire tutte le diverse classi idonee di cui hai bisogno.

## Implicazioni per altro codice
<a name="ddb-en-client-adv-features-flatmap-compare"></a>

Quando si utilizza l'`@DynamoDbFlatten`attributo (o il metodo `flatten()` builder), l'elemento in DynamoDB contiene un attributo per ogni attributo dell'oggetto composto. Include anche gli attributi dell'oggetto che lo compone. 

Al contrario, se annotate una classe di dati con una classe composta e non la utilizzate`@DynamoDbFlatten`, l'elemento viene salvato con l'oggetto composto come attributo singolo.

Ad esempio, confrontate la `Customer` classe mostrata nell'esempio di [appiattimento con l'esempio di composizione con](#ddb-en-client-adv-features-flatmap-comp-anno) e senza appiattimento dell'attributo. `record` È possibile visualizzare la differenza con JSON come illustrato nella tabella seguente.


****  

| Con appiattimento | Senza appiattimento | 
| --- | --- | 
| 3 attributi | 2 attributi | 
|  <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 differenza diventa importante se si dispone di altro codice che accede alla tabella DynamoDB che prevede di trovare determinati attributi.

# Lavora con attributi che sono bean, mappe, elenchi e set
<a name="ddb-en-client-adv-features-nested"></a>

Una definizione di bean, come la `Person` classe mostrata di seguito, potrebbe definire proprietà (o attributi) che si riferiscono a tipi con attributi aggiuntivi. Ad esempio, nella `Person` classe, `mainAddress` c'è una proprietà che si riferisce a un `Address` bean che definisce attributi di valore aggiuntivi. `addresses`si riferisce a una mappa Java, i cui elementi si riferiscono ai `Address` bean. Questi tipi complessi possono essere considerati contenitori di attributi semplici da utilizzare per il valore dei dati nel contesto di DynamoDB. 

*DynamoDB si riferisce alle proprietà di valore degli elementi nidificati, come mappe, elenchi o bean, come attributi nidificati.* *La [Amazon DynamoDB Developer](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) Guide si riferisce al formato salvato di una mappa, un elenco o un bean Java come tipo di documento.* Gli attributi semplici utilizzati per il loro valore di dati in Java sono denominati *tipi scalari* in DynamoDB. *I set, che contengono più elementi scalari dello stesso tipo e sono denominati tipi di set.* 

È importante sapere che l'API DynamoDB Enhanced Client converte una proprietà che è bean in un tipo di documento di mappa DynamoDB quando viene salvata.

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

## Salva tipi complessi
<a name="ddb-en-client-adv-features-nested-mapping"></a>

### Usa classi di dati annotate
<a name="ddb-en-client-adv-features-nested-map-anno"></a>

Puoi salvare gli attributi annidati per le classi personalizzate semplicemente annotandoli. La `Address` classe e la `PhoneNumber` classe mostrate in precedenza vengono annotate solo con l'annotazione. `@DynamoDbBean` Quando l'API DynamoDB Enhanced Client crea lo schema della tabella per la classe con `Person` il seguente frammento, l'API rileva l'uso delle classi `PhoneNumber` and e crea le mappature corrispondenti per `Address` funzionare con DynamoDB.

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

### Usa schemi astratti con i builder
<a name="ddb-en-client-adv-features-nested-map-builder"></a>

L'approccio alternativo consiste nell'utilizzare generatori di schemi di tabelle statiche per ogni classe bean annidata, come mostrato nel codice seguente.

Gli schemi di tabella per le `PhoneNumber` classi `Address` and sono astratti, nel senso che non possono essere utilizzati con una tabella DynamoDB. Questo perché mancano di definizioni per la chiave primaria. Vengono tuttavia utilizzati come schemi annidati nello schema tabellare della classe. `Person`

Dopo le righe di commento 1 e 2 nella definizione di`PERSON_TABLE_SCHEMA`, viene visualizzato il codice che utilizza gli schemi di tabella astratti. L'uso di `documentOf` nel `EnhanceType.documentOf(...)` metodo non indica che il metodo restituisca un `EnhancedDocument` tipo di Enhanced Document API. Il `documentOf(...)` metodo in questo contesto restituisce un oggetto che sa come mappare l'argomento della classe da e verso gli attributi della tabella DynamoDB utilizzando l'argomento dello schema della tabella.

#### Codice dello schema statico
<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();
```

## Attributi di progetto di tipi complessi
<a name="ddb-en-client-adv-features-nested-projection"></a>

Per `query()` i `scan()` metodi, è possibile specificare quali attributi si desidera vengano restituiti nei risultati utilizzando chiamate di metodo come `addNestedAttributeToProject()` e`attributesToProject()`. L'API DynamoDB Enhanced Client converte i parametri di chiamata al metodo Java [in espressioni di proiezione](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) prima dell'invio della richiesta.

L'esempio seguente popola la `Person` tabella con due elementi, quindi esegue tre operazioni di scansione. 

La prima scansione accede a tutti gli elementi della tabella per confrontare i risultati con le altre operazioni di scansione. 

La seconda scansione utilizza il metodo [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#addNestedAttributeToProject(software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName))builder per restituire solo il `street` valore dell'attributo.

La terza operazione di scansione utilizza il metodo [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/ScanEnhancedRequest.Builder.html#attributesToProject(java.lang.String...))builder per restituire i dati per l'attributo di primo livello,. `hobbies` Il tipo di attributo di `hobbies` è un elenco. Per accedere a singoli elementi dell'elenco, eseguire un'`get()`operazione sull'elenco.

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

**Nota**  
Se il `attributesToProject()` metodo segue qualsiasi altro metodo di creazione che aggiunge gli attributi che desiderate proiettare, l'elenco dei nomi degli attributi fornito `attributesToProject()` sostituisce tutti gli altri nomi di attributo.  
Una scansione eseguita con l'`ScanEnhancedRequest`istanza nel frammento seguente restituisce solo dati relativi agli hobby.  

```
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]}
```
Il seguente frammento di codice utilizza innanzitutto il metodo. `attributesToProject()` Questo ordinamento conserva tutti gli altri attributi richiesti.  

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

## Usa tipi complessi nelle espressioni
<a name="ddb-en-client-adv-features-nested-expressions"></a>

È possibile utilizzare tipi complessi nelle espressioni, ad esempio espressioni di filtro ed espressioni di condizione, utilizzando gli operatori di dereferenziamento per navigare nella struttura del tipo complesso. Per oggetti e mappe, usa `. (dot)` e per gli elementi dell'elenco `[n]` (parentesi quadre attorno al numero di sequenza dell'elemento). Non puoi fare riferimento ai singoli elementi di un set, ma puoi usare la [`contains`funzione](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

L'esempio seguente mostra due espressioni di filtro utilizzate nelle operazioni di scansione. Le espressioni di filtro specificano le condizioni di corrispondenza per gli elementi da inserire nei risultati. L'esempio utilizza e `Person` `Address` le `PhoneNumber` classi mostrate in precedenza.

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

### Metodo di supporto che popola la tabella
<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);
    }
```

### Rappresentazione JSON degli elementi del database
<a name="nested-attributes-expression-json-items"></a>

```
{
 "id": 1,
 "addresses": {
  "billing": {
   "city": "BillingTown1",
   "state": "BS1",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown1",
   "state": "MS1",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName1",
 "lastName": "LastName1",
 "phoneNumbers": [
  {
   "number": "111-111-1111",
   "type": "work"
  },
  {
   "number": "222-222-2222",
   "type": "home"
  }
 ]
}

{
 "id": 2,
 "addresses": {
  "billing": {
   "city": "BillingTown2",
   "state": "BS2",
   "street": null,
   "zipCode": null
  },
  "mailing": {
   "city": "MailingTown2",
   "state": "MS2",
   "street": null,
   "zipCode": null
  }
 },
 "firstName": "FirstName2",
 "lastName": "LastName2",
 "phoneNumbers": [
  {
   "number": "333-333-3333",
   "type": "work"
  },
  {
   "number": "444-444-4444",
   "type": "cell"
  }
 ]
}
```

## Aggiorna gli elementi che contengono tipi complessi
<a name="ddb-en-client-adv-features-nested-updates"></a>

Per aggiornare un elemento che contiene tipi complessi, sono disponibili due approcci di base:
+ Approccio 1: recupera prima l'elemento (utilizzando`getItem`), aggiorna l'oggetto, quindi chiama`DynamoDbTable#updateItem`.
+ Approccio 2: non recuperate l'elemento, ma create una nuova istanza, impostate le proprietà che desiderate aggiornare e inviate l'istanza `DynamoDbTable#updateItem` impostando il valore appropriato di. [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) Questo approccio non richiede il recupero dell'elemento prima di aggiornarlo.

Gli esempi mostrati in questa sezione utilizzano le `PhoneNumber` classi `Person``Address`, e mostrate in precedenza.

### Approccio di aggiornamento 1: recupera, quindi aggiorna
<a name="ddb-en-client-adv-features-nested-updates-retreive"></a>

Utilizzando questo approccio, vi assicurate che nessun dato vada perso durante l'aggiornamento. L'API DynamoDB Enhanced Client ricrea il bean con gli attributi dell'elemento salvato in DynamoDB, inclusi i valori di tipi complessi. È quindi necessario utilizzare i getter e i setter per aggiornare il bean. Lo svantaggio di questo approccio è il costo che si deve sostenere per recuperare prima l'articolo.

L'esempio seguente dimostra che non si perde alcun dato se si recupera l'elemento prima di aggiornarlo.

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

### Approccio di aggiornamento 2: utilizzare un `IgnoreNullsMode` enum senza prima recuperare l'elemento
<a name="ddb-en-client-adv-features-nested-updates-nullmode"></a>

Per aggiornare un elemento in DynamoDB, puoi fornire un nuovo oggetto con solo le proprietà che desideri aggiornare e lasciare gli altri valori come nulli. Con questo approccio, è necessario essere consapevoli di come i valori nulli nell'oggetto vengono trattati dall'SDK e di come è possibile controllarne il comportamento.

Per specificare quali proprietà con valori nulli vuoi che l'SDK ignori, fornisci un enum quando crei il. `IgnoreNullsMode` [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) Come esempio di utilizzo di uno dei valori enumerati, il frammento seguente utilizza la modalità. `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"
    }
  }
*/
```

[L'Amazon DynamoDB Developer Guide contiene ulteriori informazioni sulle espressioni di aggiornamento.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html)

#### Descrizioni delle opzioni `IgnoreNullsMode`
<a name="ignore-nulls-mode-descriptions"></a>
+ `IgnoreNullsMode.SCALAR_ONLY`- Utilizzate questa impostazione per aggiornare gli attributi scalari a qualsiasi livello. L'SDK crea un'istruzione di aggiornamento che invia solo attributi scalari non nulli a DynamoDB. L'SDK ignora gli attributi scalari con valori nulli di un bean o di una mappa, mantenendo il valore salvato in DynamoDB.

  Quando si aggiorna un attributo scalare di map o bean, la mappa deve già esistere in DynamoDB. Se aggiungi una mappa o un bean all'oggetto che non esiste già per l'oggetto in DynamoDB, ricevi `DynamoDbException` un messaggio con il *messaggio Il percorso del documento fornito nell'espressione di aggiornamento non è valido per l'aggiornamento*. È necessario utilizzare `MAPS_ONLY` la modalità per aggiungere un bean o una map a DynamoDB prima di aggiornare uno qualsiasi dei suoi attributi.
+ `IgnoreNullsMode.MAPS_ONLY`- Utilizzate questa impostazione per aggiungere o sostituire proprietà che sono un bean o una mappa. L'SDK sostituisce o aggiunge qualsiasi mappa o bean fornito nell'oggetto. Tutti i bean o le mappe che sono nulli nell'oggetto vengono ignorati, mantenendo la mappa esistente in DynamoDB.
+ `IgnoreNullsMode.DEFAULT`- Con questa impostazione, l'SDK non ignora mai i valori nulli. Gli attributi scalari a qualsiasi livello che sono nulli vengono aggiornati a null. L'SDK aggiorna qualsiasi proprietà bean, map, list o set con valori nulli nell'oggetto su null in DynamoDB. Quando si utilizza questa modalità, o non si fornisce una modalità poiché è la modalità predefinita, è necessario recuperare prima l'elemento in modo che i valori in DynamoDB non siano impostati su null forniti nell'oggetto per l'aggiornamento, a meno che non si intenda impostare i valori su null.

In tutte le modalità, se si fornisce un oggetto con un elenco o un set non nullo, l'elenco o il set viene salvato in DynamoDB. `updateItem` 

#### Perché le modalità?
<a name="ddb-en-client-adv-features-nested-updates-nullmodes-why"></a>

Quando fornisci un oggetto con un bean o una map al `updateItem` metodo, l'SDK non è in grado di stabilire se utilizzare i valori delle proprietà nel bean (o i valori di immissione nella mappa) per aggiornare l'elemento o se l'intero bean/map deve sostituire ciò che è stato salvato in DynamoDB.

Partendo dal nostro esempio precedente che mostra innanzitutto il recupero dell'elemento, proviamo ad aggiornare l'`city`attributo di without the retrieval. `mainAddress`

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

I due esempi seguenti mostrano gli usi di e dei valori enumerati`MAPS_ONLY`. `SCALAR_ONLY` `MAPS_ONLY`aggiunge una mappa e `SCALAR_ONLY` aggiorna una mappa.

##### `IgnoreNullsMode.MAPS_ONLY` Esempio
<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.
    }
```

Fate riferimento alla tabella seguente per vedere quali valori nulli vengono ignorati per ciascuna modalità. Spesso è possibile lavorare con entrambi`SCALAR_ONLY`, `MAPS_ONLY` tranne quando si lavora con bean o mappe.


**Quali proprietà con valori nulli nell'oggetto inviato vengono ignorate dall'SDK per `updateItem` ciascuna modalità?**  

| Tipo di proprietà | in modalità SCALAR\$1ONLY | in modalità MAPS\$1ONLY | in modalità DEFAULT | 
| --- | --- | --- | --- | 
| Scalare superiore | Sì  | Sì | No | 
| Bean o mappa | Sì  | Sì | No | 
| Valore scalare di un bean o di una voce di mappa | Sì1 | No2 | No | 
| Elenco o set | Sì  | Sì | No | 

1 Ciò presuppone che la mappa esista già in DynamoDB. Qualsiasi valore scalare, nullo o non nullo, del bean o della mappa fornito nell'oggetto per l'aggiornamento richiede che esista un percorso al valore in DynamoDB. L'SDK costruisce un percorso verso l'attributo utilizzando l'operatore di dereferenza prima di inviare la richiesta. `. (dot)`

2 Poiché si utilizza la `MAPS_ONLY` modalità per sostituire completamente o aggiungere un bean o una map, tutti i valori null nel bean o nella mappa vengono mantenuti nella mappa salvata in DynamoDB.

# Conserva gli oggetti vuoti con `@DynamoDbPreserveEmptyObject`
<a name="ddb-en-client-adv-features-empty"></a>

Se salvi un bean in Amazon DynamoDB con oggetti vuoti e desideri che l'SDK ricrei gli oggetti vuoti al momento del recupero, annota il getter del bean interno con. `@DynamoDbPreserveEmptyObject`

Per illustrare come funziona l'annotazione, l'esempio di codice utilizza i due bean seguenti.

## Fagioli di esempio
<a name="ddb-en-client-adv-features-empty-ex1"></a>

La seguente classe di dati contiene due `InnerBean` campi. Il metodo getter`getInnerBeanWithoutAnno()`, non è annotato con. `@DynamoDbPreserveEmptyObject` Il `getInnerBeanWithAnno()` metodo è annotato.

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

Le istanze della `InnerBean` classe seguente sono campi di `MyBean` e vengono inizializzate come oggetti vuoti nel codice di esempio.

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

Il seguente esempio di codice salva un `MyBean` oggetto con bean interni inizializzati in DynamoDB e quindi recupera l'elemento. L'output registrato mostra che non `innerBeanWithoutAnno` è stato inizializzato, ma è stato creato. `innerBeanWithAnno`

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

## Schema statico alternativo
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

È possibile utilizzare la seguente `StaticTableSchema` versione degli schemi delle tabelle al posto delle annotazioni sui bean.

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

# Evita di salvare gli attributi nulli degli oggetti annidati
<a name="ddb-en-client-adv-features-ignore-null"></a>

È possibile ignorare gli attributi nulli degli oggetti nidificati quando si salva un oggetto di classe di dati in DynamoDB applicando l'annotazione. `@DynamoDbIgnoreNulls` Al contrario, gli attributi di primo livello con valori nulli non vengono mai salvati nel database.

Per illustrare come funziona l'annotazione, l'esempio di codice utilizza i due bean seguenti.

## Fagioli di esempio
<a name="ddb-en-client-adv-features-ignore-null-ex1"></a>

La seguente classe di dati contiene due `InnerBean` campi. Il metodo getter`getInnerBeanWithoutAnno()`, non è annotato. Il `getInnerBeanWithIgnoreNullsAnno()` metodo è annotato con. `@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();
    }
}
```

Le istanze della seguente `InnerBean` classe sono campi di `MyBean` e vengono utilizzate nel seguente codice di esempio.

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

Il seguente esempio di codice crea un `InnerBean` oggetto e imposta solo uno dei suoi due attributi con un valore. 

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

Per visualizzare i dati di basso livello inviati a DynamoDB, il codice registra la mappa degli attributi prima di salvare l'oggetto. `MyBean`

L'output registrato mostra che restituisce un attributo, `innerBeanWithIgnoreNullsAnno`

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

L'`innerBeanWithoutAnno`istanza restituisce due attributi. Un attributo ha un valore di 200 e l'altro è un attributo con valore nullo.

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

## Rappresentazione JSON della mappa degli attributi
<a name="ddb-en-client-adv-features-ignore-null-ex2"></a>

La seguente rappresentazione JSON semplifica la visualizzazione dei dati salvati in DynamoDB.

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

## Schema statico alternativo
<a name="ddb-en-client-adv-features-empty-ex1-static"></a>

È possibile utilizzare la seguente `StaticTableSchema` versione degli schemi delle tabelle al posto delle annotazioni delle classi di dati.

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

# Lavora con documenti JSON con l'API Enhanced Document per DynamoDB
<a name="ddb-en-client-doc-api"></a>

L'[Enhanced Document API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) for AWS SDK for Java 2.x è progettata per funzionare con dati orientati ai documenti che non hanno uno schema fisso. Tuttavia, consente anche di utilizzare classi personalizzate per mappare singoli attributi.

 L'Enhanced Document API è il successore dell'[API Document](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/DynamoDB.html) della AWS SDK per Java versione 1.x.

**Contents**
+ [Inizia a usare l'Enhanced Document API](ddb-en-client-doc-api-steps.md)
  + [Crea un e un `DocumentTableSchema` `DynamoDbTable`](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema)
+ [Crea documenti avanzati](ddb-en-client-doc-api-steps-create-ed.md)
  + [Crea da una stringa JSON](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromJson)
  + [Costruisci a partire da singoli elementi](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts)
+ [Esegui operazioni CRUD](ddb-en-client-doc-api-steps-use.md)
+ [Accedi agli attributi avanzati del documento come oggetti personalizzati](ddb-en-client-doc-api-convert.md)
+ [Usa e `EnhancedDocument` senza DynamoDB](ddb-en-client-doc-api-standalone.md)

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

L'API Enhanced Document richiede le stesse [dipendenze](ddb-en-client-getting-started.md#ddb-en-client-gs-dep) necessarie per l'API DynamoDB Enhanced Client. Richiede anche un'[`DynamoDbEnhancedClient`istanza](ddb-en-client-getting-started-dynamodbTable.md#ddb-en-client-getting-started-dynamodbTable-eclient), come mostrato all'inizio di questo argomento.

Poiché l'Enhanced Document API è stata rilasciata con la versione 2.20.3 di AWS SDK for Java 2.x, è necessaria quella versione o superiore.

## Crea un e un `DocumentTableSchema` `DynamoDbTable`
<a name="ddb-en-client-doc-api-steps-createschema"></a>

Per richiamare comandi su una tabella DynamoDB utilizzando l'API Enhanced Document, associa la tabella a un oggetto risorsa < > lato [DynamoDbTableclient EnhancedDocument](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html). 

Il `table()` metodo del client avanzato crea un'`DynamoDbTable<EnhancedDocument>`istanza e richiede parametri per il nome della tabella DynamoDB e un. `DocumentTableSchema` 

Il builder for a [DocumentTableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.html)richiede una chiave di indice principale e uno o più provider di convertitori di attributi. Il `AttributeConverterProvider.defaultProvider()` metodo fornisce convertitori per i tipi [predefiniti](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/internal/converter/attribute/package-summary.html). Dovrebbe essere specificato anche se si fornisce un provider di convertitori di attributi personalizzato. È possibile aggiungere una chiave di indice secondaria opzionale al generatore.

Il seguente frammento di codice mostra il codice che genera la rappresentazione lato client di una tabella DynamoDB che memorizza oggetti senza schema. `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.
```

Di seguito viene illustrata la rappresentazione JSON di un oggetto utilizzata in questa sezione. `person`

### Oggetto JSON `person`
<a name="ddb-en-client-doc-api-steps-createschema-obj"></a>

```
{
  "id": 1,
  "firstName": "Richard",
  "lastName": "Roe",
  "age": 25,
  "addresses":
    {
      "home": {
        "zipCode": "00000",
        "city": "Any Town",
        "state": "FL",
        "street": "123 Any Street"
      },
      "work": {
        "zipCode": "00001",
        "city": "Anywhere",
        "state": "FL",
        "street": "100 Main Street"
      }
    },
  "hobbies": [
    "Hobby 1",
    "Hobby 2"
  ],
  "phoneNumbers": [
    {
      "type": "Home",
      "number": "555-0100"
    },
    {
      "type": "Work",
      "number": "555-0119"
    }
  ]
}
```

# Crea documenti avanzati
<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)` rappresenta un oggetto di tipo documento con una struttura complessa con attributi annidati. An `EnhancedDocument` richiede attributi di primo livello che corrispondano agli attributi della chiave primaria specificati per. `DocumentTableSchema` Il contenuto rimanente è arbitrario e può essere costituito da attributi di primo livello e anche da attributi profondamente annidati.

Si crea un'`EnhancedDocument`istanza utilizzando un generatore che offre diversi modi per aggiungere elementi.

## Crea da una stringa JSON
<a name="ddb-en-client-doc-api-steps-create-ed-fromJson"></a>

Con una stringa JSON, puoi creare una chiamata `EnhancedDocument` in un unico metodo. Il seguente frammento crea un `EnhancedDocument` da una stringa JSON restituita dal metodo helper. `jsonPerson()` [Il `jsonPerson()` metodo restituisce la versione in stringa JSON dell'oggetto persona mostrato in precedenza.](ddb-en-client-doc-api-steps.md#ddb-en-client-doc-api-steps-createschema-obj)

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

## Costruisci a partire da singoli elementi
<a name="ddb-en-client-doc-api-steps-create-ed-fromparts"></a>

In alternativa, puoi creare un'`EnhancedDocument`istanza a partire da singoli componenti utilizzando i metodi type-safe del builder.

L'esempio seguente crea un documento `person` avanzato simile al documento avanzato creato a partire dalla stringa JSON dell'esempio precedente.

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

### Metodi di supporto
<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"));

    }
```

# Esegui operazioni CRUD
<a name="ddb-en-client-doc-api-steps-use"></a>

Dopo aver definito un'`EnhancedDocument`istanza, è possibile salvarla in una tabella DynamoDB. Il seguente frammento di codice utilizza [PersonDocument creato](ddb-en-client-doc-api-steps-create-ed.md#ddb-en-client-doc-api-steps-create-ed-fromparts) da singoli elementi.

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

Dopo aver letto un'istanza di documento avanzata da DynamoDB, è possibile estrarre i valori dei singoli attributi utilizzando i getter, come mostrato nel seguente frammento di codice, che accedono ai dati salvati da. `personDocument` In alternativa, è possibile estrarre il contenuto completo in una stringa JSON, come mostrato nell'ultima parte del codice di esempio.

```
        // 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`le istanze possono essere utilizzate con qualsiasi metodo `[DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)` o al posto delle classi [DynamoDbEnhancedClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html)di dati mappate.

# Accedi agli attributi avanzati del documento come oggetti personalizzati
<a name="ddb-en-client-doc-api-convert"></a>

Oltre a fornire un'API per leggere e scrivere attributi con strutture senza schema, l'API Enhanced Document consente di convertire gli attributi da e verso istanze di classi personalizzate.

L'API Enhanced Document utilizza `AttributeConverterProvider` i `AttributeConverter` caratteri e i caratteri mostrati nella sezione di [conversione degli attributi di controllo](ddb-en-client-adv-features-conversion.md) come parte dell'API DynamoDB Enhanced Client.

Nell'esempio seguente, utilizziamo a `CustomAttributeConverterProvider` con la sua `AddressConverter` classe annidata per convertire gli oggetti. `Address` 

Questo esempio mostra che è possibile combinare dati provenienti da classi e anche dati provenienti da strutture create secondo necessità. Questo esempio mostra anche che le classi personalizzate possono essere utilizzate a qualsiasi livello di una struttura annidata. Gli `Address` oggetti in questo esempio sono valori utilizzati in una mappa.

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

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

## Metodo di supporto che fornisce indirizzi
<a name="ddb-en-client-doc-api-convert-helper"></a>

Il seguente metodo di supporto fornisce la mappa che utilizza istanze personalizzate per i valori anziché `Address` istanze generiche `Map<String, String>` per i valori.

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

# Usa e `EnhancedDocument` senza DynamoDB
<a name="ddb-en-client-doc-api-standalone"></a>

Sebbene di solito si utilizzi un'istanza di an `EnhancedDocument` per leggere e scrivere elementi DynamoDB di tipo documento, può essere utilizzata anche indipendentemente da DynamoDB. 

È possibile utilizzarli `EnhancedDocuments` per la loro capacità di convertire tra stringhe JSON o oggetti personalizzati in mappe di basso livello come mostrato nell'esempio seguente. `AttributeValues`

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

**Nota**  
Quando utilizzi un documento avanzato indipendente da una tabella DynamoDB, assicurati di impostare in modo esplicito i provider di conversione degli attributi sul builder.  
Al contrario, lo schema della tabella dei documenti fornisce i provider di conversione quando un documento avanzato viene utilizzato con una tabella DynamoDB.

# Usa le estensioni per personalizzare le operazioni di DynamoDB Enhanced Client
<a name="ddb-en-client-extensions"></a>

L'API DynamoDB Enhanced Client supporta le estensioni dei plugin che forniscono funzionalità che vanno oltre le operazioni di mappatura. Le estensioni utilizzano due metodi hook per modificare i dati durante le operazioni di lettura e scrittura:
+ `beforeWrite()`- Modifica un'operazione di scrittura prima che avvenga
+ `afterRead()`- Modifica i risultati di un'operazione di lettura dopo che è avvenuta

Alcune operazioni (come l'aggiornamento degli elementi) eseguono sia una scrittura che una lettura, quindi vengono chiamati entrambi i metodi hook.

## Come vengono caricate le estensioni
<a name="ddb-en-client-extensions-loading"></a>

Le estensioni vengono caricate nell'ordine specificato nel generatore di client avanzato. L'ordine di caricamento può essere importante perché un'estensione può agire su valori che sono stati trasformati da un'estensione precedente.

Per impostazione predefinita, il client avanzato carica due estensioni:
+ `[VersionedRecordExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/VersionedRecordExtension.html)`- Fornisce un blocco ottimistico
+ `[AtomicCounterExtension](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/extensions/AtomicCounterExtension.html)`- Incrementa automaticamente gli attributi del contatore

È possibile sovrascrivere il comportamento predefinito con il client builder avanzato e caricare qualsiasi estensione. Puoi anche specificarne nessuna se non desideri le estensioni predefinite.

**Importante**  
Se carichi le tue estensioni, il client avanzato non carica alcuna estensione predefinita. Se desideri il comportamento fornito da una delle estensioni predefinite, devi aggiungerla esplicitamente all'elenco delle estensioni.

L'esempio seguente mostra come caricare un'estensione personalizzata che `verifyChecksumExtension` prende il `VersionedRecordExtension` nome da. In questo esempio non `AtomicCounterExtension` viene caricato.

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

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

## Dettagli e configurazione delle estensioni disponibili
<a name="ddb-en-client-extensions-details"></a>

Le seguenti sezioni forniscono informazioni dettagliate su ciascuna estensione disponibile nell'SDK.

### Implementa il blocco ottimistico con `VersionedRecordExtension`
<a name="ddb-en-client-extensions-VRE"></a>

L'`VersionedRecordExtension`estensione fornisce un blocco ottimistico incrementando e tracciando il numero di versione di un articolo man mano che gli articoli vengono scritti nel database. A ogni scrittura viene aggiunta una condizione che causa l'esito negativo della scrittura se il numero di versione dell'elemento persistente effettivo non corrisponde al valore letto per l'ultima volta dall'applicazione.

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

Per specificare l'attributo da utilizzare per tenere traccia del numero di versione dell'elemento, contrassegnate un attributo numerico nello schema della tabella.

Il frammento seguente specifica che l'`version`attributo deve contenere il numero di versione dell'articolo.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

#### Come funziona
<a name="ddb-en-client-extensions-VRE-how-it-works"></a>

Il blocco ottimistico con il `VersionedRecordExtension` ha il seguente impatto su questi metodi: `DynamoDbEnhancedClient` `DynamoDbTable`

**`putItem`**  
Ai nuovi elementi viene assegnato un valore di versione iniziale pari a 0. Questo può essere configurato con`@DynamoDbVersionAttribute(startAt = X)`.

**`updateItem`**  
Se recuperate un elemento, aggiornate una o più delle sue proprietà e tentate di salvare le modifiche, l'operazione ha esito positivo solo se il numero di versione sul lato client e sul lato server corrisponde.  
In caso di successo, il numero di versione viene automaticamente incrementato di 1. Questo può essere configurato con`@DynamoDbVersionAttribute(incrementBy = X)`.

**`deleteItem`**  
L'`DynamoDbVersionAttribute`annotazione non ha effetto. È necessario aggiungere manualmente un'espressione di condizione quando si elimina un elemento.  
L'esempio seguente aggiunge un'espressione condizionale per garantire che l'elemento eliminato sia quello che è stato letto. Nell'esempio seguente l'attributo del bean `recordVersion` è annotato con. `@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`: Questo metodo ha lo stesso comportamento di`putItem`.
+ `addUpdateItem`: Questo metodo ha lo stesso comportamento di`updateItem`.
+ `addDeleteItem`: Questo metodo ha lo stesso comportamento di`deleteItem`.

**`batchWriteItem`**  
+ `addPutItem`: Questo metodo ha lo stesso comportamento di`putItem`.
+ `addDeleteItem`: Questo metodo ha lo stesso comportamento di`deleteItem`.

**Nota**  
Le tabelle globali di DynamoDB utilizzano [una riconciliazione «last writer win»](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.consistency-modes) tra aggiornamenti simultanei, in cui DynamoDB fa del suo meglio per determinare l'ultimo writer. Se si utilizzano tabelle globali, questa politica «l'ultimo scrittore vince» significa che le strategie di blocco potrebbero non funzionare come previsto, poiché tutte le repliche alla fine convergeranno in base all'ultima scrittura determinata da DynamoDB. 

#### Come disattivare
<a name="ddb-en-client-extensions-VRE-how-to-disable"></a>

Per disabilitare il blocco ottimistico, non utilizzare l'`@DynamoDbVersionAttribute`annotazione.

### Implementa i contatori con `AtomicCounterExtension`
<a name="ddb-en-client-extensions-ACE"></a>

L'`AtomicCounterExtension`estensione incrementa un attributo numerico con tag ogni volta che un record viene scritto nel database. È possibile specificare valori iniziali e incrementali. Se non viene specificato alcun valore, il valore iniziale viene impostato su 0 e il valore dell'attributo aumenta di 1.

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

Per specificare quale attributo è un contatore, contrassegnate un attributo di tipo `Long` nello schema della tabella.

Il frammento seguente mostra l'uso dei valori di inizio e incremento predefiniti per l'attributo. `counter`

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

L'approccio allo schema di tabella statica è illustrato nel frammento seguente. L'estensione del contatore atomico utilizza un valore iniziale di 10 e incrementa il valore di 5 ogni volta che viene scritto il record.

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

### Aggiungi timestamp con `AutoGeneratedTimestampRecordExtension`
<a name="ddb-en-client-extensions-AGTE"></a>

L'`AutoGeneratedTimestampRecordExtension`estensione aggiorna automaticamente gli attributi di tipo contrassegnati `[Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html)` con un timestamp corrente ogni volta che l'elemento viene scritto correttamente nel database. Questa estensione non viene caricata per impostazione predefinita.

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

Per specificare l'attributo da aggiornare con il timestamp corrente, contrassegnate l'`Instant`attributo nello schema della tabella.

L'`lastUpdate`attributo è l'obiettivo del comportamento dell'estensione nel frammento seguente. Nota il requisito secondo cui l'attributo deve essere di `Instant` tipo.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

### Genera un UUID con AutoGeneratedUuidExtension
<a name="ddb-en-client-extensions-AGUE"></a>

L'`AutoGeneratedUuidExtension`estensione genera un UUID (Universally Unique Identifier) univoco per un attributo quando un nuovo record viene scritto nel database. Utilizza il metodo Java JDK [UUID.randomUUID](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--) () e si applica agli attributi di tipo. `java.lang.String` Questa estensione non viene caricata per impostazione predefinita.

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

L'`uniqueId`attributo è l'obiettivo del comportamento dell'estensione nel frammento seguente.

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

L'approccio equivalente allo schema di tabella statica è illustrato nel frammento seguente.

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

Se desideri che l'estensione compili l'UUID solo per i `putItem` metodi e non per i `updateItem` metodi, aggiungi l'annotazione sul [comportamento di aggiornamento](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/UpdateBehavior.html) come mostrato nel seguente frammento.

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

Se utilizzate l'approccio dello schema a tabella statica, utilizzate il seguente codice equivalente.

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

# Esempio di estensione personalizzata
<a name="ddb-en-client-extensions-custom"></a>

È possibile creare estensioni personalizzate implementando l'`DynamoDbEnhancedClientExtension`interfaccia. La seguente classe di estensione personalizzata mostra un `beforeWrite()` metodo che utilizza un'espressione di aggiornamento per impostare un `registrationDate` attributo se l'elemento nel database non ne ha già uno.

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

# Usa l'API DynamoDB Enhanced Client in modo asincrono
<a name="ddb-en-client-async"></a>

Se l'applicazione richiede chiamate asincrone non bloccanti a DynamoDB, è possibile utilizzare il. [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html) È simile all'implementazione sincrona ma con le seguenti differenze chiave:

1. Quando si crea il`DynamoDbEnhancedAsyncClient`, è necessario fornire la versione asincrona del client standard`DynamoDbAsyncClient`, come mostrato nel frammento seguente.

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

1. I metodi che restituiscono un singolo oggetto di dati restituiscono un `CompletableFuture` risultato anziché solo il risultato. L'applicazione può quindi eseguire altre operazioni senza dover bloccare il risultato. Il frammento seguente mostra il metodo `getItem()` asincrono. 

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

1. I metodi che restituiscono elenchi di risultati impaginati restituiscono un valore [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)anziché un valore restituito dalla modalità sincrona per [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)gli stessi metodi. `DynamoDbEnhanceClient` L'applicazione può quindi sottoscrivere un gestore a tale editore per gestire i risultati in modo asincrono senza dover bloccare.

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

   Per un esempio più completo di utilizzo di`SdkPublisher API`, consultate l'[esempio](ddb-en-client-use-multirecord.md#ddb-en-client-use-multirecord-scan-async) nella sezione che illustra il metodo `scan()` asincrono di questa guida.

# Annotazioni di classi di dati
<a name="ddb-en-client-anno-index"></a>

La tabella seguente elenca le annotazioni che possono essere utilizzate sulle classi di dati e fornisce collegamenti a informazioni ed esempi contenuti in questa guida. La tabella è ordinata in ordine alfabetico crescente in base al nome dell'annotazione.


**Annotazioni delle classi di dati utilizzate in questa guida**  

| Nome dell'annotazione | L'annotazione si applica a 1 | Cosa fa | Dove viene mostrato in questa guida | 
| --- | --- | --- | --- | 
| DynamoDbAtomicCounter | attributo 2 | Incrementa un attributo numerico con tag ogni volta che un record viene scritto nel database. | [Introduzione e discussione.](ddb-en-client-extensions.md#ddb-en-client-extensions-ACE) | 
| DynamoDbAttribute | attributo | Definisce o rinomina una proprietà del bean mappata a un attributo di tabella DynamoDB. |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbAutoGeneratedTimestampAttribute | attributo | Aggiorna un attributo taggato con un timestamp corrente ogni volta che l'elemento viene scritto correttamente nel database | [Introduzione e discussione.](ddb-en-client-extensions.md#ddb-en-client-extensions-AGTE) | 
| DynamoDbAutoGeneratedUuid | attributo | Genera un UUID (Universally Unique Identifier) univoco per un attributo quando un nuovo record viene scritto nel database. | [Introduzione e discussione.](ddb-en-client-extensions.md#ddb-en-client-extensions-AGUE) | 
| DynamoDbBean | classe | Contrassegna una classe di dati come mappabile su uno schema tabellare. | Primo utilizzo sulla [classe Customer nella sezione](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) Guida introduttiva. In tutta la guida sono presenti diversi utilizzi. | 
| DynamoDbConvertedBy | attributo | Associa un attributo personalizzato all'AttributeConverterattributo annotato. | [Discussione iniziale ed esempio.](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-single) | 
| DynamoDbFlatten | attributo | Appiattisce tutti gli attributi di una classe di dati DynamoDB separata e li aggiunge come attributi di primo livello al record che viene letto e scritto nel database.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnore | attributo |  Fa sì che l'attributo rimanga non mappato.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbIgnoreNulls | attributo | Impedisce il salvataggio degli attributi nulli degli oggetti annidati. DynamoDb  | [Discussioni ed esempi.](ddb-en-client-adv-features-ignore-null.md) | 
| DynamoDbImmutable | classe |  Contrassegna una classe di dati immutabile come mappabile su uno schema tabellare.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPartitionKey | attributo |  Contrassegna un attributo come chiave di partizione primaria (chiave hash) della tabella. DynamoDb  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbPreserveEmptyObject | attributo |  Speciifica che se non sono presenti dati per l'oggetto mappato all'attributo annotato, l'oggetto deve essere inizializzato con tutti i campi nulli.  | [Discussione ed esempi.](ddb-en-client-adv-features-empty.md) | 
| DynamoDbSecondaryPartitionKey | attributo |  Contrassegna un attributo come chiave di partizione per un indice secondario globale.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSecondarySortKey | attributo |  Contrassegna un attributo come chiave di ordinamento opzionale per un indice secondario globale o locale.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbSortKey | attributo |  Contrassegna un attributo come chiave di ordinamento primaria opzionale (chiave di intervallo).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/ddb-en-client-anno-index.html)  | 
| DynamoDbUpdateBehavior | attributo |  Specifica il comportamento quando questo attributo viene aggiornato come parte di un'operazione di 'aggiornamento' come UpdateItem.  | [Introduzione ed esempio.](ddb-en-client-adv-features-upd-behavior.md) | 
| DynamoDbVersionAttribute | attributo | Incrementa il numero di versione di un articolo. | [Introduzione e discussione.](ddb-en-client-extensions.md#ddb-en-client-extensions-VRE) | 

1 È possibile applicare un'annotazione a livello di attributo al getter o al setter, ma non a entrambi. Questa guida mostra le annotazioni sui getter.

2 Il termine `property` viene normalmente utilizzato per un valore incapsulato in una classe di dati. JavaBean Tuttavia, questa guida utilizza `attribute` invece il termine, per coerenza con la terminologia utilizzata da DynamoDB.

# Lavora con Amazon EC2
<a name="examples-ec2"></a>

Questa sezione fornisce esempi di programmazione [Amazon EC2](https://docs.aws.amazon.com/ec2/)che utilizzano il AWS SDK per Java 2.x.

**Topics**
+ [Gestione delle Amazon EC2 istanze](examples-ec2-instances.md)
+ [Zone Regioni AWS di utilizzo e disponibilità](examples-ec2-regions-zones.md)
+ [Collabora con i gruppi di sicurezza in Amazon EC2](examples-ec2-security-groups.md)
+ [Lavora con i metadati delle istanze Amazon EC2](examples-ec2-IMDS.md)

# Gestione delle Amazon EC2 istanze
<a name="examples-ec2-instances"></a>

## Creare un'istanza
<a name="create-an-instance"></a>

Crea una nuova Amazon EC2 istanza chiamando il [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))metodo di [Ec2Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html), fornendogli una Amazon Machine Image (AMI) [RunInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesRequest.html)contenente l'[Amazon Machine Image (AMI)](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/AMIs.html) da utilizzare e un tipo di [istanza](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/instance-types.html).

 **Importazioni** 

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

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateInstance.java) su. GitHub

## Avviare un'istanza
<a name="start-an-instance"></a>

Per avviare un' Amazon EC2 istanza, chiama il [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))metodo di Ec2Client, fornendogli un file [StartInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StartInstancesRequest.html)contenente l'ID dell'istanza da avviare.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) su. GitHub

## Arrestare un'istanza
<a name="stop-an-instance"></a>

Per fermare un' Amazon EC2 istanza, chiama il [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))metodo di Ec2Client, fornendogli un file [StopInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/StopInstancesRequest.html)contenente l'ID dell'istanza da interrompere.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/StartStopInstance.java) su. GitHub

## Riavviare un'istanza
<a name="reboot-an-instance"></a>

Per riavviare un' Amazon EC2 istanza, chiama il [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))metodo di Ec2Client, fornendogli un file [RebootInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RebootInstancesRequest.html)contenente l'ID dell'istanza da riavviare.

 **Importazioni** 

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

 **Codice** 

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

[Vedi l'esempio completo su.](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/RebootInstance.java) GitHub

## Descrivere le istanze
<a name="describe-instances"></a>

Per elencare le tue istanze, crea un metodo [DescribeInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesRequest.html)e chiama il metodo di 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)) Restituirà un [DescribeInstancesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeInstancesResponse.html)oggetto che puoi utilizzare per elencare le Amazon EC2 istanze del tuo account e della tua regione.

Le istanze sono raggruppate in base alla *prenotazione*. Ogni prenotazione corrisponde alla chiamata a `startInstances` che ha avviato l'istanza. Per elencare le istanze, devi prima chiamare il metodo `reservations` della classe `DescribeInstancesResponse` e quindi chiamare `instances` su ciascun oggetto [Reservation](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Reservation.html) restituito.

 **Importazioni** 

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

 **Codice** 

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

I risultati vengono paginati; puoi ottenere altri risultati passando il valore restituito dal metodo `nextToken` dell'oggetto risultante a un nuovo metodo `nextToken` dell'oggetto richiesta e utilizzando il nuovo oggetto richiesta nella chiamata successiva a `describeInstances`.

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeInstances.java) su. GitHub

## Monitorare un'istanza
<a name="monitor-an-instance"></a>

È possibile monitorare vari aspetti delle Amazon EC2 istanze, come l'utilizzo della CPU e della rete, la memoria disponibile e lo spazio rimanente su disco. Per ulteriori informazioni sul monitoraggio delle istanze, consulta [Monitoraggio Amazon EC2](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/monitoring_ec2.html) nella Guida per l' Amazon EC2 utente delle istanze Linux.

Per iniziare a monitorare un'istanza, è necessario crearne un'[MonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/MonitorInstancesRequest.html)con l'ID dell'istanza da monitorare e passarla al metodo di 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))

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) su. GitHub

## Arrestare il monitoraggio delle istanze
<a name="stop-instance-monitoring"></a>

Per interrompere il monitoraggio di un'istanza, creane un'istanza [UnmonitorInstancesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/UnmonitorInstancesRequest.html)con l'ID dell'istanza per interrompere il monitoraggio e passala al metodo di [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))Ec2Client.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/ec2/src/main/java/com/example/ec2/MonitorInstance.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html)nell' Amazon EC2 API Reference
+  [DescribeInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html)nell' Amazon EC2 API Reference
+  [StartInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StartInstances.html)nell' Amazon EC2 API Reference
+  [StopInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StopInstances.html)nell' Amazon EC2 API Reference
+  [RebootInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RebootInstances.html)nell' Amazon EC2 API Reference
+  [MonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_MonitorInstances.html)nell' Amazon EC2 API Reference
+  [UnmonitorInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_UnmonitorInstances.html)nell' Amazon EC2 API Reference

# Zone Regioni AWS di utilizzo e disponibilità
<a name="examples-ec2-regions-zones"></a>

## Descrivere le regioni
<a name="describe-regions"></a>

Per elencare le regioni disponibili per il tuo account, chiama il metodo di Ec2Client. `describeRegions` Restituisce [DescribeRegionsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeRegionsResponse.html). Chiamare il metodo `regions` dell'oggetto restituito per ottenere un elenco di oggetti [Region](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/Region.html) che rappresentano ciascuna regione.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) su. GitHub

## Descrivere le zone di disponibilità
<a name="describe-availability-zones"></a>

Per elencare ogni zona di disponibilità disponibile per il tuo account, chiama il metodo di Ec2Client. `describeAvailabilityZones` Restituisce [DescribeAvailabilityZonesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAvailabilityZonesResponse.html). Chiama il suo `availabilityZones` metodo per ottenere un elenco di [AvailabilityZone](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AvailabilityZone.html)oggetti che rappresentano ogni zona di disponibilità.

 **Importazioni** 

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

 **Codice** 

Crea Ec2Client.

```
        Ec2AsyncClient ec2AsyncClient = Ec2AsyncClient.builder()
            .region(Region.US_EAST_1)
            .build();
```

Quindi chiama describeAvailabilityZones () e recupera i risultati.

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeRegionsAndZones.java) su. GitHub

## Descrivere gli account
<a name="describe-accounts"></a>

Per elencare le informazioni EC2 relative al tuo account, chiama il metodo di Ec2Client. `describeAccountAttributes` Questo metodo restituisce un oggetto. [DescribeAccountAttributesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeAccountAttributesResponse.html) Invoca questo `accountAttributes` metodo degli oggetti per ottenere un elenco di [AccountAttribute](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttribute.html)oggetti. È possibile scorrere l'elenco per recuperare un oggetto. `AccountAttribute`

Puoi ottenere i valori degli attributi del tuo account richiamando il metodo dell'`AccountAttribute`oggetto. `attributeValues` Questo metodo restituisce un elenco di [AccountAttributeValue](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AccountAttributeValue.html)oggetti. È possibile scorrere questo secondo elenco per visualizzare il valore degli attributi (vedere l'esempio di codice riportato di seguito).

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeAccount.java) su GitHub.

## Ulteriori informazioni
<a name="more-information"></a>
+  [Regioni e zone di disponibilità](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/using-regions-availability-zones.html) nella Guida per l' Amazon EC2 utente per le istanze Linux
+  [DescribeRegions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html)nel riferimento alle Amazon EC2 API
+  [DescribeAvailabilityZones](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAvailabilityZones.html)nell' Amazon EC2 API Reference

# Collabora con i gruppi di sicurezza in Amazon EC2
<a name="examples-ec2-security-groups"></a>

## Creazione di un gruppo di sicurezza
<a name="create-a-security-group"></a>

Per creare un gruppo di sicurezza, chiama il `createSecurityGroup` metodo di Ec2Client con un [CreateSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/CreateSecurityGroupRequest.html)che contiene il nome della chiave.

 **Importazioni** 

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

 **Codice** 

```
            CreateSecurityGroupRequest createRequest = CreateSecurityGroupRequest.builder()
                .groupName(groupName)
                .description(groupDesc)
                .vpcId(vpcId)
                .build();

            CreateSecurityGroupResponse resp= ec2.createSecurityGroup(createRequest);
```

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) su. GitHub

## Configurare un gruppo di sicurezza
<a name="configure-a-security-group"></a>

Un gruppo di sicurezza può controllare sia il traffico in entrata (ingresso) che quello in uscita (in uscita) verso le tue istanze. Amazon EC2 

Per aggiungere regole di ingresso al tuo gruppo di sicurezza, usa il `authorizeSecurityGroupIngress` metodo di Ec2Client, fornendo il nome del gruppo di sicurezza e le regole di accesso ([IpPermission](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/IpPermission.html)) che desideri assegnargli all'interno di un oggetto. [AuthorizeSecurityGroupIngressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupIngressRequest.html) Nell'esempio seguente viene mostrato come aggiungere autorizzazioni IP a un gruppo di sicurezza.

 **Importazioni** 

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

 **Codice** 

Innanzitutto, crea un Ec2Client

```
        Region region = Region.US_WEST_2;
        Ec2Client ec2 = Ec2Client.builder()
                .region(region)
                .build();
```

Quindi usa il metodo di 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 "";
    }
```

Per aggiungere una regola di uscita al gruppo di sicurezza, fornisci dati simili in un metodo di [AuthorizeSecurityGroupEgressRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/AuthorizeSecurityGroupEgressRequest.html)Ec2Client. `authorizeSecurityGroupEgress`

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/CreateSecurityGroup.java) su. GitHub

## Descrivere i gruppi di sicurezza
<a name="describe-security-groups"></a>

Per descrivere i tuoi gruppi di sicurezza o ottenere informazioni su di essi, chiama il metodo di `describeSecurityGroups` Ec2Client. Restituisce un [DescribeSecurityGroupsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DescribeSecurityGroupsResponse.html)comando che puoi usare per accedere all'elenco dei gruppi di sicurezza chiamando il relativo `securityGroups` metodo, che restituisce un elenco di [SecurityGroup](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/SecurityGroup.html)oggetti.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DescribeSecurityGroups.java) su GitHub.

## Eliminare un gruppo di sicurezza
<a name="delete-a-security-group"></a>

Per eliminare un gruppo di sicurezza, chiama il `deleteSecurityGroup` metodo di Ec2Client, passandogli un gruppo di sicurezza [DeleteSecurityGroupRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/DeleteSecurityGroupRequest.html)che contiene l'ID del gruppo di sicurezza da eliminare.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/ec2/src/main/java/com/example/ec2/DeleteSecurityGroup.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Amazon EC2 Gruppi di sicurezza](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html) nella Guida per l' Amazon EC2 utente per le istanze Linux
+  [Autorizza il traffico in entrata per le tue istanze Linux nella Guida per l' Amazon EC2 utente per le istanze](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html) Linux
+  [CreateSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateSecurityGroup.html)nella guida di riferimento alle API Amazon EC2 
+  [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)nell' Amazon EC2 API Reference
+  [DeleteSecurityGroup](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteSecurityGroup.html)nell' Amazon EC2 API Reference
+  [AuthorizeSecurityGroupIngress](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AuthorizeSecurityGroupIngress.html)nell' Amazon EC2 API Reference

# Lavora con i metadati delle istanze Amazon EC2
<a name="examples-ec2-IMDS"></a>

Un client Java SDK per Amazon EC2 Instance Metadata Service (client di metadati) consente alle applicazioni di accedere ai metadati sulla loro istanza EC2 locale. Il client di metadati funziona con l'istanza locale di [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)(Instance Metadata Service v2) e utilizza richieste orientate alla sessione. 

Nell'SDK sono disponibili due classi di client. Il sincrono `[Ec2MetadataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataClient.html)` serve per bloccare le operazioni e l'altro per i casi d'uso asincroni e [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)non bloccanti. 

## Nozioni di base
<a name="examples-ec2-IMDS-getstarted"></a>

Per utilizzare il client di metadati, aggiungi l'artefatto Maven al tuo progetto`imds`. Sono inoltre necessarie classi per un `[SdkHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/SdkHttpClient.html)` (o un `[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)` per la variante asincrona) sul classpath. 

Il seguente codice XML Maven mostra i frammenti di dipendenza per l'utilizzo del sincrono insieme alla dipendenza per i client di metadati. [UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)

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

Cerca nel repository centrale di [Maven la versione più recente](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) dell'artefatto. `bom`

Per utilizzare un client HTTP asincrono, sostituisci lo snippet di dipendenza per l'artefatto. `url-connection-client` Ad esempio, il seguente frammento introduce l'implementazione. [NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>netty-nio-client</artifactId>
    </dependency>
```

## Usa il client di metadati
<a name="examples-ec2-IMDS-use"></a>

### Crea un'istanza di un client di metadati
<a name="examples-ec2-IMDS-use-create"></a>

È possibile creare un'istanza di un sistema sincrono `Ec2MetadataClient` quando nel classpath è presente una sola implementazione dell'`SdkHttpClient`interfaccia. A tale scopo, chiamate il `Ec2MetadataClient#create()` metodo statico come illustrato nel frammento seguente. 

```
Ec2MetadataClient client = Ec2MetadataClient.create(); // 'Ec2MetadataAsyncClient#create' is the asynchronous version.
```

Se l'applicazione ha più implementazioni dell'`SdkHttpAsyncClient`interfaccia `SdkHttpClient` or, è necessario specificare un'implementazione da utilizzare per il client di metadati, come illustrato nella sezione. [Client HTTP configurabile](#examples-ec2-IMDS-features-http) 

**Nota**  
Per la maggior parte dei client di servizi, come Amazon S3, l'SDK for Java aggiunge automaticamente implementazioni dell'interfaccia or. `SdkHttpClient` `SdkHttpAsyncClient` Se il tuo client di metadati utilizza la stessa implementazione, funzionerà. `Ec2MetadataClient#create()` Se hai bisogno di un'implementazione diversa, devi specificarla quando crei il client di metadati.

### Inviare richieste
<a name="examples-ec2-IMDS-use-req"></a>

[Per recuperare i metadati dell'istanza, create un'istanza della `EC2MetadataClient` classe e chiamate il `get` metodo con un parametro path che specifica la categoria di metadati dell'istanza.](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)

L'esempio seguente stampa il valore associato alla chiave sulla console. `ami-id`

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

Se il percorso non è valido, il `get` metodo genera un'eccezione. 

Riutilizzate la stessa istanza del client per più richieste, ma chiamate `close` il client quando non è più necessario per rilasciare risorse. Dopo la chiamata del metodo close, l'istanza del client non può più essere utilizzata.

### Analizza le risposte
<a name="examples-ec2-IMDS-use-pares"></a>

I metadati delle istanze EC2 possono essere emessi in diversi formati. Il testo normale e il JSON sono i formati più utilizzati. I client di metadati offrono modi per lavorare con questi formati. 

Come illustrato nell'esempio seguente, utilizzate il `asString` metodo per ottenere i dati come stringa Java. È inoltre possibile utilizzare il `asList` metodo per separare una risposta in testo semplice che restituisce più righe. 

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/");
String fullResponse = response.asString();
List<String> splits = response.asList();
```

Se la risposta è in JSON, utilizzate il `Ec2MetadataResponse#asDocument` metodo per analizzare la risposta JSON in un'istanza [Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/Document.html), come mostrato nel seguente frammento di codice.

```
Document fullResponse = response.asDocument();
```

Verrà generata un'eccezione se il formato dei metadati non è in JSON. Se la risposta viene analizzata correttamente, puoi utilizzare l'[API del documento](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/package-summary.html) per esaminare la risposta in modo più dettagliato. Consulta la [tabella delle categorie di metadati](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html) delle istanze per scoprire quali categorie di metadati forniscono risposte in formato JSON.

## Configura un client di metadati
<a name="examples-ec2-IMDS-config"></a>

### Tentativi
<a name="examples-ec2-IMDS-config-retries"></a>

È possibile configurare un client di metadati con un meccanismo di ripetizione dei tentativi. In tal caso, il client può riprovare automaticamente le richieste che non vanno a buon fine per motivi imprevisti. Per impostazione predefinita, il client riprova tre volte in caso di richiesta non riuscita, con un tempo di backoff esponenziale tra un tentativo e l'altro.

Se il tuo caso d'uso richiede un meccanismo di ripetizione dei tentativi diverso, puoi personalizzare il client utilizzando il metodo del relativo generatore. `retryPolicy` Ad esempio, l'esempio seguente mostra un client sincrono configurato con un ritardo fisso di due secondi tra i tentativi e cinque tentativi.

```
BackoffStrategy fixedBackoffStrategy = FixedDelayBackoffStrategy.create(Duration.ofSeconds(2));
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .retryPolicy(retryPolicyBuilder -> retryPolicyBuilder.numRetries(5)
                                                                           .backoffStrategy(fixedBackoffStrategy))
                     .build();
```

Ce ne sono diversi [BackoffStrategies](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/package-summary.html)che è possibile utilizzare con un client di metadati.

Puoi anche disabilitare completamente il meccanismo di riprova, come mostra il seguente frammento.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                    .retryPolicy(Ec2MetadataRetryPolicy.none())
                    .build();
```

L'utilizzo `Ec2MetadataRetryPolicy#none()` disattiva la politica di riprova predefinita in modo che il client di metadati non tenti di ripetere i tentativi.

### Versione IP
<a name="examples-ec2-IMDS-config-ipversion"></a>

Per impostazione predefinita, un client di metadati utilizza l'endpoint in. IPV4 `http://169.254.169.254` Per modificare il client in modo che utilizzi la IPV6 versione, usa il metodo `endpointMode` o il `endpoint` metodo del generatore. Si verifica un'eccezione se entrambi i metodi vengono chiamati sul builder.

Gli esempi seguenti mostrano entrambe le IPV6 opzioni.

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpointMode(EndpointMode.IPV6)
                     .build();
```

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpoint(URI.create("http://[fd00:ec2::254]"))
                     .build();
```

## Funzionalità principali
<a name="examples-ec2-IMDS-features"></a>

### Client asincrono
<a name="examples-ec2-IMDS-features-async"></a>

Per utilizzare la versione non bloccante del client, crea un'istanza della classe. `Ec2MetadataAsyncClient` Il codice nell'esempio seguente crea un client asincrono con impostazioni predefinite e utilizza il `get` metodo per recuperare il valore della chiave. `ami-id`

```
Ec2MetadataAsyncClient asyncClient = Ec2MetadataAsyncClient.create();
CompletableFuture<Ec2MetadataResponse> response = asyncClient.get("/latest/meta-data/ami-id");
```

Il valore `java.util.concurrent.CompletableFuture` restituito dal `get` metodo viene completato quando viene restituita la risposta. L'esempio seguente stampa i `ami-id` metadati sulla console.

```
response.thenAccept(metadata -> System.out.println(metadata.asString()));
```

### Client HTTP configurabile
<a name="examples-ec2-IMDS-features-http"></a>

Il generatore di ogni client di metadati dispone di un `httpClient` metodo che puoi utilizzare per fornire un client HTTP personalizzato. 

L'esempio seguente mostra il codice per un'istanza personalizzata`UrlConnectionHttpClient`.

```
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'esempio seguente mostra il codice per un'`NettyNioAsyncHttpClient`istanza personalizzata con un client di metadati asincrono.

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

L'[Configurare i client HTTP in AWS SDK for Java 2.x](http-configuration.md)argomento di questa guida fornisce dettagli su come configurare i client HTTP disponibili nell'SDK for Java.

### Memorizzazione nella cache dei token
<a name="examples-ec2-IMDS-features-token"></a>

Poiché i client utilizzano i metadati IMDSv2, tutte le richieste sono associate a una sessione. Una sessione è definita da un token con scadenza, che il client di metadati gestisce per voi. Ogni richiesta di metadati riutilizza automaticamente il token fino alla scadenza. 

Per impostazione predefinita, un token dura sei ore (21.600 secondi). Ti consigliamo di mantenere il time-to-live valore predefinito, a meno che il tuo caso d'uso specifico non richieda una configurazione avanzata. 

Se necessario, configura la durata utilizzando il metodo `tokenTtl` builder. Ad esempio, il codice nel frammento seguente crea un client con una durata della sessione di cinque minuti. 

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .tokenTtl(Duration.ofMinutes(5))
                     .build();
```

Se omettete di chiamare il `tokenTtl` metodo sul builder, viene invece utilizzata la durata predefinita di 21.600. 

# Lavora con IAM
<a name="examples-iam"></a>

Questa sezione fornisce esempi di programmazione AWS Identity and Access Management (IAM) utilizzando la versione AWS SDK per Java 2.x.

 AWS Identity and Access Management (IAM) consente di controllare in modo sicuro l'accesso ai AWS servizi e alle risorse per gli utenti. Utilizzando IAM, è possibile creare e gestire AWS utenti e gruppi e utilizzare le autorizzazioni per consentire e negare il loro accesso alle risorse. AWS Per una guida completa IAM, consulta la Guida per l'[IAM utente](https://docs.aws.amazon.com//IAM/latest/UserGuide/introduction.html).

Gli esempi seguenti includono solo il codice necessario per dimostrare ciascuna tecnica. Il [codice di esempio completo è disponibile su GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Da qui puoi scaricare un singolo file sorgente o clonare l'archivio localmente per ottenere tutti gli esempi da creare ed eseguire.

**Topics**
+ [Gestire le chiavi di IAM accesso](examples-iam-access-keys.md)
+ [Gestisci IAM gli utenti](examples-iam-users.md)
+ [Creare policy IAM](feature-iam-policy-builder.md)
+ [Lavora con IAM le politiche](examples-iam-policies.md)
+ [Lavora con i certificati IAM del server](examples-iam-server-certificates.md)

# Gestire le chiavi di IAM accesso
<a name="examples-iam-access-keys"></a>

## Creare una chiave di accesso
<a name="create-an-access-key"></a>

Per creare una chiave di IAM accesso, chiama il `IamClient’s` `createAccessKey` metodo con 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)oggetto.

**Nota**  
È necessario impostare la regione su **AWS\$1GLOBAL**affinché `IamClient` le chiamate funzionino perché IAM si tratta di un servizio globale.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/CreateAccessKey.java) su GitHub.

## Elencare le chiavi di accesso
<a name="list-access-keys"></a>

Per elencare le chiavi di accesso per un determinato utente, create 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)oggetto che contenga il nome utente per cui elencare le chiavi e passatelo al `IamClient’s` `listAccessKeys` metodo.

**Nota**  
Se non fornite un nome utente a`listAccessKeys`, tenterà di elencare le chiavi di accesso associate a chi Account AWS ha firmato la richiesta.

 **Importazioni** 

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

 **Codice** 

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

I risultati di `listAccessKeys` sono paginati (con un massimo predefinito di 100 record per chiamata). È possibile richiamare `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)oggetto restituito per verificare se la query ha restituito un numero inferiore di risultati rispetto a quelli disponibili. In tal caso, chiama `marker` su `ListAccessKeysResponse` e utilizzalo durante la creazione di una nuova richiesta. Utilizza la nuova richiesta nella prossima invocazione di `listAccessKeys`.

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/ListAccessKeys.java) su GitHub.

## Recupero dell'ora ultimo utilizzo di una chiave di accesso
<a name="retrieve-an-access-key-s-last-used-time"></a>

Per sapere l'ora in cui è stata utilizzata l'ultima volta una chiave di accesso, chiamate il `IamClient’s` `getAccessKeyLastUsed` metodo con l'ID della chiave di accesso (che può essere passato utilizzando 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)oggetto).

È quindi possibile utilizzare 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)oggetto restituito per recuperare l'ultima ora utilizzata della chiave.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/AccessKeyLastUsed.java) su. GitHub

## Attivare o disattivare le chiavi di accesso
<a name="iam-access-keys-update"></a>

È possibile attivare o disattivare una chiave di accesso creando 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)oggetto, fornendo l'ID della chiave di accesso, facoltativamente il nome utente e quello desiderato [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), quindi passando l'oggetto della richiesta al `IamClient’s` `updateAccessKey` metodo.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/UpdateAccessKey.java) su. GitHub

## Eliminare una chiave di accesso
<a name="delete-an-access-key"></a>

Per eliminare definitivamente una chiave di accesso, chiamate il `IamClient’s` `deleteKey` metodo, fornendogli un codice [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)contenente l'ID e il nome utente della chiave di accesso.

**Nota**  
Dopo che è stata eliminata, una chiave non può più essere recuperata né utilizzata. Per disattivare temporaneamente una chiave in modo che possa essere riattivata in un secondo momento, usa invece [`updateAccessKey`](#iam-access-keys-update)method.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/iam/src/main/java/com/example/iam/DeleteAccessKey.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [CreateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html)nell' IAM API Reference
+  [ListAccessKeys](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html)nell' IAM API Reference
+  [GetAccessKeyLastUsed](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetAccessKeyLastUsed.html)nell' IAM API Reference
+  [UpdateAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html)nell' IAM API Reference
+  [DeleteAccessKey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html)nell' IAM API Reference

# Gestisci IAM gli utenti
<a name="examples-iam-users"></a>

## Creazione di un utente
<a name="creating-a-user"></a>

Crea un nuovo IAM utente fornendo il nome utente al `createUser` metodo IamClient's utilizzando un [CreateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreateUserRequest.html)oggetto contenente il nome utente.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/CreateUser.java) su GitHub.

## Creazione di elenchi sugli utenti
<a name="listing-users"></a>

Per elencare gli IAM utenti del tuo account, creane uno nuovo [ListUsersRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersRequest.html)e passalo al `listUsers` metodo IamClient's. È possibile recuperare l'elenco degli utenti `users` chiamando l'[ListUsersResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListUsersResponse.html)oggetto restituito.

L'elenco di utenti restituito da `listUsers` è paginato. È possibile verificare se ci sono più risultati da recuperare chiamando il metodo `isTruncated` dell'oggetto di risposta. Se viene restituito `true`, chiamare il metodo `marker()` dell'oggetto di risposta. Utilizza il valore del contrassegno per creare un nuovo oggetto di risposta. Quindi, chiama nuovamente il metodo `listUsers` con una nuova richiesta.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/ListUsers.java) su. GitHub

## Aggiorna un utente
<a name="updating-a-user"></a>

Per aggiornare un utente, chiamate il `updateUser` metodo dell' IamClient oggetto, che accetta un [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)oggetto che potete usare per modificare il *nome* o il *percorso* dell'utente.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/UpdateUser.java) su GitHub.

## Eliminazione di un utente
<a name="deleting-a-user"></a>

Per eliminare un utente, chiama la `deleteUser` richiesta IamClient's con un [UpdateUserRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateUserRequest.html)oggetto impostato con il nome utente da eliminare.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DeleteUser.java) su GitHub.

## Ulteriori informazioni
<a name="more-information"></a>
+  [IAM Utenti](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) nella Guida per l' IAM utente
+  [Gestione IAM degli utenti](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_manage.html) nella Guida IAM per l'utente
+  [CreateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html)nel riferimento alle IAM API
+  [ListUsers](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html)nell' IAM API Reference
+  [UpdateUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html)nell' IAM API Reference
+  [DeleteUser](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUser.html)nell' IAM API Reference

# Crea policy IAM con 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) è una libreria che puoi utilizzare per creare [policy IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) in Java e caricarle su AWS Identity and Access Management (IAM). 

Invece di creare una policy IAM assemblando manualmente una stringa JSON o leggendo un file, l'API fornisce un approccio lato client orientato agli oggetti per generare la stringa JSON. Quando leggi una policy IAM esistente in formato JSON, l'API la converte in un'istanza per la gestione. [IamPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.html)

L'API IAM Policy Builder è diventata disponibile con la versione 2.20.105 dell'SDK, quindi usa quella versione o una successiva nel tuo file di build di Maven. [Il numero di versione più recente dell'SDK è elencato su Maven Central.](https://central.sonatype.com/artifact/software.amazon.awssdk/iam-policy-builder)

Il seguente frammento mostra un esempio di blocco di dipendenza per un file Maven. `pom.xml` Ciò ti consente di utilizzare l'API IAM Policy Builder nel tuo progetto. 

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>iam-policy-builder</artifactId>
    <version>2.27.21</version>
</dependency>
```

## Creazione di un `IamPolicy`
<a name="iam-policy-builder-create"></a>

Questa sezione mostra diversi esempi di come creare policy utilizzando l'API IAM Policy Builder.

In ciascuno degli esempi seguenti, inizia con `[IamPolicy.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.Builder.html)` e aggiungi una o più istruzioni utilizzando il `addStatement` metodo. Seguendo questo schema, [IamStatement.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamStatement.Builder.html) dispone di metodi per aggiungere effetti, azioni, risorse e condizioni all'istruzione.

### Esempio: creare una politica basata sul tempo
<a name="iam-policy-builder-create-ex-time-based"></a>

L'esempio seguente crea una policy basata sull'identità che consente l'azione di Amazon DynamoDB tra due momenti temporali. `GetItem`

```
    public String timeBasedPolicyExample() {
        IamPolicy policy = IamPolicy.builder()
                .addStatement(b -> b
                        .effect(IamEffect.ALLOW)
                        .addAction("dynamodb:GetItem")
                        .addResource(IamResource.ALL)
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.DATE_GREATER_THAN)
                                .key("aws:CurrentTime")
                                .value("2020-04-01T00:00:00Z"))
                        .addCondition(b1 -> b1
                                .operator(IamConditionOperator.DATE_LESS_THAN)
                                .key("aws:CurrentTime")
                                .value("2020-06-30T23:59:59Z")))
                .build();

        // Use an IamPolicyWriter to write out the JSON string to a more readable format.
        return policy.toJson(IamPolicyWriter.builder()
                        .prettyPrint(true)
                        .build());
    }
```

#### Output JSON
<a name="iam-builder-ex-json-date"></a>

L'ultima istruzione dell'esempio precedente restituisce la seguente stringa JSON. 

Ulteriori informazioni su questo [esempio sono disponibili](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws-dates.html) nella *Guida per l'AWS Identity and Access Management utente*.

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

------

### Esempio: specificare più condizioni
<a name="iam-policy-builder-create-ex-multi-conditions"></a>

L'esempio seguente mostra come creare una policy basata sull'identità che consenta l'accesso a specifici attributi di DynamoDB. La policy contiene due condizioni.

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

#### Output JSON
<a name="iam-builder-ex-json-multi-cond"></a>

L'ultima istruzione dell'esempio precedente restituisce la seguente stringa JSON. 

Ulteriori informazioni su questo [esempio sono disponibili](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_dynamodb_attributes.html) nella *Guida per l'AWS Identity and Access Management utente*.

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

------

### Esempio: specificare i principi
<a name="iam-policy-builder-create-ex-principals"></a>

L'esempio seguente mostra come creare una politica basata sulle risorse che neghi l'accesso a un bucket a tutti i principali ad eccezione di quelli specificati nella condizione.

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

#### Output JSON
<a name="iam-policy-builder-create-json-ex-principals"></a>

L'ultima istruzione dell'esempio precedente restituisce la seguente stringa JSON. 

Ulteriori informazioni su questo [esempio sono disponibili](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-anonymous) nella *Guida per l'AWS Identity and Access Management utente*.

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

------

### Esempio: consentire l'accesso su più account
<a name="iam-policy-builder-create-ex-cross-account"></a>

L'esempio seguente mostra come consentire Account AWS a un altro utente di caricare oggetti nel tuo bucket mantenendo il pieno controllo del proprietario degli oggetti caricati. 

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

#### Output JSON
<a name="iam-policy-builder-create-ex-json-cross-account"></a>

L'ultima istruzione dell'esempio precedente restituisce la seguente stringa JSON. 

Scopri di più su questo [esempio](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-acl-2) nella *Amazon Simple Storage Service User Guide*.

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

------

## Usa un `IamPolicy` con IAM
<a name="iam-policy-builder-work-with-service"></a>

Dopo aver creato un'`IamPolicy`istanza, usi 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)per lavorare con il servizio IAM. 

L'esempio seguente crea una policy che consente a un'[identità IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html) di scrivere elementi in una tabella DynamoDB nell'account specificato con il parametro. `accountID` La policy viene quindi caricata su IAM come stringa 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'esempio successivo si basa sull'esempio precedente. Il codice scarica la policy e la utilizza come base per una nuova policy copiando e alterando la dichiarazione. La nuova politica viene quindi caricata.

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

Gli esempi precedenti utilizzano un `IamClient` argomento creato come illustrato nel frammento seguente.

```
IamClient iam = IamClient.builder().region(Region.AWS_GLOBAL).build();
```

### Politiche in JSON
<a name="iam-policy-builder-work-with-serivce-json"></a>

Gli esempi restituiscono le seguenti stringhe JSON.

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

# Lavora con IAM le politiche
<a name="examples-iam-policies"></a>

## Creazione di una policy
<a name="create-a-policy"></a>

Per creare una nuova policy, fornisci il nome della policy e un documento di policy in formato JSON utilizzando un [CreatePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/CreatePolicyRequest.html)metodo to the's. IamClient `createPolicy`

 **Importazioni** 

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

 **Codice** 

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

[Vedi l'esempio completo su.](https://github.com/awsdocs/aws-doc-sdk-examples/blob/e41bacfd5e671e7ef1a9f73e972540dc6a434664/javav2/example_code/iam/src/main/java/com/example/iam/CreatePolicy.java) GitHub

## Ottenere una policy
<a name="get-a-policy"></a>

Per recuperare una policy esistente, chiamate il `getPolicy` metodo IamClient's, fornendo l'ARN della policy all'interno [GetPolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetPolicyRequest.html)di un oggetto.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/GetPolicy.java) su. GitHub

## Allegare una policy dei ruoli
<a name="attach-a-role-policy"></a>

Puoi allegare una policy a un IAM [ruolo](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) chiamando il `attachRolePolicy` metodo IamClient th's, fornendogli il nome del ruolo e l'ARN della policy in un. [AttachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/AttachRolePolicyRequest.html)

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) su. GitHub

## Elencare le policy dei ruoli collegate
<a name="list-attached-role-policies"></a>

Elenca le politiche allegate su un ruolo chiamando il `listAttachedRolePolicies` metodo IamClient's. È necessario un [ListAttachedRolePoliciesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesRequest.html)oggetto che contenga il nome del ruolo per cui elencare le politiche.

Richiama `getAttachedPolicies` l'[ListAttachedRolePoliciesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListAttachedRolePoliciesResponse.html)oggetto restituito per ottenere l'elenco delle politiche allegate. I risultati possono essere troncati; se il metodo `ListAttachedRolePoliciesResponse` dell'oggetto `isTruncated` restituisce `true`, chiama il metodo `ListAttachedRolePoliciesResponse` dell'oggetto `marker`. Utilizza il contrassegno restituito per creare una nuova richiesta e utilizzala per chiamare nuovamente `listAttachedRolePolicies` per ottenere il batch di risultati successivo.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/AttachRolePolicy.java) su GitHub.

## Scollegare una policy dei ruoli
<a name="detach-a-role-policy"></a>

Per scollegare una policy da un ruolo, chiamate il `detachRolePolicy` metodo IamClient th's, fornendogli il nome del ruolo e l'ARN della policy in a. [DetachRolePolicyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DetachRolePolicyRequest.html)

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/iam/src/main/java/com/example/iam/DetachRolePolicy.java) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [Panoramica delle IAM politiche](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) nella Guida per l' IAM utente.
+ [AWS Riferimento alla politica IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) nella Guida IAM per l'utente.
+  [CreatePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html)nell' IAM API Reference
+  [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html)nell' IAM API Reference
+  [AttachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_AttachRolePolicy.html)nell' IAM API Reference
+  [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)nell' IAM API Reference
+  [DetachRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DetachRolePolicy.html)nell' IAM API Reference

# Lavora con i certificati IAM del server
<a name="examples-iam-server-certificates"></a>

Per abilitare le connessioni HTTPS al tuo sito Web o alla tua applicazione AWS, devi disporre di un *certificato SSL/TLS del server*. È possibile utilizzare un certificato server fornito da AWS Certificate Manager o ottenuto da un provider esterno.

Si consiglia di ACM utilizzarlo per fornire, gestire e distribuire i certificati del server. Con ACM puoi richiedere un certificato, distribuirlo nelle tue AWS risorse e lasciare che ACM gestisca i rinnovi dei certificati al posto tuo. I certificati forniti da ACM sono gratuiti. Per ulteriori informazioni in merito ACM, consulta la [Guida AWS Certificate Manager per l'utente](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html).

## Recupero di un certificato del server
<a name="get-a-server-certificate"></a>

È possibile recuperare un certificato del server chiamando il `getServerCertificate` metodo IamClient's e passandolo [GetServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/GetServerCertificateRequest.html)con il nome del certificato.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/GetServerCertificate.java) su. GitHub

## Elencare i certificati del server
<a name="list-server-certificates"></a>

Per elencare i certificati del tuo server, chiama il `listServerCertificates` metodo IamClient's con un [ListServerCertificatesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesRequest.html). Restituisce [ListServerCertificatesResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ListServerCertificatesResponse.html).

Chiama il `serverCertificateMetadataList` metodo dell'`ListServerCertificateResponse`oggetto restituito per ottenere un elenco di [ServerCertificateMetadata](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/ServerCertificateMetadata.html)oggetti che puoi utilizzare per ottenere informazioni su ciascun certificato.

I risultati possono essere troncati; se il metodo `ListServerCertificateResponse` dell'oggetto `isTruncated` restituisce `true`, chiamare il metodo `ListServerCertificatesResponse` dell'oggetto `marker` e utilizzare il contrassegno per creare una nuova richiesta. Utilizza la nuova richiesta per chiamare nuovamente `listServerCertificates` per ottenere il batch di risultati successivo.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/ListServerCertificates.java) su GitHub.

## Aggiornamento di un certificato del server
<a name="update-a-server-certificate"></a>

È possibile aggiornare il nome o il percorso di un certificato del server chiamando il `updateServerCertificate` metodo IamClient's. Richiede un [UpdateServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/UpdateServerCertificateRequest.html)oggetto impostato con il nome corrente del certificato del server e un nuovo nome o un nuovo percorso da utilizzare.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/UpdateServerCertificate.java) su GitHub.

## Eliminazione di un certificato del server
<a name="delete-a-server-certificate"></a>

Per eliminare un certificato del server, chiama il `deleteServerCertificate` metodo IamClient's con un [DeleteServerCertificateRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iam/model/DeleteServerCertificateRequest.html)contenente il nome del certificato.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/0b1785e42949ebf959eaa0f0da4dc2a48f92ea25/javav2/example_code/iam/src/main/java/com/example/iam/DeleteServerCertificate.java) su GitHub.

## Ulteriori informazioni
<a name="more-information"></a>
+  [Utilizzo dei certificati server](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_server-certs.html) nella Guida per l' IAM utente
+  [GetServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetServerCertificate.html)nell' IAM API Reference
+  [ListServerCertificates](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListServerCertificates.html)nell' IAM API Reference
+  [UpdateServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateServerCertificate.html)nell' IAM API Reference
+  [DeleteServerCertificate](https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteServerCertificate.html)nell' IAM API Reference
+  [AWS Certificate Manager Guida per l'utente](https://docs.aws.amazon.com/acm/latest/userguide/) 

# Lavora con Kinesis
<a name="examples-kinesis"></a>

Questa sezione fornisce esempi di programmazione [Amazon Kinesis](https://docs.aws.amazon.com/kinesis/)con AWS SDK per Java 2.x.

Per ulteriori informazioni in merito Kinesis, consulta la [Guida per gli Amazon Kinesis sviluppatori](https://docs.aws.amazon.com/streams/latest/dev/introduction.html).

Gli esempi seguenti includono solo il codice necessario per dimostrare ciascuna tecnica. Il [codice di esempio completo è disponibile su GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2). Da qui puoi scaricare un singolo file sorgente o clonare l'archivio localmente per ottenere tutti gli esempi da creare ed eseguire.

**Topics**
+ [Iscriviti a Amazon Kinesis Data Streams](examples-kinesis-stream.md)

# Iscriviti a Amazon Kinesis Data Streams
<a name="examples-kinesis-stream"></a>

Gli esempi seguenti mostrano come recuperare ed elaborare i Amazon Kinesis dati da Data Streams utilizzando il metodo. `subscribeToShard` Kinesis Data Streams ora utilizza la funzionalità fanout avanzata e un'API di recupero dati HTTP/2 a bassa latenza, che facilita agli sviluppatori l'esecuzione di più applicazioni a bassa latenza e ad alte prestazioni sullo stesso Data Stream. Kinesis 

## Configurazione
<a name="set-up"></a>

Innanzitutto, [SubscribeToShardRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardRequest.html)crea un client asincrono e un oggetto. Kinesis Questi oggetti vengono utilizzati in ciascuno degli esempi seguenti per sottoscrivere gli eventi. Kinesis 

 **Importazioni** 

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

 **Codice** 

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

## Usa l'interfaccia Builder
<a name="use-the-builder-interface"></a>

È possibile utilizzare il `builder` metodo per semplificare la creazione di. [SubscribeToShardResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.html)

Utilizzando il generatore, è possibile impostare la richiamata del ciclo di vita con una chiamata al metodo invece che implementando l'interfaccia completa.

 **Codice** 

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

Per un maggiore controllo del publisher, è possibile utilizzare il metodo `publisherTransformer` per personalizzare il publisher.

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) su GitHub.

## Usa un gestore di risposte personalizzato
<a name="use-a-custom-response-handler"></a>

Per il pieno controllo dell'abbonato e dell'editore, implementa l'`SubscribeToShardResponseHandler`interfaccia.

In questo esempio implementi il metodo `onEventStream`, che ti consente l'accesso completo al publisher. Questo dimostra come trasformare il publisher in record di eventi da stampare da parte del sottoscrittore.

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) su. GitHub

## Usa l'interfaccia per i visitatori
<a name="use-the-visitor-interface"></a>

È possibile utilizzare un oggetto [Visitatore](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/SubscribeToShardResponseHandler.Visitor.html) per iscriverti a eventi specifici che ti interessa guardare.

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) su GitHub.

## Usa un abbonato personalizzato
<a name="use-a-custom-subscriber"></a>

Puoi anche implementare i tuoi sottoscrittori personalizzati per iscriverti al flusso.

Questo frammento di codice mostra un esempio di sottoscrittore.

 **Codice** 

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

È possibile passare l'abbonato personalizzato al `subscribe` metodo come illustrato nel seguente frammento di codice.

 **Codice** 

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

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamEx.java) su. GitHub

## Scrivi i record di dati in un flusso di Kinesis dati
<a name="write-data-records-into-a-kinesis-data-stream"></a>

È possibile utilizzare l'[KinesisClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/KinesisClient.html)oggetto per scrivere record di dati in un flusso di Kinesis dati utilizzando il `putRecords` metodo. Per richiamare correttamente questo metodo, create un [PutRecordsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kinesis/model/PutRecordsRequest.html)oggetto. Si passa il nome del flusso di dati al `streamName` metodo. Inoltre devi passare i dati utilizzando il metodo `putRecords` (come mostrato nell'esempio di codice seguente).

 **Importazioni** 

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

Nel seguente esempio di codice Java, notate che l'**StockTrade**oggetto viene utilizzato come dati da scrivere nel flusso di Kinesis dati. Prima di eseguire questo esempio, assicuratevi di aver creato il flusso di dati.

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/kinesis/src/main/java/com/example/kinesis/StockTradesWriter.java) su GitHub.

## Usa una libreria di terze parti
<a name="use-a-third-party-library"></a>

Puoi utilizzare altre librerie di terze parti anziché implementare un sottoscrittore personalizzato. Questo esempio dimostra l'utilizzo dell' RxJava implementazione, ma è possibile utilizzare qualsiasi libreria che implementa le interfacce Reactive Streams. Vedi la [pagina RxJava wiki su Github per ulteriori informazioni su](https://github.com/ReactiveX/RxJava/wiki) quella libreria.

Per utilizzare la libreria, aggiungerla come una dipendenza. Se stai utilizzando Maven, l'esempio illustra lo snippet POM da utilizzare.

 **Voce POM** 

```
<dependency>
 <groupId>io.reactivex.rxjava2</groupId>
 <artifactId>rxjava</artifactId>
 <version>2.2.21</version>
</dependency>
```

 **Importazioni** 

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

Questo esempio utilizza RxJava il metodo `onEventStream` lifecycle. In questo modo hai pieno accesso al publisher, che può essere utilizzato per creare un Rx Flowable.

 **Codice** 

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

Puoi anche utilizzare il metodo `publisherTransformer` con il publisher `Flowable`. È necessario adattare l'`Flowable`editore a un *SdkPublisher*, come illustrato nell'esempio seguente.

 **Codice** 

```
        SubscribeToShardResponseHandler responseHandler = SubscribeToShardResponseHandler
            .builder()
            .onError(t -> System.err.println("Error during stream - " + t.getMessage()))
            .publisherTransformer(p -> SdkPublisher.adapt(Flowable.fromPublisher(p).limit(100)))
            .build();
```

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/kinesis/src/main/java/com/example/kinesis/KinesisStreamRxJavaEx.java) su GitHub.

## Ulteriori informazioni
<a name="more-information"></a>
+  [SubscribeToShardEvent](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShardEvent.html)nell' Amazon Kinesis API Reference
+  [SubscribeToShard](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_SubscribeToShard.html)nell' Amazon Kinesis API Reference

# Funzioni di richiamo, elenco ed eliminazione AWS Lambda
<a name="examples-lambda"></a>

Questa sezione fornisce esempi di programmazione con il client di Lambda servizio utilizzando AWS SDK per Java 2.x.

**Topics**
+ [Invocazione di una funzione Lambda.](#invoke-function)
+ [Elenca le funzioni Lambda](#list-function)
+ [Eliminazione di una funzione Lambda](#delete-function)

## Invocazione di una funzione Lambda.
<a name="invoke-function"></a>

È possibile richiamare una Lambda funzione creando 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)oggetto e richiamando il relativo metodo. `invoke` Create 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)oggetto per specificare informazioni aggiuntive come il nome della funzione e il payload da passare alla funzione. Lambda I nomi delle funzioni vengono visualizzati come *arn:aws:lambda:us-east- 1:123456789012:function*:. HelloFunction È possibile recuperare il valore osservando la funzione in. Console di gestione AWS

Per passare i dati del payload a una funzione, create 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)oggetto che contenga informazioni. Nell'esempio di codice riportato di seguito, notare i dati JSON passati alla funzione Lambda .

 **Importazioni** 

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

 **Codice** 

Il seguente esempio di codice mostra come richiamare una funzione. Lambda 

```
    public static void invokeFunction(LambdaClient awsLambda, String functionName) {

         InvokeResponse res = null ;
        try {
            //Need a SdkBytes instance for the payload
            String json = "{\"Hello \":\"Paris\"}";
            SdkBytes payload = SdkBytes.fromUtf8String(json) ;

            //Setup an InvokeRequest
            InvokeRequest request = InvokeRequest.builder()
                    .functionName(functionName)
                    .payload(payload)
                    .build();

            res = awsLambda.invoke(request);
            String value = res.payload().asUtf8String() ;
            System.out.println(value);

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/LambdaInvoke.java) su. GitHub

## Elenca le funzioni Lambda
<a name="list-function"></a>

Costruisci un `[Lambda Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/lambda/LambdaClient.html)` oggetto e invoca il suo `listFunctions` metodo. Questo metodo restituisce 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)oggetto. È possibile richiamare il `functions` metodo di questo oggetto per restituire un elenco di [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)oggetti. È possibile scorrere l'elenco per recuperare informazioni sulle funzioni. Il seguente esempio di codice Java mostra come ottenere i nomi di ogni funzione.

 **Importazioni** 

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

 **Codice** 

Nell'esempio di codice Java riportato di seguito viene illustrato come recuperare un elenco di nomi di funzioni.

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/ListLambdaFunctions.java) su. GitHub

## Eliminazione di una funzione Lambda
<a name="delete-function"></a>

Costruisci 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)oggetto e invoca il suo `deleteFunction` metodo. Crea 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)oggetto e passalo al `deleteFunction` metodo. Questo oggetto contiene informazioni quali il nome della funzione da eliminare. I nomi delle funzioni vengono visualizzati come *arn:aws:lambda:us-east- 1:123456789012:function*:. HelloFunction È possibile recuperare il valore osservando la funzione in. Console di gestione AWS

 **Importazioni** 

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

 **Codice** 

Il seguente codice Java mostra come eliminare una Lambda funzione.

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/lambda/src/main/java/com/example/lambda/DeleteFunction.java) su. GitHub

# Funziona con Amazon S3
<a name="examples-s3"></a>

Questa sezione fornisce informazioni di base per lavorare con Amazon S3 utilizzando. AWS SDK for Java 2.x Questa sezione completa gli esempi di [Amazon S3 Java v2](java_s3_code_examples.md) presentati nella sezione Esempi di *codice di* questa guida.

## Client S3 in AWS SDK for Java 2.x
<a name="s3-clients"></a>

 AWS SDK for Java 2.x Fornisce diversi tipi di client S3. La tabella seguente mostra le differenze e può aiutarti a decidere qual è la soluzione migliore per i tuoi casi d'uso.


**Diverse versioni di client Amazon S3**  

| Client S3 | Breve descrizione | Quando utilizzare | Limitazione/inconveniente | 
| --- | --- | --- | --- | 
|  **AWS Client S3 basato su CRT** [Interfaccia: S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) [Costruttore: 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/it_it/sdk-for-java/latest/developer-guide/examples-s3.html) Per informazioni, consulta [Usa un client S3 performante: client S3 basato su AWS CRT](crt-based-s3-client.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  | 
|  ***Client asincrono S3 basato su Java con multipart abilitato*** Interfaccia[: S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) [Costruttore: 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/it_it/sdk-for-java/latest/developer-guide/examples-s3.html) Per informazioni, consulta [Configura il client asincrono S3 basato su Java per utilizzare trasferimenti paralleli](s3-async-client-multipart.md).  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  | Meno performante del client S3 basato su CRT. AWS  | 
|  ***Client asincrono S3 basato su Java senza multipart abilitato*** Interfaccia[: S3 AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) [Costruttore: 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/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Nessuna ottimizzazione delle prestazioni.  | 
|  **Client di sincronizzazione S3 basato su Java** [Interfaccia: S3Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) [Costruttore: 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/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/examples-s3.html)  |  Nessuna ottimizzazione delle prestazioni.  | 

**Nota**  
A partire dalla versione 2.18.x, AWS SDK for Java 2.x utilizza l'[indirizzamento in stile host virtuale](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) quando include un endpoint override. Questo vale purché il nome del bucket sia un'etichetta DNS valida.   
Chiama il [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)metodo con `true` nel tuo client builder per forzare il client a utilizzare l'indirizzamento in stile path per i bucket.  
L'esempio seguente mostra un client di servizio configurato con un endpoint override e che utilizza un indirizzamento in stile path.  

```
S3Client client = S3Client.builder()
                          .region(Region.US_WEST_2)
                          .endpointOverride(URI.create("https://s3.us-west-2.amazonaws.com"))
                          .forcePathStyle(true)
                          .build();
```

**Topics**
+ [Client S3 nell'SDK](#s3-clients)
+ [Caricamento di stream su S3](best-practices-s3-uploads.md)
+ [Prefirmato URLs](examples-s3-presign.md)
+ [Accesso interregionale](s3-cross-region.md)
+ [Protezione dell'integrità dei dati con checksum](s3-checksums.md)
+ [Usa un client S3 performante](crt-based-s3-client.md)
+ [Configurare il supporto per il trasferimento parallelo](s3-async-client-multipart.md)
+ [Trasferisci file e directory](transfer-manager.md)
+ [Notifiche di eventi di Amazon S3](examples-s3-event-notifications.md)

# Caricamento di stream su Amazon S3 utilizzando AWS SDK for Java 2.x
<a name="best-practices-s3-uploads"></a>

Quando usi uno stream per caricare contenuti su S3 utilizzando [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))o [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)), utilizzi una classe di `RequestBody` fabbrica per l'API sincrona per fornire lo stream. Per l'API asincrona, `AsyncRequestBody` è la classe factory equivalente.

## Quali metodi caricano gli stream?
<a name="s3-stream-upload-methods"></a>

Per l'API sincrona, puoi utilizzare i seguenti metodi di fabbrica `RequestBody` per fornire lo stream:
+ `[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`Ha il metodo `fromInputStream(InputStream inputStream)` factory
+ `[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)`

Per l'API asincrona, puoi utilizzare i seguenti metodi di fabbrica di: `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)`
  + Si utilizza AsyncRequestBodyFromInputStreamConfiguration .Builder per fornire lo stream
+ `[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)`
  + Il risultato `[BlockingInputStreamAsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.html)` contiene il metodo `writeInputStream(InputStream inputStream)` che è possibile utilizzare per fornire lo stream

## Esecuzione del caricamento
<a name="s3-upload-stream-perform"></a>

### Se conosci la durata dello stream
<a name="s3-stream-upload-supply-content-length"></a>

Come puoi vedere dalla firma dei metodi mostrata in precedenza, la maggior parte dei metodi accetta un parametro di lunghezza del contenuto. 

Se conosci la lunghezza del contenuto in byte, fornisci il valore esatto:

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

**avvertimento**  
 Quando carichi da un flusso di input, se la lunghezza del contenuto specificata non corrisponde al numero effettivo di byte, potresti riscontrare:  
Oggetti troncati se la lunghezza specificata è troppo piccola
Caricamenti non riusciti o connessioni sospese se la lunghezza specificata è troppo grande

### Se non conosci la durata dello stream
<a name="s3-stream-upload-unknown-length"></a>

#### Utilizzando l'API sincrona
<a name="s3-upload-unknown-sync-client"></a>

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

Poiché l'SDK memorizza nel buffer l'intero flusso per calcolare la lunghezza del contenuto, è possibile che si verifichino problemi di memoria con flussi di grandi dimensioni. Se devi caricare stream di grandi dimensioni con il client sincrono, prendi in considerazione l'utilizzo dell'API multipart:

##### Carica uno stream utilizzando l'API client sincrona e l'API multipart
<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;
}
```

**Nota**  
Nella maggior parte dei casi d'uso, consigliamo di utilizzare l'API client asincrona per flussi di dimensioni sconosciute. Questo approccio consente i trasferimenti paralleli e offre un'interfaccia di programmazione più semplice, poiché l'SDK gestisce la segmentazione del flusso in blocchi multiparte se lo stream è di grandi dimensioni.   
Sia il client asincrono S3 standard con multipart abilitato sia il client S3 basato su CRT implementano questo approccio. AWS Mostriamo esempi di questo approccio nella sezione seguente.

#### Utilizzo dell'API asincrona
<a name="s3-stream-upload-unknown-async-client"></a>

È possibile fornire `null` l'argomento al `contentLength` `fromInputStream(InputStream inputStream, Long contentLength, ExecutorService executor)`

**Example utilizzando il client AWS asincrono basato su 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 utilizzando il client asincrono standard con multipart abilitato:**  

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

# Lavora con prodotti Amazon S3 prefirmati URLs
<a name="examples-s3-presign"></a>

Pre-signed URLs fornisce l'accesso temporaneo agli oggetti S3 privati senza richiedere agli utenti di disporre di AWS credenziali o autorizzazioni. 

Ad esempio, si supponga che Alice abbia accesso a un oggetto S3 e che voglia condividere temporaneamente l'accesso a quell'oggetto con Bob. Alice può generare una richiesta GET prefirmata da condividere con Bob in modo che possa scaricare l'oggetto senza richiedere l'accesso alle credenziali di Alice. È possibile generare richieste HTTP GET e HTTP PUT URLs prefirmate.

## Genera un URL prefirmato per un oggetto, quindi scaricalo (richiesta GET)
<a name="get-presignedobject"></a>

L'esempio seguente è composto da due parti.
+ Parte 1: Alice genera l'URL prefirmato per un oggetto.
+ Parte 2: Bob scarica l'oggetto utilizzando l'URL prefirmato.

### Parte 1: Generazione dell'URL
<a name="get-presigned-object-part1"></a>

Alice ha già un oggetto in un bucket S3. Usa il codice seguente per generare una stringa URL che Bob può utilizzare in una successiva richiesta GET.

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

### Parte 2: scarica l'oggetto
<a name="get-presigned-object-part2"></a>

Bob utilizza una delle seguenti tre opzioni di codice per scaricare l'oggetto. In alternativa, potrebbe utilizzare un browser per eseguire la richiesta GET.

#### Usa JDK `HttpURLConnection` (dalla 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();
    }
```

#### Usa `HttpClient` JDK (dalla 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();
    }
```

#### Utilizzo `SdkHttpClient` dall'SDK for Java
<a name="get-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java SdkHttpClient class to do the download. */
    public byte[] useSdkHttpClientToGet(String presignedUrlString) {

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.
        try {
            URL presignedUrl = new URL(presignedUrlString);
            SdkHttpRequest request = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.GET)
                    .uri(presignedUrl.toURI())
                    .build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                response.responseBody().ifPresentOrElse(
                        abortableInputStream -> {
                            try {
                                IoUtils.copy(abortableInputStream, byteArrayOutputStream);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        },
                        () -> logger.error("No response body."));

                logger.info("HTTP Response code is {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

Guarda l'[esempio completo e prosegui](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedGetUrlAndRetrieve.java) [il test](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedGetUrlTests.java). GitHub

## Genera un URL prefirmato per un caricamento, quindi carica un file (richiesta PUT)
<a name="put-presignedobject"></a>

L'esempio seguente è composto da due parti.
+ Parte 1: Alice genera l'URL prefirmato per caricare un oggetto.
+ Parte 2: Bob carica un file utilizzando l'URL prefirmato.

### Parte 1: Generazione dell'URL
<a name="put-presigned-object-part1"></a>

Alice ha già un bucket S3. Usa il codice seguente per generare una stringa URL che Bob può utilizzare in una successiva richiesta PUT.

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

### Parte 2: carica un oggetto file
<a name="put-presigned-object-part2"></a>

Bob utilizza una delle seguenti tre opzioni di codice per caricare un file.

#### Usa JDK `HttpURLConnection` (dalla 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);
        }
    }
```

#### Usa `HttpClient` JDK (dalla 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);
        }
    }
```

#### Utilizzo `SdkHttpClient` dall'SDK for Java
<a name="put-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java V2 SdkHttpClient class to do the upload. */
    public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());

        try {
            URL presignedUrl = new URL(presignedUrlString);

            SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.PUT)
                    .uri(presignedUrl.toURI());
            // Add headers
            metadata.forEach((k, v) -> requestBuilder.putHeader("x-amz-meta-" + k, v));
            // Finish building the request.
            SdkHttpRequest request = requestBuilder.build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath()))
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                logger.info("Response code: {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

Guarda l'[esempio completo e prosegui](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java) [il test](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedPutUrlTests.java). GitHub

# Accesso interregionale per Amazon S3
<a name="s3-cross-region"></a>

Quando lavori con i bucket Amazon Simple Storage Service (Amazon S3) Simple Storage Service (Amazon S3), di solito sai qual Regione AWS è il bucket giusto. La regione con cui lavori viene determinata al momento della creazione del client S3. 

Tuttavia, a volte potresti dover lavorare con un bucket specifico, ma non sai se si trova nella stessa regione impostata per il client S3. 

Invece di effettuare più chiamate per determinare la regione del bucket, puoi utilizzare l'SDK per abilitare l'accesso ai bucket S3 in diverse regioni.

## Configurazione
<a name="s3-cross-region-setup"></a>

Il supporto per l'accesso interregionale è diventato disponibile con la versione `2.20.111` dell'SDK. Usa questa versione o una successiva nel tuo file di build di Maven per la `s3` dipendenza, come mostrato nel seguente frammento.

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
```

Successivamente, quando crei il tuo client S3, abilita l'accesso interregionale come mostrato nello snippet. Per impostazione predefinita, l'accesso non è abilitato.

```
S3AsyncClient client = S3AsyncClient.builder()
                                    .crossRegionAccessEnabled(true)
                                    .build();
```

## In che modo l'SDK fornisce l'accesso a più regioni
<a name="s3-cross-region-routing"></a>

Quando si fa riferimento a un bucket esistente in una richiesta, ad esempio quando si utilizza il `putObject` metodo, l'SDK avvia una richiesta alla regione configurata per il client. 

Se il bucket non esiste in quella regione specifica, la risposta all'errore include la regione effettiva in cui risiede il bucket. L'SDK utilizza quindi la regione corretta in una seconda richiesta.

Per ottimizzare le richieste future allo stesso bucket, l'SDK memorizza nella cache questa mappatura della regione nel client.

## Considerazioni
<a name="s3-cross-region-considerations"></a>

Quando abiliti l'accesso ai bucket tra regioni, tieni presente che la prima chiamata API potrebbe comportare un aumento della latenza se il bucket non si trova nella regione configurata dal client. Tuttavia, le chiamate successive traggono vantaggio dalle informazioni sulla regione memorizzate nella cache, con conseguente miglioramento delle prestazioni.

Quando si abilita l'accesso tra regioni, l'accesso al bucket non viene influenzato. L'utente deve essere autorizzato ad accedere al bucket in qualsiasi regione in cui risieda.

# Protezione dell'integrità dei dati con checksum
<a name="s3-checksums"></a>

Amazon Simple Storage Service (Amazon S3) Simple Storage Service (Amazon S3) offre la possibilità di specificare un checksum quando carichi un oggetto. Quando specifichi un checksum, questo viene memorizzato con l'oggetto e può essere convalidato quando l'oggetto viene scaricato.

I checksum forniscono un ulteriore livello di integrità dei dati durante il trasferimento dei file. Con i checksum, è possibile verificare la coerenza dei dati confermando che il file ricevuto corrisponde al file originale. [Per ulteriori informazioni sui checksum con Amazon S3, consulta la Guida per l'[utente di Amazon Simple Storage Service](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html), che include gli algoritmi supportati.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#using-additional-checksums)

Hai la flessibilità di scegliere l'algoritmo più adatto alle tue esigenze e lasciare che sia l'SDK a calcolare il checksum. In alternativa, puoi fornire un valore di checksum precalcolato utilizzando uno degli algoritmi supportati. 

**Nota**  
A partire dalla versione 2.30.0 di AWS SDK for Java 2.x, l'SDK fornisce protezioni di integrità predefinite calcolando automaticamente un checksum per i caricamenti. `CRC32` L'SDK calcola questo checksum se non fornisci un valore di checksum precalcolato o se non specifichi un algoritmo che l'SDK deve utilizzare per calcolare un checksum.   
[L'SDK fornisce anche impostazioni globali per la protezione dell'integrità dei dati che puoi impostare esternamente, come puoi leggere nella Guida di riferimento agli strumenti.AWS SDKs ](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html)

Discutiamo i checksum in due fasi di richiesta: caricamento di un oggetto e download di un oggetto. 

## Caricamento di un oggetto
<a name="use-service-S3-checksum-upload"></a>

 Quando caricate un oggetto con il `putObject` metodo e fornite un algoritmo di checksum, l'SDK calcola il checksum per l'algoritmo specificato. 

Il seguente frammento di codice mostra una richiesta di caricamento di un oggetto con un checksum. `SHA256` Quando l'SDK invia la richiesta, calcola il `SHA256` checksum e carica l'oggetto. Amazon S3 convalida l'integrità del contenuto calcolando il checksum e confrontandolo con il checksum fornito dall'SDK. Amazon S3 memorizza quindi il checksum con l'oggetto.

```
public void putObjectWithChecksum() {
        s3Client.putObject(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA256),
            RequestBody.fromString("This is a test"));
}
```

Se non fornisci un algoritmo di checksum con la richiesta, il comportamento del checksum varia a seconda della versione dell'SDK che usi, come mostrato nella tabella seguente.

**Comportamento del checksum quando non viene fornito alcun algoritmo di checksum**


| Versione Java SDK | Comportamento del checksum | 
| --- | --- | 
| precedente alla 2.30.0 | L'SDK non calcola automaticamente un checksum basato su CRC e lo fornisce nella richiesta. | 
| 2.30.0 o versione successiva | L'SDK utilizza l'`CRC32`algoritmo per calcolare il checksum e lo fornisce nella richiesta. Amazon S3 convalida l'integrità del trasferimento calcolando il proprio `CRC32` checksum e lo confronta con il checksum fornito dall'SDK. Se i checksum corrispondono, il checksum viene salvato con l'oggetto. | 

### Utilizza un valore di checksum precalcolato
<a name="use-service-S3-checksum-upload-pre"></a>

Un valore di checksum precalcolato fornito con la richiesta disabilita il calcolo automatico da parte dell'SDK e utilizza invece il valore fornito.

L'esempio seguente mostra una richiesta con un checksum precalcolato. SHA256

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

Se Amazon S3 determina che il valore del checksum non è corretto per l'algoritmo specificato, il servizio restituisce una risposta di errore.

### Caricamenti in più parti
<a name="use-service-S3-checksum-upload-multi"></a>

Puoi anche utilizzare i checksum con caricamenti in più parti.

 L'SDK for Java 2.x offre due opzioni per utilizzare i checksum con caricamenti multiparte. La prima opzione utilizza il. `S3TransferManager` 

Il seguente esempio di gestore di trasferimento specifica l' SHA1 algoritmo per il caricamento.

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

Se non fornite un algoritmo di checksum quando utilizzate il gestore di trasferimento per i caricamenti, l'SDK calcola automaticamente un checksum in base all'algoritmo. `CRC32` L'SDK esegue questo calcolo per tutte le versioni dell'SDK.

La seconda opzione utilizza l'[`S3Client`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) (o l'[`S3AsyncClient`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)) per eseguire il caricamento in più parti. Se si specifica un checksum con questo approccio, è necessario specificare l'algoritmo da utilizzare all'avvio del caricamento. Inoltre, devi specificare l’algoritmo per ogni richiesta parte e fornire il checksum calcolato per ciascuna parte dopo che è stata caricata.

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

Il [codice per gli esempi e i test completi](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PerformMultiPartUpload.java) [si trova](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/test/java/com/example/s3/PerformMultiPartUploadTests.java) nel repository degli esempi di GitHub codice.

## Donwload di un oggetto
<a name="use-service-S3-checksum-download"></a>

 quando il `checksumMode` metodo del builder for the è impostato su. `GetObjectRequest` `ChecksumMode.ENABLED` 

La richiesta nel seguente frammento indica all'SDK di convalidare il checksum nella risposta calcolando il checksum e confrontando i valori.

```
    public GetObjectResponse getObjectWithChecksum() {
        return s3Client.getObject(b -> b
                        .bucket(bucketName)
                        .key(key)
                        .checksumMode(ChecksumMode.ENABLED))
                .response();
    }
```

**Nota**  
Se l'oggetto non è stato caricato con un checksum, non viene effettuata alcuna convalida. 

## Altre opzioni di calcolo del checksum
<a name="S3-checsum-calculation-options"></a>

**Nota**  
Per verificare l'integrità dei dati trasmessi e identificare eventuali errori di trasmissione, incoraggiamo gli utenti a mantenere le impostazioni predefinite dell'SDK per le opzioni di calcolo del checksum. Per impostazione predefinita, l'SDK aggiunge questo importante controllo per molte operazioni S3, tra cui e. `PutObject` `GetObject`

Se l'uso di Amazon S3 richiede una convalida minima dei checksum, tuttavia, puoi disabilitare molti controlli modificando le impostazioni di configurazione predefinite. 

### Disattiva il calcolo automatico del checksum a meno che non sia necessario
<a name="S3-minimize-checksum-calc-global"></a>

Puoi disabilitare il calcolo automatico del checksum da parte dell'SDK per le operazioni che lo supportano, ad esempio e. `PutObject` `GetObject` Alcune operazioni di S3, tuttavia, richiedono un calcolo del checksum; non è possibile disabilitare il calcolo del checksum per queste operazioni.

L'SDK fornisce impostazioni separate per il calcolo di un checksum per il payload di una richiesta e per il payload di una risposta.

L'elenco seguente descrive le impostazioni che è possibile utilizzare per ridurre al minimo i calcoli di checksum nei diversi ambiti.
+ **Ambito di tutte le applicazioni**: modificando le impostazioni nelle variabili di ambiente o in un profilo negli archivi condivisi AWS `config` e nei `credentials` file, tutte le applicazioni possono utilizzare queste impostazioni. Queste impostazioni influiscono su tutti i client di servizio in tutte le applicazioni AWS SDK, a meno che non vengano sostituite nell'ambito dell'applicazione o del client di servizio.
  + Aggiungi le impostazioni in un profilo:

    ```
    [default]
    request_checksum_calculation = WHEN_REQUIRED
    response_checksum_validation = WHEN_REQUIRED
    ```
  + Aggiungi variabili di ambiente:

    ```
    AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
    AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED
    ```
+ **Ambito dell'applicazione corrente**: è possibile impostare la proprietà del sistema Java `aws.requestChecksumCalculation` su per `WHEN_REQUIRED` limitare il calcolo del checksum. La proprietà di sistema corrispondente per le risposte è. `aws.responseChecksumValidation`

  Queste impostazioni influiscono su tutti i client di servizio SDK nell'applicazione, a meno che non vengano sostituite durante la creazione del client di servizio.

  Imposta la proprietà del sistema all'avvio dell'applicazione:

  ```
  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.
      }
  }
  ```
+ **Ambito del client di servizio S3 singolo**: puoi configurare un singolo client di servizio S3 per calcolare la quantità minima di checksum utilizzando i metodi builder:

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

### `LegacyMd5Plugin` MD5 Utilizza il per una compatibilità semplificata
<a name="S3-checksum-legacy-md5"></a>

Oltre al rilascio del comportamento dei CRC32 checksum con la versione 2.30.0, l'SDK ha interrotto il calcolo MD5 dei checksum sulle operazioni richieste.

Se hai bisogno di un comportamento di MD5 checksum precedente per le operazioni S3, puoi utilizzare la, che è stata rilasciata con la versione 2.31.32 dell'`LegacyMd5Plugin`SDK.

`LegacyMd5Plugin`È particolarmente utile quando è necessario mantenere la compatibilità con le applicazioni che dipendono dal comportamento dei MD5 checksum precedenti, specialmente quando si lavora con provider di storage di terze parti compatibili con S3, come quelli utilizzati con i connettori di file system S3A (Apache Spark, Iceberg).

Per utilizzarlo, aggiungilo al tuo client builder S3: `LegacyMd5Plugin`

```
// For synchronous S3 client.
S3Client s3Client = S3Client.builder()
                           .addPlugin(LegacyMd5Plugin.create())
                           .build();

// For asynchronous S3 client.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .build();
```

Se desideri aggiungere MD5 checksum alle operazioni che richiedono checksum e vuoi saltare l'aggiunta di checksum SDK predefiniti per operazioni che supportano i checksum ma non sono obbligatorie, puoi abilitare le opzioni e as. `ClientBuilder` `requestChecksumCalculation` `responseChecksumValidation` `WHEN_REQUIRED` Questo aggiungerà i checksum predefiniti dell'SDK solo alle operazioni che richiedono i checksum:

```
// Use the `LegacyMd5Plugin` with `requestChecksumCalculation` and `responseChecksumValidation` set to WHEN_REQUIRED.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
                                       .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
                                       .build();
```

Questa configurazione è particolarmente utile quando si lavora con sistemi di storage di terze parti compatibili con S3 che potrebbero non supportare completamente i nuovi algoritmi di checksum ma che richiedono comunque i checksum per determinate operazioni. MD5 

# Usa un client S3 performante: client S3 basato su AWS CRT
<a name="crt-based-s3-client"></a>

Il client S3 AWS basato su CRT, basato su [AWS Common Runtime (CRT), è un client asincrono S3 alternativo](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html). [Trasferisce oggetti da e verso Amazon Simple Storage Service (Amazon S3) con prestazioni e affidabilità migliorate utilizzando automaticamente l'API di caricamento [multiparte e i recuperi per intervallo di byte di](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) Amazon S3.](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range) 

Il client S3 AWS basato su CRT migliora l'affidabilità del trasferimento in caso di guasto della rete. L'affidabilità è migliorata riprovando le singole parti non riuscite di un trasferimento di file senza riavviare il trasferimento dall'inizio.

Inoltre, il client S3 AWS basato su CRT offre un pool di connessioni avanzato e un bilanciamento del carico DNS (Domain Name System), che migliora anche la velocità effettiva.

Puoi utilizzare il client S3 AWS basato su CRT al posto del client asincrono S3 standard dell'SDK e sfruttare subito il suo throughput migliorato.

**Importante**  
Il client S3 AWS basato su CRT attualmente non supporta la raccolta di metriche [SDK](metrics.md) a livello di client né a livello di richiesta.

**AWS Componenti basati su CRT nell'SDK**

Il client *S3 AWS * basato su CRT, descritto in questo argomento, e il client *HTTP AWS * basato su CRT sono componenti diversi dell'SDK. 

Il **client S3 AWS basato su CRT** è un'implementazione dell'AsyncClientinterfaccia [S3](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) e viene utilizzato per lavorare con il servizio Amazon S3. È un'alternativa all'implementazione dell'interfaccia basata su Java e offre diversi vantaggi. `S3AsyncClient`

Il [client HTTP AWS basato su CRT](http-configuration-crt.md) è un'implementazione dell'[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)interfaccia e viene utilizzato per la comunicazione HTTP generale. È un'alternativa all'implementazione Netty dell'`SdkAsyncHttpClient`interfaccia e offre diversi vantaggi.

Sebbene entrambi i componenti utilizzino librerie di [AWS Common Runtime](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html), il client S3 AWS basato su CRT utilizza la [libreria aws-c-s 3 e supporta le funzionalità](https://github.com/awslabs/aws-c-s3) dell'API di caricamento multipart [S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html). Poiché il client HTTP AWS basato su CRT è pensato per un uso generico, non supporta le funzionalità dell'API di caricamento multipart S3.

## Aggiungi dipendenze per utilizzare il client S3 basato su CRT AWS
<a name="crt-based-s3-client-depend"></a>

Per utilizzare il client S3 AWS basato su CRT, aggiungi le seguenti due dipendenze al tuo file di progetto Maven. L'esempio mostra le versioni minime da utilizzare. [Cerca nel repository centrale di Maven le versioni più recenti degli artefatti [s3](https://central.sonatype.com/artifact/software.amazon.awssdk/s3) e 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>
```

## Crea un'istanza AWS del client S3 basato su CRT
<a name="crt-based-s3-client-create"></a>

 Crea un'istanza del client S3 AWS basato su CRT con le impostazioni predefinite, come mostrato nel seguente frammento di codice.

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
```

Per configurare il client, utilizzate il generatore di client CRT. AWS È possibile passare dal client asincrono S3 standard al client basato su AWS CRT modificando il metodo del generatore.

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

**Nota**  
Alcune impostazioni del generatore standard potrebbero non essere attualmente supportate nel generatore del client CRT. AWS Scarica lo standard builder chiamando. `S3AsyncClient#builder()`

## Usa il client S3 AWS basato su CRT
<a name="crt-based-s3-client-use"></a>

Usa il client S3 AWS basato su CRT per chiamare le operazioni dell'API Amazon S3. L'esempio seguente illustra le operazioni [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))e [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))disponibili tramite. AWS SDK per 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();
```

## Caricamento di stream di dimensioni sconosciute
<a name="crt-stream-unknown-size"></a>

Un vantaggio significativo del client S3 AWS AWS basato su CRT è la sua capacità di gestire in modo efficiente flussi di input di dimensioni sconosciute. Ciò è particolarmente utile quando è necessario caricare dati da una fonte in cui la dimensione totale non può essere determinata in anticipo.

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

Questa funzionalità consente di evitare problemi comuni con i caricamenti tradizionali, in cui una specifica errata della lunghezza dei contenuti può portare a oggetti troncati o a caricamenti non riusciti.

## Limitazioni di configurazione
<a name="crt-based-s3-client-limitations"></a>

Il client S3 AWS basato su CRT e il client asincrono S3 basato su Java [offrono](examples-s3.md#s3-clients) funzionalità comparabili, mentre il client S3 basato su CRT offre un vantaggio in termini di prestazioni. AWS Tuttavia, il client S3 basato su CRT non dispone delle impostazioni di configurazione del AWS client asincrono S3 basato su Java. Queste impostazioni includono:
+ *Configurazione a livello di client:* timeout dei tentativi di chiamata API, intercettori di esecuzione della compressione, editori di metriche, attributi di esecuzione personalizzati, opzioni avanzate personalizzate, servizio esecutore pianificato personalizzato, intestazioni personalizzate
+ *Configurazione a livello di richiesta:* firmatari personalizzati, timeout dei tentativi di chiamata API

Per un elenco completo delle differenze di configurazione, consulta il riferimento all'API.


| Client asincrono S3 basato su Java | AWS Client S3 basato su CRT | 
| --- | --- | 
| Configurazioni a livello di client[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Configurazioni a livello di richiesta[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | Configurazioni a livello di client[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)Configurazioni a livello di richiesta[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | 

# Configura il client asincrono S3 basato su Java per utilizzare trasferimenti paralleli
<a name="s3-async-client-multipart"></a>

Dalla versione 2.27.5, il client asincrono S3 standard basato su Java supporta trasferimenti paralleli automatici (caricamenti e download multiparte). Il supporto per i trasferimenti paralleli viene configurato quando si crea il client asincrono S3 basato su Java. 

Questa sezione mostra come abilitare i trasferimenti paralleli e come personalizzare la configurazione.

## Creare un'istanza di `S3AsyncClient`
<a name="s3-async-client-multipart-create"></a>

Quando crei un'`S3AsyncClient`istanza senza chiamare nessuno dei `multipart*` metodi sul [builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html), i trasferimenti paralleli non sono abilitati. Ciascuna delle seguenti istruzioni crea un client asincrono S3 basato su Java senza supporto per caricamenti e download multiparte.

### *Crea senza supporto multiparte*
<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();
```

### Crea *con il supporto* multiparte
<a name="s3-async-client-mp-on"></a>

Per abilitare i trasferimenti paralleli con le impostazioni predefinite, chiama `multipartEnabled` on the builder e passali `true` come mostrato nell'esempio seguente.

**Example**  

```
S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartEnabled(true)
        .build();
```

Il valore predefinito è 8 MiB per `thresholdInBytes` e `minimumPartSizeInBytes` impostazioni.

Se si personalizzano le impostazioni multiparte, i trasferimenti paralleli vengono abilitati automaticamente come illustrato di seguito.

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

## Caricamento di stream di dimensioni sconosciute
<a name="java-async-client-stream-unknown-size"></a>

Il client asincrono S3 basato su Java con multipart abilitato è in grado di gestire in modo efficiente i flussi di input in cui la dimensione totale non è nota in anticipo:

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

Questo approccio previene i problemi che possono verificarsi quando si specifica manualmente una lunghezza errata del contenuto, come oggetti troncati o caricamenti non riusciti.

# Trasferisci file e directory con Amazon S3 Transfer Manager
<a name="transfer-manager"></a>

Amazon S3 Transfer Manager è un'utilità di trasferimento file open source di alto livello per. AWS SDK for Java 2.x Usalo per trasferire file e directory da e verso Amazon Simple Storage Service (Amazon S3). 

[https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) 

Con S3 Transfer Manager, puoi anche monitorare l'avanzamento di un trasferimento in tempo reale e mettere in pausa il trasferimento per un'esecuzione successiva.

## Nozioni di base
<a name="transfer-manager-prerequisites"></a>

### Aggiungi dipendenze al tuo file di build
<a name="transfer-manager-add-dependency"></a>

Per utilizzare S3 Transfer Manager con prestazioni multiparte migliorate, configura il file di build con le dipendenze necessarie.

------
#### [ 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 Ultima versione[.](https://central.sonatype.com/artifact/software.amazon.awssdk/bom) 2 [Ultima versione](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 [Ultima versione](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

------

### Crea un'istanza di S3 Transfer Manager
<a name="transfer-manager-create"></a>

Per abilitare il trasferimento parallelo, è necessario passare un client S3 AWS basato su CRT OPPURE un client asincrono S3 basato su Java con multipart abilitato. Gli esempi seguenti mostrano come configurare un S3 Transfer Manager con impostazioni personalizzate. 

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

Se la `aws-crt` dipendenza non è inclusa nel file di build, S3 Transfer Manager si basa sul client asincrono S3 standard basato su Java utilizzato nell'SDK for Java 2.x. 

**Configurazione personalizzata del client S3: richiede l'attivazione di più parti**

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
                .multipartEnabled(true)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

**Nessuna configurazione del client S3: supporto multiparte abilitato automaticamente**

```
S3TransferManager transferManager = S3TransferManager.create();
```

------

## Carica un file in un bucket S3
<a name="transfer-manager-upload"></a>

L'esempio seguente mostra un esempio di caricamento di file insieme all'uso opzionale di a [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), che registra l'avanzamento del caricamento.

[Per caricare un file su Amazon S3 utilizzando S3 Transfer Manager, passa 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)oggetto al `S3TransferManager` metodo 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)oggetto restituito dal `uploadFile` metodo rappresenta il processo di caricamento. Al termine della richiesta, l'[CompletedFileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileUpload.html)oggetto contiene informazioni sul caricamento.

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

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

## Scarica un file da un bucket S3
<a name="transfer-manager-download"></a>

L'esempio seguente mostra un esempio di download insieme all'uso opzionale di a [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html), che registra l'avanzamento del download.

[Per scaricare un oggetto da un bucket S3 utilizzando S3 Transfer Manager, crea un [DownloadFileRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadFileRequest.html)oggetto e passalo al metodo 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)oggetto restituito dal `downloadFile` metodo `S3TransferManager`'s rappresenta il trasferimento del file. Una volta completato il download, [CompletedFileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileDownload.html)contiene l'accesso alle informazioni sul download.

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

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

## Copiare un oggetto Amazon S3 in un altro bucket
<a name="transfer-manager-copy"></a>

L'esempio seguente mostra come copiare un oggetto con S3 Transfer Manager.

Per iniziare la copia di un oggetto da un bucket S3 a un altro bucket, crea un'istanza di base. [CopyObjectRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/CopyObjectRequest.html)

Successivamente, racchiudi il file di base `CopyObjectRequest` in un file [CopyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CopyRequest.html)che possa essere utilizzato da S3 Transfer Manager. 

L'`Copy`oggetto restituito dal `copy` metodo `S3TransferManager`'s rappresenta il processo di copia. Una volta completato il processo di copia, l'[CompletedCopy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedCopy.html)oggetto contiene i dettagli sulla risposta.

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

**Nota**  
Per eseguire una copia su più regioni con S3 Transfer Manager, abilitalo sul generatore di client S3 AWS basato `crossRegionAccessEnabled` su CRT, come mostrato nel frammento seguente.  

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .crossRegionAccessEnabled(true)
                .build();

S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

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

## Carica una directory locale in un bucket S3
<a name="transfer-manager-upload_directory"></a>

L'esempio seguente mostra come caricare una directory locale su S3.

Inizia chiamando il metodo [uploadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadDirectory(software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest)) dell'`S3TransferManager`istanza, passando 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)oggetto rappresenta il processo di caricamento, che genera un al [CompletedDirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryUpload.html)termine della richiesta. L'`CompleteDirectoryUpload`oggetto contiene informazioni sui risultati del trasferimento, inclusi i file non riusciti a trasferire.

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

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

## Scarica gli oggetti del bucket S3 in una directory locale
<a name="transfer-manager-download_directory"></a>

Puoi scaricare gli oggetti in un bucket S3 in una directory locale come mostrato nell'esempio seguente.

Per scaricare gli oggetti in un bucket S3 in una directory locale, iniziate chiamando il metodo [DownloadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadDirectory(software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest)) di Transfer Manager, passando 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)oggetto rappresenta il processo di download, che genera un messaggio [CompletedDirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryDownload.html)quando la richiesta viene completata. L'`CompleteDirectoryDownload`oggetto contiene informazioni sui risultati del trasferimento, inclusi i file non riusciti a trasferire.

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

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

## Vedi esempi completi
<a name="transfer-manager-example-location"></a>

[GitHub contiene il codice completo](https://github.com/awsdocs/aws-doc-sdk-examples/tree/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/transfermanager) per tutti gli esempi in questa pagina.

# Lavora con le notifiche degli eventi S3
<a name="examples-s3-event-notifications"></a>

Per aiutarti a monitorare l'attività nei tuoi bucket, Amazon S3 può inviare notifiche quando si verificano determinati eventi. La Guida per l'utente di Amazon S3 fornisce informazioni sulle [notifiche che un bucket può](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html#notification-how-to-overview) inviare. 

Puoi configurare un bucket per inviare eventi a quattro possibili destinazioni utilizzando l'SDK for Java: 
+ Argomenti su Amazon Simple Notification Service
+ Code Amazon Simple Queue Service
+ AWS Lambda funzioni
+ Amazon EventBridge

Quando configuri un bucket a cui inviare eventi EventBridge, hai la possibilità di configurare una EventBridge regola per inviare lo stesso evento a più destinazioni. Quando configuri il bucket per l'invio diretto a una delle prime tre destinazioni, puoi specificare un solo tipo di destinazione per ogni evento.

Nella sezione successiva, vedrai come configurare un bucket utilizzando l'SDK for Java per inviare notifiche di eventi S3 in due modi: direttamente a una coda Amazon SQS e a. EventBridge

L'ultima sezione mostra come utilizzare l'API S3 Event Notifications per utilizzare le notifiche in modo orientato agli oggetti.

## Configura un bucket da inviare direttamente a una destinazione
<a name="s3-event-conf-bucket-direct"></a>

L'esempio seguente configura un bucket per inviare notifiche quando si verificano eventi di *creazione di oggetti* o eventi di *tagging di oggetti* su un bucket.

```
static void processS3Events(String bucketName, String queueArn) {
    // Configure the bucket to send Object Created and Object Tagging notifications to an existing SQS queue.
    s3Client.putBucketNotificationConfiguration(b -> b
            .notificationConfiguration(ncb -> ncb
                    .queueConfigurations(qcb -> qcb
                            .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                            .queueArn(queueArn)))
                    .bucket(bucketName)
    );
}
```

Il codice mostrato sopra imposta una coda per ricevere due tipi di eventi. Comodamente, il `queueConfigurations` metodo consente di impostare più destinazioni di coda, se necessario. Inoltre, nel `notificationConfiguration` metodo puoi impostare destinazioni aggiuntive, come uno o più argomenti di Amazon SNS o una o più funzioni Lambda. Il seguente frammento mostra un esempio con due code e tre tipi di destinazioni.

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

Il GitHub repository Code Examples contiene l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java) di invio di notifiche di eventi S3 direttamente a una coda.

## Configura un bucket a cui inviare EventBridge
<a name="s3-event-conf-bucket-eventbridge"></a>

L'esempio seguente configura un bucket a cui inviare notifiche. 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());
```

Quando si configura un bucket a cui inviare eventi EventBridge, è sufficiente indicare la EventBridge destinazione, non i tipi di eventi né la destinazione finale a cui EventBridge verranno inviati gli eventi. Puoi configurare gli obiettivi finali e i tipi di eventi utilizzando il client di Java SDK. EventBridge

Il codice seguente mostra come EventBridge configurare la suddivisione degli eventi *creati dagli oggetti* in un argomento e in una coda.

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

Per utilizzarlo EventBridge nel codice Java, aggiungi una dipendenza dall'`eventbridge`artefatto al tuo file Maven. `pom.xml`

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>eventbridge</artifactId>
</dependency>
```

Il GitHub repository Code Examples contiene l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PutBucketS3EventNotificationEventBridge.java) di invio di notifiche di eventi S3 e quindi a un argomento EventBridge e a una coda.

## Utilizza l'API S3 Event Notifications per elaborare gli eventi
<a name="s3-event-notification-read"></a>

Dopo che una destinazione riceve eventi di notifica S3, puoi elaborarli in modo orientato agli oggetti utilizzando l'API S3 Event Notifications. Puoi utilizzare l'API S3 Event Notifications per lavorare con le notifiche di eventi che vengono inviate direttamente a un target (come mostrato nel [primo esempio](#s3-event-conf-bucket-direct)), ma non con le notifiche inoltrate. EventBridge Le notifiche di eventi S3 inviate dai bucket EventBridge contengono una [struttura diversa](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ev-events.html#ev-events-list) che l'API S3 Event Notifications attualmente non gestisce.

### Aggiungi dipendenza
<a name="s3-event-notifications-dep"></a>

L'API S3 Event Notifications è stata rilasciata con la versione 2.25.11 dell'SDK for Java 2.x.

Per utilizzare l'API S3 Event Notifications, aggiungi l'elemento di dipendenza richiesto a `pom.xml` Maven, come mostrato nel seguente frammento.

```
<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 Ultima versione.](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)

### Usa la `S3EventNotification` classe
<a name="s3-event-notifications-use"></a>

#### Crea un'`S3EventNotification`istanza da una stringa JSON
<a name="s3-event-notifications-use-from-json"></a>

Per convertire una stringa JSON in un `S3EventNotification` oggetto, utilizzate i metodi statici della `S3EventNotification` classe come mostrato nell'esempio seguente.

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

In questo esempio, il `fromJson` metodo converte la stringa JSON in un oggetto. `S3EventNotification` I campi mancanti nella stringa JSON produrranno `null` valori nei campi degli oggetti Java corrispondenti e tutti i campi aggiuntivi nel JSON verranno ignorati.

Ulteriori informazioni APIs relative al record di notifica degli eventi sono disponibili nel riferimento API per. `[S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html)`

#### Convertire un'`S3EventNotification`istanza in una stringa JSON
<a name="s3-event-notifications-use-to-json"></a>

Utilizzate il metodo `toJson` (or`toJsonPretty`) per convertire un `S3EventNotification` oggetto in una stringa JSON, come mostrato nell'esempio seguente.

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

I campi per `GlacierEventData``ReplicationEventData`,`IntelligentTieringEventData`, e `LifecycleEventData` sono esclusi dal JSON se lo sono. `null` Gli altri `null` campi verranno serializzati come. `null`

Di seguito viene mostrato un esempio di output del `toJsonPretty` metodo per un evento di tagging di oggetti 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
      }
    }
  } ]
}
```

È disponibile un [esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/75c3daadf750406156fc87fa30ee499a206b4a36/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java#L117) GitHub che mostra come utilizzare l'API per gestire le notifiche ricevute da una coda Amazon SQS.

## Elabora gli eventi S3 in Lambda con le librerie Java: e AWS SDK for Java 2.x `aws-lambda-java-events`
<a name="s3-event-notif-processing-options"></a>

Invece di utilizzare l'SDK for Java 2.x per elaborare le notifiche degli eventi di Amazon S3 in una funzione Lambda, puoi utilizzare la libreria nella versione 3.x.x. `[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)` AWS gestisce la `aws-lambda-java-events` libreria in modo indipendente e ha i propri requisiti di dipendenza. La `aws-lambda-java-events` libreria funziona solo con gli eventi S3 nelle funzioni Lambda, mentre l'SDK per Java 2.x funziona con gli eventi S3 nelle funzioni Lambda, Amazon SNS e Amazon SQS.

Entrambi gli approcci modellano il payload di notifica degli eventi JSON in modo orientato agli oggetti con similari. APIs La tabella seguente mostra le notevoli differenze tra l'utilizzo dei due approcci.


****  

|  | AWS SDK per Java | aws-lambda-java-events libreria | 
| --- | --- | --- | 
| Denominazione dei pacchetti |  `software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification`  | com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification | 
| Parametro RequestHandler |  Scrivi l'`RequestHandler`implementazione della tua funzione Lambda per ricevere una stringa 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>  | Scrivi l'RequestHandlerimplementazione della tua funzione Lambda per ricevere un S3Event oggetto:<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> | 
| Dipendenze da 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>  | 

# Lavora con Amazon Simple Notification Service
<a name="examples-simple-notification-service"></a>

Con Amazon Simple Notification Service, puoi inviare facilmente messaggi di notifica in tempo reale dalle tue applicazioni agli abbonati su più canali di comunicazione. In questo argomento viene descritto come eseguire alcune delle funzioni di base di Amazon SNS.

## Creazione di un argomento
<a name="sns-create-topic"></a>

Un **argomento** è un raggruppamento logico di canali di comunicazione che definisce a quali sistemi inviare un messaggio, ad esempio suddividendo un messaggio AWS Lambda e un webhook HTTP. I messaggi vengono inviati ai Amazon SNS canali definiti nell'argomento e poi vengono distribuiti ai canali definiti nell'argomento. Questo rende i messaggi disponibili per gli abbonati.

Per creare un argomento, crea prima un [CreateTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicRequest.html)oggetto, con il nome dell'argomento impostato utilizzando il `name()` metodo nel generatore. Quindi, invia l'oggetto della richiesta a Amazon SNS utilizzando il `createTopic()` metodo di. [SnsClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/SnsClient.html) È possibile acquisire il risultato di questa richiesta come [CreateTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/CreateTopicResponse.html)oggetto, come illustrato nel seguente frammento di codice.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/CreateTopic.java) su. GitHub

## Elenca i tuoi Amazon SNS argomenti
<a name="sns-crelistate-topics"></a>

Per recuperare un elenco dei tuoi Amazon SNS argomenti esistenti, crea un [ListTopicsRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsRequest.html)oggetto. Quindi, invia l'oggetto della richiesta a Amazon SNS utilizzando il `listTopics()` metodo di. `SnsClient` È possibile acquisire il risultato di questa richiesta come [ListTopicsResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/ListTopicsResponse.html)oggetto.

Il seguente frammento di codice stampa il codice di stato HTTP della richiesta e un elenco di Amazon Resource Names (ARNs) per i tuoi Amazon SNS argomenti.

 **Importazioni** 

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

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/ListTopics.java) su. GitHub

## Sottoscrizione di un endpoint a un argomento
<a name="sns-subscribe-endpoint-topic"></a>

Dopo aver creato un argomento, puoi configurare quali canali di comunicazione saranno endpoint per tale argomento. I messaggi vengono distribuiti a questi endpoint dopo averli Amazon SNS ricevuti.

Per configurare un canale di comunicazione come endpoint per un argomento, sottoscrivi tale endpoint all'argomento. Per iniziare, costruisci un [SubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html)oggetto. Specificate il canale di comunicazione (ad esempio, `lambda` o`email`) come`protocol()`. Imposta la `endpoint()` posizione di output pertinente (ad esempio, l'ARN di una Lambda funzione o un indirizzo e-mail), quindi imposta l'ARN dell'argomento a cui desideri iscriverti come. `topicArn()` Inviate l'oggetto della richiesta a Amazon SNS utilizzando il `subscribe()` metodo di. `SnsClient` È possibile acquisire il risultato di questa richiesta come [SubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeResponse.html)oggetto.

Il frammento di codice seguente mostra come sottoscrivere un indirizzo e-mail a un argomento.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/SubscribeEmail.java) su GitHub.

## Pubblicazione di un messaggio in un argomento
<a name="sns-publish-message-topic"></a>

Dopo avere configurato un argomento e uno o più endpoint, puoi pubblicare un messaggio. Per iniziare, costruisci un [PublishRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishRequest.html)oggetto. Specifica `message()` per l'invio e l'ARN dell'argomento (`topicArn()`) a cui inviarlo. Quindi, invia l'oggetto della richiesta a Amazon SNS utilizzando il `publish()` metodo di`SnsClient`. È possibile acquisire il risultato di questa richiesta come [PublishResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/PublishResponse.html)oggetto.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/PublishTopic.java) su GitHub.

## Annullamento della sottoscrizione di un endpoint da un argomento
<a name="sns-unsubscribe-endpoint-topic"></a>

Puoi rimuovere i canali di comunicazione configurati come endpoint per un argomento. Dopo aver eseguito questa operazione, l'argomento stesso continua a esistere e distribuire i messaggi a qualsiasi altro endpoint configurato per tale argomento.

Per rimuovere un canale di comunicazione come endpoint per un argomento, annulla la sottoscrizione dell'endpoint dall'argomento. Per iniziare, crea un [UnsubscribeRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeRequest.html)oggetto e imposta l'ARN dell'argomento a cui desideri annullare l'iscrizione come. `subscriptionArn()` Quindi invia l'oggetto della richiesta a SNS utilizzando il metodo `unsubscribe()` di `SnsClient`. Puoi acquisire il risultato di questa richiesta come oggetto [UnsubscribeResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/UnsubscribeResponse.html).

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/Unsubscribe.java) su GitHub.

## Eliminazione di un argomento
<a name="sns-delete-topic"></a>

Per eliminare un Amazon SNS argomento, crea prima un [DeleteTopicRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicRequest.html)oggetto con l'ARN dell'argomento impostato come `topicArn()` metodo nel generatore. Quindi invia l'oggetto della richiesta a Amazon SNS utilizzando il `deleteTopic()` metodo di. `SnsClient` È possibile acquisire il risultato di questa richiesta come [DeleteTopicResponse](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/DeleteTopicResponse.html)oggetto, come illustrato nel seguente frammento di codice.

 **Importazioni** 

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

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/da520cb4436f8567a90b6f73f77232fd590a50bf/javav2/example_code/sns/src/main/java/com/example/sns/DeleteTopic.java) su. GitHub

Per ulteriori informazioni, consulta la [Guida per gli sviluppatori di Amazon Simple Notification Service](https://docs.aws.amazon.com/sns/latest/dg/).

# Lavora con Amazon Simple Queue Service
<a name="examples-sqs"></a>

Questa sezione fornisce esempi di programmazione [Amazon Simple Queue Service](https://docs.aws.amazon.com/sqs/)con AWS SDK per Java 2.x.

Gli esempi seguenti includono solo il codice necessario per dimostrare ciascuna tecnica. Il [codice di esempio completo è disponibile su. GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2) Da qui puoi scaricare un singolo file sorgente o clonare l'archivio localmente per ottenere tutti gli esempi da creare ed eseguire.

**Topics**
+ [Utilizza il raggruppamento automatico delle richieste](sqs-auto-batch.md)
+ [Operazioni di coda](examples-sqs-message-queues.md)
+ [Operazioni relative ai messaggi](examples-sqs-messages.md)

# Utilizza il batching automatico delle richieste per Amazon SQS con AWS SDK for Java 2.x
<a name="sqs-auto-batch"></a>

L'API Automatic Request Batching per Amazon SQS è una libreria di alto livello che fornisce un modo efficiente per creare batch e bufferizzare le richieste per le operazioni SQS. Utilizzando l'API di batching, riduci il numero di richieste a SQS, il che migliora la produttività e minimizza i costi. 

Poiché i metodi dell'API batch corrispondono ai `[SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)` metodi—`sendMessage`,, `changeMessageVisibility``deleteMessage`, `receiveMessage` —puoi utilizzare l'API batch come sostituto immediato con modifiche minime. 

Questo argomento offre una panoramica su come configurare e utilizzare l'API Automatic Request Batching per Amazon SQS.

## Verifica i prerequisiti
<a name="sqs-auto-batch-requirements"></a>

È necessario utilizzare la versione *2.28.0* o successiva dell'SDK for Java 2.x per avere accesso all'API di batch. Il tuo Maven `pom.xml` dovrebbe contenere almeno i seguenti elementi.

```
<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 Ultima versione](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)

## Crea un gestore di batch
<a name="sqs-auto-batch-create"></a>

L'API di raggruppamento automatico delle richieste è implementata dall'[SqsAsyncBatchManager](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html)interfaccia. È possibile creare un'istanza del gestore in due modi.

### Configurazione predefinita utilizzando `SqsAsyncClient`
<a name="sqs-batch-manager-create-default"></a>

Il modo più semplice per creare un gestore di batch consiste nel chiamare il metodo `batchManager` factory su un'[SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)istanza esistente. L'approccio semplice è illustrato nel frammento seguente. 

```
SqsAsyncClient asyncClient = SqsAsyncClient.create();
SqsAsyncBatchManager sqsAsyncBatchManager = asyncClient.batchManager();
```

Quando utilizzate questo approccio, l'`SqsAsyncBatchManager`istanza utilizza i valori predefiniti mostrati nella tabella della sezione. [Sostituisci le impostazioni di configurazione per `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) Inoltre, l'`SqsAsyncBatchManager`istanza utilizza `ExecutorService` l'`SqsAsyncClient`istanza da cui è stata creata.

### Configurazione personalizzata utilizzando `SqsAsyncBatchManager.Builder`
<a name="sqs-batch-manager-create-custom"></a>

Per casi d'uso più avanzati, è possibile personalizzare il gestore batch utilizzando [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). Utilizzando questo approccio per creare un'`SqsAsyncBatchManager`istanza, è possibile ottimizzare il comportamento di batch. Il seguente frammento mostra un esempio di come utilizzare il builder per personalizzare il comportamento del batch.

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

Quando utilizzate questo approccio, potete regolare le impostazioni sull'`BatchOverrideConfiguration`oggetto mostrate nella tabella della sezione. [Sostituisci le impostazioni di configurazione per `SqsAsyncBatchManager`](#sqs-auto-batch-config-settings) È inoltre possibile fornire una personalizzazione [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)per il gestore dei batch utilizzando questo approccio.

## Inviare messaggi
<a name="sqs-auto-batch-send"></a>

Per inviare messaggi con il gestore batch, usa il `[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))` metodo. L'SDK memorizza le richieste e le invia come batch quando vengono raggiunti `sendRequestFrequency` i valori `maxBatchSize` or.

L'esempio seguente mostra una `sendMessage` richiesta immediatamente successiva a un'altra richiesta. In questo caso, l'SDK invia entrambi i messaggi in un unico batch.

```
// Sending the first message
CompletableFuture<SendMessageResponse> futureOne = 
    sqsAsyncBatchManager.sendMessage(r -> r.messageBody("One").queueUrl("queue"));

// Sending the second message
CompletableFuture<SendMessageResponse> futureTwo = 
    sqsAsyncBatchManager.sendMessage(r -> r.messageBody("Two").queueUrl("queue"));

// Waiting for both futures to complete and retrieving the responses
SendMessageResponse messageOne = futureOne.join();
SendMessageResponse messageTwo = futureTwo.join();
```

## Modifica il timeout di visibilità dei messaggi
<a name="sqs-auto-batch-change-vis"></a>

È possibile modificare il timeout di visibilità dei messaggi in un batch utilizzando il [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))metodo. L'SDK memorizza le richieste nel buffer e le invia in batch quando vengono raggiunti `sendRequestFrequency` i valori `maxBatchSize` or.

L'esempio seguente mostra come chiamare il `changeMessageVisibility` metodo.

```
CompletableFuture<ChangeMessageVisibilityResponse> futureOne =
    sqsAsyncBatchManager.changeMessageVisibility(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
ChangeMessageVisibilityResponse response = futureOne.join();
```

## Eliminare i messaggi
<a name="sqs-auto-batch-delete"></a>

È possibile eliminare i messaggi in batch utilizzando il [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))metodo. L'SDK memorizza le richieste nel buffer e le invia come batch quando vengono raggiunti `sendRequestFrequency` i valori `maxBatchSize` or.

L'esempio seguente mostra come chiamare il `deleteMessage` metodo.

```
CompletableFuture<DeleteMessageResponse> futureOne = 
    sqsAsyncBatchManager.deleteMessage(r -> 
        r.receiptHandle("receiptHandle")
         .queueUrl("queue"));
DeleteMessageResponse response = futureOne.join();
```

## Ricevere messaggi
<a name="sqs-auto-batch-receive"></a>

### Usa le impostazioni predefinite
<a name="sqs-auto-batch-receive-default-settings"></a>

Quando esegui il polling del `[SqsAsyncBatchManager\$1receiveMessage](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html#receiveMessage(java.util.function.Consumer))` metodo nell'applicazione, il gestore batch recupera i messaggi dal suo buffer interno, che l'SDK aggiorna automaticamente in background.

L'esempio seguente mostra come chiamare il metodo. `receiveMessage`

```
CompletableFuture<ReceiveMessageResponse> responseFuture = 
    sqsAsyncBatchManager.receiveMessage(r -> r.queueUrl("queueUrl"));
```

### Usa impostazioni personalizzate
<a name="sqs-auto-batch-receive-custom-settings"></a>

Se desideri personalizzare ulteriormente la richiesta, ad esempio impostando tempi di attesa personalizzati e specificando il numero di messaggi da recuperare, puoi personalizzare la richiesta come mostrato nell'esempio seguente.

```
CompletableFuture<ReceiveMessageResponse> response = 
    sqsAsyncBatchManager.receiveMessage(r -> 
        r.queueUrl("queueUrl")
         .waitTimeSeconds(5)
         .visibilityTimeout(20));
```

**Nota**  
Se chiami `receiveMessage` con un `[ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)` che include uno dei seguenti parametri, l'SDK ignora il gestore batch e invia una normale richiesta asincrona: `receiveMessage`  
`messageAttributeNames`
`messageSystemAttributeNames`
`messageSystemAttributeNamesWithStrings`
`overrideConfiguration`

## Sostituisci le impostazioni di configurazione per `SqsAsyncBatchManager`
<a name="sqs-auto-batch-config-settings"></a>

È possibile modificare le seguenti impostazioni quando si crea un'`SqsAsyncBatchManager`istanza. Il seguente elenco di impostazioni è disponibile in [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).


| Impostazione | Description | Valore predefinito | 
| --- | --- | --- | 
| maxBatchSize | Numero massimo di richieste per batch per ciascuna SendMessageBatchRequestChangeMessageVisibilityBatchRequest, oDeleteMessageBatchRequest. Il valore massimo è 10. | 10 | 
| sendRequestFrequency |  Tempo prima dell'invio di un batch, a meno che non `maxBatchSize` venga raggiunto prima. Valori più alti possono ridurre le richieste ma aumentare la latenza.  | 200 ms | 
| receiveMessageVisibilityTimeout | Timeout di visibilità per i messaggi. Se non è impostato, viene utilizzato il valore predefinito della coda. | L'impostazione predefinita della coda | 
| receiveMessageMinWaitDuration | Tempo di attesa minimo per le receiveMessage richieste. Evita di impostarlo su 0 per evitare sprechi di CPU. | 50 ms | 
| receiveMessageSystemAttributeNames | Elenco dei [nomi degli attributi di sistema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/MessageSystemAttributeName.html) da richiedere per receiveMessage le chiamate. | Nessuno | 
| receiveMessageAttributeNames | Elenco dei [nomi degli attributi](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-message-attributes) da richiedere per receiveMessage le chiamate. | Nessuno | 

# Lavora con le code di Amazon Simple Queue Service messaggi
<a name="examples-sqs-message-queues"></a>

Una *coda di messaggi* è il contenitore logico utilizzato per inviare messaggi in modo affidabile. Amazon Simple Queue Service Sono disponibili due tipi di code: *standard* e *first-in, first-out* (FIFO). [Per ulteriori informazioni sulle code e sulle differenze tra questi tipi, consulta la Guida per gli Amazon Simple Queue Service sviluppatori.](https://docs.aws.amazon.com//AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html)

Questo argomento descrive come creare, elencare, eliminare e ottenere l'URL di una Amazon Simple Queue Service coda utilizzando. AWS SDK per Java

La `sqsClient` variabile utilizzata negli esempi seguenti può essere creata dal seguente frammento.

```
SqsClient sqsClient = SqsClient.create();
```

[Quando si crea un `SqsClient` utilizzando il `create()` metodo statico, l'SDK configura la regione utilizzando la catena di provider di aree [predefinita e le credenziali utilizzando la catena di provider](region-selection.md#default-region-provider-chain) di credenziali predefinita.](credentials-chain.md)

## Crea una coda
<a name="sqs-create-queue"></a>

Utilizzate il `SqsClient’s` `createQueue` metodo e fornite un `[CreateQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/CreateQueueRequest.html)` oggetto che descriva i parametri della coda come mostrato nel seguente frammento di codice.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

```
            CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
                .queueName(queueName)
                .build();

            sqsClient.createQueue(createQueueRequest);
```

Vedi l'esempio [completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L52) su. GitHub

## Elencare code
<a name="sqs-list-queues"></a>

Per elencare le Amazon Simple Queue Service code relative al tuo account, chiama il `SqsClient’s` `listQueues` metodo con un `[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)` oggetto.

Quando utilizzate il modulo del [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())metodo che non accetta parametri, il servizio restituisce *tutte le code, fino a 1.000 code*. 

È possibile fornire un prefisso per il nome della coda all'`[ListQueuesRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ListQueuesRequest.html)`oggetto per limitare i risultati alle code che corrispondono a tale prefisso, come illustrato nel codice seguente.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

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

[Guarda l'esempio completo su.](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L79) GitHub

## Ottenere l'URL di una coda
<a name="sqs-get-queue-url"></a>

Il codice seguente mostra come ottenere l'URL di una coda chiamando il `SqsClient’s` `getQueueUrl` metodo con un `[GetQueueUrlRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/GetQueueUrlRequest.html)` oggetto.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

```
            GetQueueUrlResponse getQueueUrlResponse =
                sqsClient.getQueueUrl(GetQueueUrlRequest.builder().queueName(queueName).build());
            String queueUrl = getQueueUrlResponse.queueUrl();
            return queueUrl;
```

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/7486a1a092aa8e16a21698ef26f9d524fef62e55/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L70) su. GitHub

## Elimina una coda
<a name="sqs-delete-queue"></a>

Fornisci l'[URL](#sqs-get-queue-url) della coda all'`[DeleteQueueRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/DeleteQueueRequest.html)`oggetto. Quindi chiamate il `SqsClient’s` `deleteQueue` metodo per eliminare una coda come mostrato nel codice seguente.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/6240df86c5f17eae1e23d1139d1435c7dc4b2a11/javav2/example_code/sqs/src/main/java/com/example/sqs/DeleteQueue.java#L48) su. GitHub

## Ulteriori informazioni
<a name="more-information"></a>
+  [CreateQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html)nell' Amazon Simple Queue Service API Reference
+  [GetQueueUrl](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueUrl.html)nell' Amazon Simple Queue Service API Reference
+  [ListQueues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html)nell' Amazon Simple Queue Service API Reference
+  [DeleteQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html)nell' Amazon Simple Queue Service API Reference

# Inviare, ricevere ed eliminare Amazon Simple Queue Service messaggi
<a name="examples-sqs-messages"></a>

Un messaggio è una parte di dati che possono essere inviati e ricevuti da componenti distribuiti. I messaggi vengono sempre distribuiti tramite una [coda SQS](examples-sqs-message-queues.md).

La `sqsClient` variabile utilizzata negli esempi seguenti può essere creata dal seguente frammento.

```
SqsClient sqsClient = SqsClient.create();
```

[Quando si crea un `SqsClient` utilizzando il `create()` metodo statico, l'SDK configura la regione utilizzando la catena di provider di aree [predefinita e le credenziali utilizzando la catena di provider](region-selection.md#default-region-provider-chain) di credenziali predefinita.](credentials-chain.md)

## Invio di un messaggio
<a name="sqs-message-send"></a>

Aggiungi un singolo messaggio a una Amazon Simple Queue Service coda chiamando il metodo client. SqsClient `sendMessage` Fornisci un [SendMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageRequest.html)oggetto che contenga l'[URL](examples-sqs-message-queues.md#sqs-get-queue-url) della coda, il corpo del messaggio e il valore di ritardo opzionale (in secondi).

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

```
            sqsClient.sendMessage(SendMessageRequest.builder()
                .queueUrl(queueUrl)
                .messageBody("Hello world!")
                .delaySeconds(10)
                .build());

            sqsClient.sendMessage(sendMsgRequest);
```

## Invia più messaggi in una richiesta
<a name="sqs-messages-send-multiple"></a>

Invia più messaggi in una singola richiesta utilizzando il metodo SqsClient di `sendMessageBatch`. Questo metodo richiede un file [SendMessageBatchRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequest.html)che contenga l'URL della coda e un elenco di messaggi da inviare. (Ogni messaggio è un [SendMessageBatchRequestEntry](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SendMessageBatchRequestEntry.html).) Puoi anche ritardare l'invio di un messaggio specifico impostando un valore di ritardo nel messaggio.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L133) su GitHub.

## Recuperare messaggi
<a name="sqs-messages-receive"></a>

Recupera eventuali messaggi che si trovano attualmente nella coda chiamando il metodo SqsClient di `receiveMessage`. Questo metodo accetta un file [ReceiveMessageRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html)che contiene l'URL della coda. Puoi specificare il numero massimo di messaggi da restituire. I messaggi vengono restituiti come un elenco di oggetti [Message](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/Message.html).

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L148) su. GitHub

## Eliminare un messaggio dopo la ricezione
<a name="sqs-messages-delete"></a>

Dopo aver ricevuto un messaggio e averne elaborato il contenuto, eliminatelo dalla coda inviando al metodo l'handle di ricezione e l'URL di coda del `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))messaggio.

 **Importazioni** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.util.List;
```

 **Codice** 

```
        try {
            for (Message message : messages) {
                DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                        .queueUrl(queueUrl)
                        .receiptHandle(message.receiptHandle())
                        .build();
                sqsClient.deleteMessage(deleteMessageRequest);
            }
```

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/cf25559da654a7b74bec039c0ab9397dc5951dd4/javav2/example_code/sqs/src/main/java/com/example/sqs/SQSExample.java#L187) su. GitHub

## Ulteriori informazioni
<a name="more-info"></a>
+  [Come funzionano Amazon Simple Queue Service le code](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html) nella Guida per gli Amazon Simple Queue Service sviluppatori
+  [SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)nell' Amazon Simple Queue Service API Reference
+  [SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)nell' Amazon Simple Queue Service API Reference
+  [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)nell' Amazon Simple Queue Service API Reference
+  [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)nell' Amazon Simple Queue Service API Reference

# Lavora con Amazon Transcribe
<a name="examples-transcribe"></a>

L'esempio seguente mostra come funziona lo streaming bidirezionale con Amazon Transcribe. Lo streaming bidirezionale implica che ci sia un flusso di dati verso il servizio e in direzione opposta in tempo reale. L'esempio utilizza la trascrizione Amazon Transcribe in streaming per inviare un flusso audio e ricevere un flusso di testo trascritto in tempo reale.

Per ulteriori informazioni [su questa funzionalità, consulta Streaming Transcription](https://docs.aws.amazon.com//transcribe/latest/dg/streaming.html) nella Guida per gli Amazon Transcribe sviluppatori.

Per [iniziare a utilizzare](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html), consulta la sezione Guida introduttiva nella Guida per gli Amazon Transcribe sviluppatori. Amazon Transcribe

## Configura il microfono
<a name="set-up-the-microphone"></a>

Questo codice usa il pacchetto javax.sound.sampled per lo streaming audio da un dispositivo di input.

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/Microphone.java) su GitHub.

## Crea un editore
<a name="create-a-publisher"></a>

Questo codice implementa un editore che pubblica dati audio dal flusso Amazon Transcribe audio.

 **Codice** 

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

Vedi l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/AudioStreamPublisher.java) su. GitHub

## Crea il client e avvia lo streaming
<a name="create-the-client-and-start-the-stream"></a>

Nel metodo principale, è necessario creare un oggetto richiesta, avviare il flusso di input audio e creare un'istanza per il publisher con l’input audio.

È inoltre necessario creare un [StartStreamTranscriptionResponseHandler](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/transcribestreaming/model/StartStreamTranscriptionResponseHandler.html)file per specificare come gestire la risposta da Amazon Transcribe.

Quindi, usa il `startStreamTranscription` metodo TranscribeStreamingAsyncClient's per avviare lo streaming bidirezionale.

 **Importazioni** 

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

 **Codice** 

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

Guarda l'[esempio completo](https://github.com/awsdocs/aws-doc-sdk-examples/blob/ac748d8ef99cd17e297cb74fe13aa671e2679088/javav2/example_code/transcribe/src/main/java/com/amazonaws/transcribe/BidirectionalStreaming.java) su. GitHub

## Ulteriori informazioni
<a name="more-info"></a>
+  [Come funziona](https://docs.aws.amazon.com//transcribe/latest/dg/how-it-works.html) nella Guida per gli Amazon Transcribe sviluppatori.
+  [Guida introduttiva allo streaming audio](https://docs.aws.amazon.com//transcribe/latest/dg/getting-started.html) nella Guida per Amazon Transcribe gli sviluppatori.