Concetti

Questo argomento spiega alcuni dei concetti chiave per l'utilizzo di Oracle Cloud Infrastructure SDK per Java.

Chiamate sincrone

Per effettuare chiamate sincrone, creare un'istanza del client sincrono. Il pattern generale per i client sincroni è che per un servizio denominato Example, ci sarà un'interfaccia denominata ExampleService e l'implementazione del client sincrono sarà denominata ExampleServiceClient. Di seguito è riportato un esempio di creazione di un client di storage degli oggetti.

AuthenticationDetailsProvider provider = ...;
ObjectStorage clientWithDefaultClientConfig = new ObjectStorageClient(provider);
clientWithDefaultClientConfig.setRegion(Region.US_ASHBURN_1);

ClientConfiguration clientConfig = ...;
ObjectStorage clientWithExplicitClientConfig = new ObjectStorageClient(provider, clientConfig);
clientWithExplicitClientConfig.setRegion(Region.US_ASHBURN_1);

Le chiamate sincrone verranno bloccate fino a quando la risposta non sarà disponibile. Tutte le API SDK restituiscono un oggetto di risposta (indipendentemente dal fatto che l'API invii o meno contenuto). In genere, l'oggetto risposta contiene almeno un ID richiesta che è possibile utilizzare quando si contatta il Supporto Oracle per assistenza su una richiesta specifica.

ObjectStorage client = ...;
GetBucketResponse response = client.getBucket(
    GetBucketRequest.builder().namespaceName("myNamespace").bucketName("myBucket").build());
String requestId = response.getOpcRequestId();
Bucket bucket = response.getBucket();
System.out.println(requestId);
System.out.println(bucket.getName());

Chiamate asincrone

Per effettuare chiamate asincrone, creare un'istanza del client asincrono. Il modello generale per i client asincroni è che per un servizio denominato Esempio, ci sarà un'interfaccia denominata ExampleServiceAsync e l'implementazione client asincrona sarà denominata ExampleServiceAsyncClient. Di seguito è riportato un esempio di creazione di un client di storage degli oggetti.

AuthenticationDetailsProvider provider = ...;
ObjectStorageAsync clientWithDefaultClientConfig = new ObjectStorageAsyncClient(provider);
clientWithDefaultClientConfig.setRegion(Region.US_ASHBURN_1);
 
ClientConfiguration clientConfig = ...;
ObjectStorageAsync clientWithExplicitClientConfig = new ObjectStorageAsyncClient(provider, clientConfig);
clientWithExplicitClientConfig.setRegion(Region.US_ASHBURN_1);

Le chiamate asincrone vengono restituite immediatamente. È necessario fornire un AsyncHandler che verrà richiamato al termine della chiamata in modo corretto o non riuscito:

ObjectStorageAsync client = ...;
 
AsyncHandler<GetBucketRequest, GetBucketResponse> handler = new AsyncHandler<GetBucketRequest, GetBucketResponse>() {
        @Override
        public void onSuccess(GetBucketRequest request, GetBucketResponse response) {
            String requestId = response.getOpcRequestId();
            Bucket bucket = response.getBucket();
            System.out.println(requestId);
            System.out.println(bucket.getName());
        }

        @Override
        public void onError(GetBucketRequest request, Throwable error) {
            error.printStackTrace();
        }
};
 
Future<GetBucketResponse> future = client.getBucket(
        GetBucketRequest.builder().namespaceName("myNamespace").bucketName("myBucket").build(),
        handler);

Polling con camerieri

L'SDK offre camerieri che consentono al codice di attendere fino a quando una risorsa specifica raggiunge lo stato desiderato. Un cameriere può essere richiamato sia in modo bloccante che non bloccante (con callback asincrono) e attenderà fino al raggiungimento dello stato desiderato o al superamento di un timeout. I camerieri astraggono la logica di polling che altrimenti dovresti scrivere in una chiamata a metodo singolo facile da usare.

I camerieri vengono ottenuti tramite il client del servizio (client.getWaiters()). Al metodo waiters.for<Resource> vengono passati sia uno stato Get<Resource>Request che uno stato del ciclo di vita desiderato. Ad esempio:

public static Instance waitForInstanceProvisioningToComplete(  ComputeClient computeClient, String instanceId) throws Exception {
        
    ComputeWaiters waiters = computeClient.getWaiters();
    GetInstanceResponse response = waiters.forInstance(
        GetInstanceRequest.builder().instanceId(instanceId).build(),
        Instance.LifecycleState.Running)
    .execute();
        
    return response.getInstance();
}

Ogni metodo waiters.for<Resource> dispone di due versioni:

  • Una versione utilizza i valori di polling predefiniti. Ad esempio:

    waiters.forInstance(GetInstanceRequest, LifecycleState)
  • L'altra versione ti dà il pieno controllo su quanto tempo aspettare e quanto tempo tra i tentativi di polling. Ad esempio:

    waiters.forInstance(GetInstanceRequest, LifecycleState, TerminationStrategy, DelayStrategy)

Modello di threading

Un client diventa thread-safe quando viene inizializzato. Dopo aver impostato l'endpoint, è possibile utilizzare in modo sicuro un client in più thread e contemporaneamente richiamarvi metodi.

È possibile riutilizzare un client su più richieste, sia tra thread concorrenti che all'interno di un singolo thread. A meno che le risorse dell'ambiente non siano limitate, è necessario chiudere il client solo immediatamente prima che non rientri nell'ambito di applicazione.

Nota

Questa garanzia si applica solo all'implementazione JAX-RS predefinita, Jersey. Quando si utilizza un'implementazione alternativa, è necessario gestire autonomamente la sicurezza dei thread. Per ulteriori informazioni, vedere Configurazione del kit SDK

Caricamento di oggetti di grandi dimensioni

Il servizio di storage degli oggetti supporta i caricamenti multiparte per semplificare i caricamenti di oggetti di grandi dimensioni suddividendo l'oggetto di grandi dimensioni in parti. L'SDK per Java supporta le operazioni di caricamento multiparte raw per casi d'uso avanzati, nonché una classe di caricamento di livello superiore che utilizza le API di caricamento multiparte. Utilizzo dei caricamenti multiparte fornisce collegamenti alle API utilizzate per le operazioni di caricamento multiparte. I caricamenti multiparte di livello superiore vengono implementati utilizzando UploadManager, che consente di suddividere un oggetto di grandi dimensioni in parti, caricare le parti in parallelo, quindi ricombinare e eseguire il commit delle parti come un singolo oggetto nello storage.

L'esempio UploadObject mostra come utilizzare UploadManager per suddividere automaticamente un oggetto in parti da caricare per semplificare l'interazione con il servizio di storage degli oggetti.

Nuovi tentativi

A partire dalla versione 2.10.0, l'SDK per Java è configurato per impostazione predefinita per riprovare a eseguire determinate operazioni SDK non riuscite. L'SDK consente di specificare la strategia da utilizzare per la modalità di gestione dei nuovi tentativi, incluso il numero di tentativi da eseguire, la condizione in base alla quale l'SDK deve riprovare a eseguire un'operazione e quando interrompere il nuovo tentativo di un'operazione. È possibile impostare questi parametri a livello di client e a livello di singola richiesta.

Per determinare quali operazioni del servizio hanno nuovi tentativi abilitati per impostazione predefinita, fare riferimento alla descrizione delle operazioni del servizio nell'SDK.

Nota

I nuovi tentativi non sono attualmente supportati per i client asincroni

Per impostazione predefinita, l'SDK riproverà le operazioni con i codici di stato di risposta HTTP 409 (con un codice di errore IncorrectState), 429, 500, 502, 503, 504, errori di timeout (ad esempio connessione HTTP e timeout di lettura), errori di connessione delle richieste, eccezioni delle richieste e eccezioni degli interruttori di circuito.

La configurazione dei nuovi tentativi predefinita più recente e l'elenco degli errori che è possibile rieseguire possono essere visualizzati su Github.

Disabilitazione dei nuovi tentativi predefiniti

Per disattivare la funzione di nuovi tentativi predefinita, è possibile effettuare una delle seguenti operazioni:

  1. Impostare la variabile di ambiente OCI_SDK_DEFAULT_RETRY_ENABLED su false per disabilitare i tentativi predefiniti a livello globale
  2. Eseguire l'override dei tentativi predefiniti per un'istanza client specifica. Questo esempio mostra l'override dei nuovi tentativi predefiniti per objectStorageClient:

    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder()
                    .retryConfiguration(RetryConfiguration.builder().terminationStrategy(new MaxAttemptsTerminationStrategy(1))
                            .build())
                    .build();
    ObjectStorage objectStorageClient = ObjectStorageClient.builder().configuration(clientConfiguration).build(provider);
    
  3. Esegue l'override dei tentativi predefiniti per un'istanza di richiesta specifica. Questo esempio mostra i tentativi di sostituzione per putObjectRequest:

    PutObjectRequest putObjectRequest =
            PutObjectRequest.builder()
                    .putObjectBody(stream)
                    .bucketName(bucketName)
                    .objectName(objectName)
                    .namespaceName(namespace)
                    .retryConfiguration(RetryConfiguration.builder().terminationStrategy(new MaxAttemptsTerminationStrategy(1)).build())
                    .build();

Riprova precedenza comportamento

  • Qualsiasi nuova configurazione definita in modo esplicito a livello di richiesta sostituirà la configurazione del nuovo tentativo a livello di client o la configurazione del nuovo tentativo a livello globale e la sostituzione della variabile di ambiente per l'istanza di richiesta specifica.
  • Qualsiasi configurazione di nuovo tentativo definita in modo esplicito a livello di client sostituirà la configurazione di nuovo tentativo globale e l'override a livello di variabile di ambiente per quella particolare istanza client.

Riprova strategie

È possibile specificare la strategia da utilizzare per la modalità di gestione dei nuovi tentativi, incluso il numero di tentativi da eseguire, la condizione in base alla quale l'SDK deve riprovare a eseguire un'operazione e quando interrompere il nuovo tentativo di un'operazione. È possibile impostare questi parametri a livello di client e a livello di singola richiesta.
Nota

È possibile visualizzare su Github la configurazione dei nuovi tentativi predefinita più recente e l'elenco degli errori che è possibile ritentare.

Strategia ritardo

Il parametro delayStrategy determina il tempo di attesa tra ogni chiamata di nuovo tentativo. Sono disponibili due opzioni per questo parametro:

  • FixedTimeDelayStrategy (milliseconds) - Ogni nuovo tentativo viene ritardato di un numero di millisecondi specificato.
  • ExponentialBackoffDelayStrategy (milliseconds) - Il tempo di ritardo per le chiamate di nuovo tentativo successive aumenta di un fattore esponenziale di 2 fino a raggiungere il ritardo massimo definito (in millisecondi), con un valore di base di un millisecondo.

La strategia di ritardo predefinita è impostata su ExponentialBackoffDelayStrategy con un valore jitter compreso tra 0 e 1000 millisecondi e un tempo di attesa massimo tra chiamate di 30 secondi.

Condizione nuovo tentativo

retryCondition definisce una funzione con un argomento di errore che restituisce un valore booleano che indica se riprovare o meno. L'operazione verrà rieseguita se questa funzione restituisce true.

Strategia cessazione

Il parametro terminationStrategy definisce quando terminare i tentativi. Questo parametro supporta le opzioni riportate di seguito.

  • MaxTimeTerminationStrategy (milliseconds): definisce la durata totale in millisecondi per la quale il nuovo tentativo tenta.
  • MaxAttemptsTerminationStrategy (attempts): definisce il numero totale di tentativi.

La strategia di interruzione predefinita per gli SDK OCI è un valore MaxAttemptsTerminationStrategy di 8.

Esempi di nuovi tentativi

Java

Questo esempio mostra come configurare e utilizzare i nuovi tentativi con SDK per Java:

/**
 * Copyright (c) 2016, 2021, Oracle and/or its affiliates.  All rights reserved.
 * This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
 */
import com.oracle.bmc.ClientConfiguration;
import com.oracle.bmc.ConfigFileReader;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
import com.oracle.bmc.identity.Identity;
import com.oracle.bmc.identity.IdentityClient;
import com.oracle.bmc.identity.requests.ListRegionsRequest;
import com.oracle.bmc.identity.responses.ListRegionsResponse;
import com.oracle.bmc.retrier.Retriers;
import com.oracle.bmc.retrier.RetryConfiguration;
import com.oracle.bmc.waiter.FixedTimeDelayStrategy;
import com.oracle.bmc.waiter.MaxAttemptsTerminationStrategy;

/**
 * This example demonstrates how to use the SDK retries.
 *
 * Retry configuration may be set at
 * a) the SDK level (using {@link Retriers#setDefaultRetryConfiguration(RetryConfiguration)}
 * b) the client level (using {@link ClientConfiguration}
 * c) the request level (using {@link com.oracle.bmc.requests.BmcRequest#setRetryConfiguration(RetryConfiguration)}
 */
public class RetryExample {
    public static void main(String[] args) throws Exception {
        String configurationFilePath = "~/.oci/config";
        String profile = "DEFAULT";

        // Configuring the AuthenticationDetailsProvider. It's assuming there is a default OCI config file
        // "~/.oci/config", and a profile in that config with the name "DEFAULT". Make changes to the following
        // line if needed and use ConfigFileReader.parse(configurationFilePath, profile);

        final ConfigFileReader.ConfigFile configFile = ConfigFileReader.parseDefault();

        final AuthenticationDetailsProvider provider =
                new ConfigFileAuthenticationDetailsProvider(configFile);

        // Set the default retry strategy for all operations to set retry attempts to 3
        Retriers.setDefaultRetryConfiguration(
                RetryConfiguration.builder()
                        .terminationStrategy(new MaxAttemptsTerminationStrategy(3))
                        .build());

        // Override the default retry strategy for the identity client and update retry attempts to 4
        final Identity identityClient =
                new IdentityClient(
                        provider,
                        ClientConfiguration.builder()
                                .retryConfiguration(
                                        RetryConfiguration.builder()
                                                .terminationStrategy(
                                                        new MaxAttemptsTerminationStrategy(4))
                                                .build())
                                .build());

        // Override the client's retry strategy for the list regions request and wait for 5ms between retrying
        final ListRegionsRequest listRegionsRequest =
                ListRegionsRequest.builder()
                        .retryConfiguration(
                                RetryConfiguration.builder()
                                        .terminationStrategy(new MaxAttemptsTerminationStrategy(2))
                                        .delayStrategy(new FixedTimeDelayStrategy(5L))
                                        .build())
                        .build();
        final ListRegionsResponse listRegionsResponse =
                identityClient.listRegions(listRegionsRequest);

        System.out.println(listRegionsResponse.getItems());
    }
}

Interruttori automatici

A partire dalla versione 2.10.0, l'SDK per Java fornisce il supporto predefinito per gli interruttori di circuito per i client di servizio che hanno abilitato gli interruttori di circuito SDK predefiniti. Gli interruttori di circuito aiutano a impedire al client di sovraccaricare il servizio bloccando l'invio delle richieste al servizio dopo il raggiungimento di una determinata soglia di errore.

Nota

Gli interruttori di circuito predefiniti non sono attualmente supportati per i client asincroni.

Per gli interruttori di circuito predefiniti, tutti gli errori che possono essere ripetuti verranno trattati come errori per gli interruttori di circuito. Per determinare i client del servizio per i quali sono abilitati gli interruttori di circuito, fare riferimento alla descrizione del client del servizio nell'SDK.

Nota

La configurazione dell'interruttore di circuito predefinito può essere visualizzata su Github.

Configurazione dell'interruttore

I seguenti parametri definiscono un interruttore:

  • Soglia tasso di errore: lo stato dell'interruttore cambia da CHIUSO ad APERTO quando il tasso di errore è uguale o maggiore di questa soglia. Ad esempio, quando più del 50% delle chiamate registrate non sono riuscite, l'interruttore si aprirà.
  • Reimposta timeout - il timeout dopo il quale un interruttore di circuito aperto tenterà di eseguire una richiesta se viene effettuata una richiesta
  • Eccezioni errore: l'elenco delle eccezioni che verranno considerate come errori per il circuito
  • Numero minimo di chiamate/soglia volume - il numero minimo di chiamate richieste (per periodo finestra scorrevole) prima che l'interruttore possa calcolare il tasso di errore

Configurazione predefinita interruttore

Di seguito è riportata la configurazione predefinita dell'interruttore circuito.

  • Soglia tasso di errore: 80%. Quando l'80% delle richieste calcolate per una finestra temporale di 120 secondi non è riuscita, il circuito passerà da chiuso ad aperto.
  • Numero minimo di chiamate/soglia volume: 10, per la finestra temporale definita sopra di 120 secondi.
  • Reimposta timeout: l'interruttore di circuito attenderà 30 secondi prima di impostare l'interruttore sullo stato halfOpen e riprovare a eseguire l'azione.
  • Eccezioni errore: gli errori per il circuito verranno registrati solo per le eccezioni ritentabili o transitorie. I codici di risposta HTTP 409 (con un IncorrectState), 429, 500, 502, 503 e 504, la richiesta HTTP e altri timeout, gli errori e le eccezioni di connessione alla richiesta vengono considerati tutti errori che attiveranno un interruttore.

Disabilitazione dell'interruttore di circuito predefinito

Per disattivare la funzione di interruttore predefinito, è possibile effettuare una delle operazioni riportate di seguito.

  1. Impostare la variabile di ambiente OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED su false.
  2. Modificare la configurazione predefinita dell'interruttore automatico per un'istanza client. L'esempio seguente mostra come eseguire questa operazione con un'istanza IdentityClient.
    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder().circuitBreakerConfiguration(CircuitBreakerUtils.getNoCircuitBreakerConfiguration()).build();
     
            // Create Clients using above ClientConfiguration
            IdentityClient identityClient = new IdentityClient(provider, clientConfiguration);

Priorità comportamento interruttore

Qualsiasi configurazione dell'interruttore di circuito definita in modo esplicito a livello di client sostituirà la configurazione dell'interruttore di circuito predefinito globale e l'override a livello di ambiente per tale client.

Per ulteriori informazioni sugli interruttori di circuito e sulla configurazione dell'interruttore di circuito predefinito, vedere questo esempio su Github.

Richieste non elaborate

Le richieste raw sono utili, e in alcuni casi necessarie. I casi d'uso tipici sono: quando si utilizza il proprio client HTTP, si effettua una richiesta autenticata da OCI a un endpoint alternativo e si effettua una richiesta a un'API OCI che non è attualmente supportata nell'SDK. L'SDK per Java espone la classe DefaultRequestSigner che è possibile utilizzare per creare un'istanza RequestSigner per richieste non standard.

L'esempio Richiesta raw in GitHub mostra come:

  • creare un provider di autenticazione e richiedere il firmatario
  • integrazione con un client HTTP (Jersey in questo esempio) per autenticare le richieste

Impostazione degli endpoint

Gli endpoint del servizio possono essere impostati in tre modi.

  • Chiamare setEndpoint() nell'istanza del servizio. In questo modo è possibile specificare un nome host completo, ad esempio https://www.example.com.
  • Chiamare setRegion() nell'istanza del servizio. In questo modo viene selezionato il nome host appropriato per il servizio per l'area specificata. Tuttavia, se il servizio non è supportato nell'area impostata, l'SDK per Java restituisce un errore.
  • Passare l'area nel file di configurazione. Per ulteriori informazioni, vedere SDK and CLI Configuration File.

Tenere presente che non è possibile utilizzare un'istanza del servizio per comunicare con aree diverse. Se è necessario effettuare richieste in aree diverse, creare più istanze di servizio.

Endpoint dedicati

Gli endpoint dedicati sono i modelli di endpoint definiti dal servizio per un realm specifico a livello di client. L'SDK Java OCI consente di abilitare l'uso della funzione dei modelli di endpoint specifici del realm sia a livello di applicazione che a livello di client. Il valore minimo consigliato è di almeno 100 MB per le piattaforme a 32 bit e di almeno 144 MB per le piattaforme a 64 bit.
Nota

Il set di valori a livello di client ha la precedenza sul set di valori a livello di applicazione.

Abilitazione dei modelli di endpoint specifici del realm a livello di applicazione:

Per abilitare la funzione dei modelli di endpoint specifici del realm a livello di applicazione, impostare la variabile di ambiente OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED su true.
Nota

Il valore booleano non fa distinzione tra maiuscole e minuscole.

Abilitazione dei modelli di endpoint specifici del realm a livello di applicazione:

Per abilitare la funzione dei modelli di endpoint specifici del realm a livello di client, impostare il flag nel codice come mostrato di seguito.

Per l'SDK OCI per Java:

ObjectStorage client = ObjectStorageClient.builder().build(provider);
client.useRealmSpecificEndpointTemplate(true);

Per un esempio completo, vedere UseRealmSpecificEndpointsExample su Github.

Per l'SDK OCI legacy per Java:

ObjectStorage client = new ObjectStorageClient(provider);
client.useRealmSpecificEndpointTemplate(true);

Per un esempio completo, vedere UseRealmSpecificEndpointsExample in GitHub.

Inoltra compatibilità e enum

Se si dispone di una logica condizionale basata su un enum, assicurarsi che il codice gestisca il caso UnknownEnumValue per garantire la compatibilità in avanti. Alcuni campi di risposta sono di tipo enum, ma in futuro i singoli servizi potrebbero restituire valori non coperti da enum esistenti per quel campo. Per affrontare questa possibilità, ogni campo di risposta di tipo enum ha un valore aggiuntivo denominato UnknownEnumValue. Se un servizio restituisce un valore non riconosciuto dalla versione dell'SDK in uso, il campo di risposta verrà impostato su questo valore.

Supporto per nuove regioni

Se si utilizza una versione dell'SDK rilasciata prima dell'annuncio di una nuova area, è possibile utilizzare una soluzione alternativa per raggiungerla.

Un'area è un'area geografica localizzata. Per ulteriori informazioni sulle aree e su come identificarle, vedere Aree e domini di disponibilità.

Un realm è un set di aree che condividono entità. È possibile identificare il realm guardando il nome del dominio alla fine dell'indirizzo di rete. Ad esempio, il realm per xyz.abc.123.oraclecloud.com è oraclecloud.com.

È necessario prima chiamare Region.register per registrare la nuova area, quindi è possibile impostare l'area utilizzando il file di configurazione o chiamando il metodo setRegion.

Nota

Una volta registrata un'area, l'endpoint della federazione non è più necessario durante l'uso dei principal dell'istanza. Per un esempio, vedere https://github.com/oracle/oci-java-sdk/blob/master/bmc-examples/src/main/java/NewRegionAndRealmSupportWithoutSDKUpdate.java.

Realm oraclecloud.com

Per le aree del realm oraclecloud.com, è possibile passare nuovi nomi di area esattamente come quelli già definiti nell'enumerazione Area per la versione SDK in uso.

Nota

Per gli esempi di codice riportati di seguito, assicurarsi di fornire gli endpoint appropriati per l'area.

Se si utilizza la versione 1.2.34 o successiva dell'SDK per Java, è possibile passare il nuovo nome dell'area come stringa utilizzando uno dei metodi riportati di seguito.

  • Per impostare l'area su un client creato in precedenza, effettuare le operazioni riportate di seguito.

    client.setRegion("ca-toronto-1");
  • Per impostare un'area durante la creazione di un nuovo client:

    Identity identityClient = IdentityClient.builder()
            .region("ca-toronto-1")
            .build(provider); 
  • È inoltre possibile passare l'area nel file di configurazione. Per ulteriori informazioni, vedere SDK and CLI Configuration File.

Altri settori

Per le aree in aree diverse da oraclecloud.com, è possibile utilizzare le soluzioni seguenti per raggiungere nuove aree con versioni precedenti dell'SDK.

Per specificare l'endpoint:
AuthenticationDetailsProvider provider =
        new ConfigFileAuthenticationDetailsProvider(configurationFilePath, profile);

IdentityClient client = IdentityClient.builder()
        .endpoint("https://identity.ca-toronto-1.oraclecloud.com")
        .build(provider);
Se si esegue l'autenticazione tramite i principal dell'istanza, è possibile impostare l'endpoint e federationEndpoint tramite il processo seguente:
InstancePrincipalsAuthenticationDetailsProvider provider = InstancePrincipalsAuthenticationDetailsProvider.builder()
        .federationEndpoint("https://auth.ca-toronto-1.oraclecloud.com/v1/x509")
        .build();

IdentityClient identityClient = IdentityClient.builder()
        .endpoint("https://identity.ca-toronto-1.oraclecloud.com")
        .build(provider);

Risposte impaginate

Alcune API restituiscono set di risultati impaginati, pertanto è necessario verificare la presenza di elementi aggiuntivi e, se necessario, recuperare la pagina successiva. Puoi farlo manualmente o puoi usare un iteratore.

Recupero manuale delle pagine

Gli oggetti Risposta contengono un metodo per recuperare il token della pagina successiva. Se il token è nullo, non sono presenti altri elementi. Se non è nullo, è possibile effettuare una richiesta aggiuntiva, impostando il token sull'oggetto Request, per ottenere la pagina successiva delle risposte.

Nota

Alcune API possono restituire un token anche se non sono disponibili risultati aggiuntivi. Assicurati anche di controllare se gli articoli sono stati restituiti e fermati se non ce ne sono.

Questo esempio mostra come gestire i token di pagina restituiti dall'API di storage degli oggetti:

ObjectStorage client = ...;
 
ListBucketsRequest.Builder builder =
    ListBucketsRequest.builder().namespaceName(namespace);
String nextPageToken = null;
do {
    builder.page(nextPageToken);
    ListBucketsResponse listResponse = client.listBuckets(builder.build());
    List<Bucket> buckets = listResponse.getItems();
    // handle buckets
    nextPageToken = listResponse.getOpcNextPage();
} while (nextPageToken != null);

Utilizzo di un iteratore

Invece di utilizzare manualmente i token di pagina, è possibile utilizzare un iteratore. Ogni client di servizio espone un metodo getPaginators() che restituisce un oggetto Paginator. Questo oggetto contiene metodi per restituire oggetti di tipo Iterable. Sono supportati due approcci all'utilizzo di iterable:

  • Iteratore risposta: è possibile iterare gli oggetti Response restituiti dall'operazione di elenco. Questi sono indicati come ResponseIterators e i relativi metodi hanno il suffisso "ResponseIterator", ad esempio listUsersResponseIterator.
    Iterable<ListUsersResponse> responseIterator = identityClient.getPaginators().listUsersResponseIterator(request);
    for (ListUsersResponse response : responseIterator) {
        for (User user : response.getItems()) {
            System.out.println(user);
        }
    }
  • Iteratore record: è possibile iterare le risorse o i record elencati. Questi sono indicati come RecordIterator e i relativi metodi hanno il suffisso "RecordIterator", ad esempio listUsersRecordIterator.
    Iterable<User> recordIterator = identityClient.getPaginators().listUsersRecordIterator(request)
    for (User user : recordIterator) {
        System.out.println(user);
    }

Autenticazione lato client

Client Side Encryption consente di cifrare i dati sul lato client prima di memorizzarli localmente o utilizzarli con altri servizi Oracle Cloud Infrastructure.

Per utilizzare la cifratura lato client, è necessario creare una chiave di cifratura master (MEK) mediante il servizio Key Management. Questa operazione può essere eseguita utilizzando le operazioni CreateKey o ImportKey.

MEK viene utilizzato per generare una chiave di cifratura dati (DEK, Data Encryption Key) per cifrare ogni payload. Una copia crittografata di questo DEK (crittografato sotto il MEK) e altri pezzi di metadati sono inclusi nel payload cifrato restituito dagli SDK in modo che possano essere utilizzati per la decifrazione.

Prerequisiti di Java

I file di policy illimitati per le release precedenti sono necessari solo per gli aggiornamenti di JDK 8, 7 e 6 precedenti a 8u161, 7u171 e 6u16. Per tali versioni e versioni successive i file dei criteri sono inclusi ma non abilitati per impostazione predefinita.

Le versioni correnti del JDK non richiedono questi file di criteri. Vengono fornite qui per l'uso con le versioni precedenti del JDK. JDK 9 e versioni successive inviano i file dei criteri illimitati e li utilizzano per impostazione predefinita.

Esempi

L'esempio di codice riportato di seguito mostra come cifrare una stringa.


// String encryption example
			
final byte[] plainText = "Hello World".getBytes();
String masterKeyId = "OCID....";
Map<String, String> context = Collections.singletonMap("Example", "value");
 
OciCrypto ociCrypto = new OciCrypto();
KmsMasterKey kmsMasterKey = new KmsMasterKey(authenticationProvider, Region.US_ASHBURN_1.getRegionId(), vaultId, masterKeyId);
KmsMasterKeyProvider kmsMasterKeyProvider = new KmsMasterKeyProvider(kmsMasterKey);
 
//  Encrypt the data and embed the master key ID in the header
final OciCryptoResult encryptResult = ociCrypto.encryptData(kmsMasterKeyProvider, plainText, context);
final byte[] cipherText = encryptResult.getResult();
 
//  Decrypt the data
final OciCryptoResult decryptResult = ociCrypto.decryptData(kmsMasterKeyProvider, cipherText);

L'esempio seguente mostra come cifrare un flusso di file.


// Create Encryption file stream
FileInputStream in = new FileInputStream(srcFile);
OciCrypto ociCrypto = new OciCrypto();
KmsMasterKey kmsMasterKey = new KmsMasterKey(authenticationProvider, Region.US_ASHBURN_1.getRegionId(), vaultId, masterKeyId);
KmsMasterKeyProvider kmsMasterKeyProvider = new KmsMasterKeyProvider(kmsMasterKey);
OciCryptoInputStream encryptingStream = ociCrypto.createEncryptingStream(kmsMasterKeyProvider, in);
 
// Write the encrypted data to file
FileOutputStream out = new FileOutputStream(srcFile + ".encrypted");
IOUtils.copy(encryptingStream, out);
encryptingStream.close();
out.close();
 
// For decryption, no need to pass key info
KmsMasterKeyProvider kmsMasterKeyProvider = new KmsMasterKeyProvider(authenticationProvider);
// Create the Decryption file stream.
in = new FileInputStream(srcFile + ".encrypted");
OciCryptoInputStream decryptingStream = ociCrypto.createDecryptingStream(kmsMasterKeyProvider, in);
 
 
// Return the plaintext data
out = new FileOutputStream(srcFile + ".decrypted");
IOUtils.copy(decryptingStream, out);
decryptingStream.close();
out.close();

Gestione eccezioni

Quando si gestisce un'eccezione, è possibile ottenere ulteriori informazioni sulla richiesta HTTP che l'ha causata, ad esempio il codice di stato o il timeout. È inoltre possibile ottenere l'ID della richiesta quando si gestisce un BmcException utilizzando il metodo getOpcRequestId.

Questo esempio mostra un blocco try-catch che gestisce un BmcExceptione stampa l'ID della richiesta.

ObjectStorage client = ...;
try {
    GetBucketResponse response = client.getBucket(
	        GetBucketRequest.builder().namespaceName("myNamespace").bucketName("myBucket").build());
    String requestId = response.getOpcRequestId();
    System.out.println(requestId);
} catch (BmcException e) {
    String requestId = e.getOpcRequestId();
    System.out.println(requestId);
    e.printStackTrace();
}

Le eccezioni nell'SDK per Java sono eccezioni runtime (non selezionate), pertanto non vengono visualizzate nelle firme dei metodi. Tutte le API possono generare un BmcException.