Concepts

Cette rubrique explique certains des concepts clés liés à l'utilisation du kit SDK Oracle Cloud Infrastructure pour Java.

Cette rubrique explique certains des concepts clés liés à l'utilisation du kit SDK Oracle Cloud Infrastructure pour Java.

Appels synchrones

Pour effectuer des appels synchrones, créez une instance du client synchrone. Le modèle général relatif aux clients synchrones est le suivant : pour un service nommé Example, il existe une interface nommée ExampleService et l'implémentation du client synchrone est nommée ExampleServiceClient. Voici un exemple de création d'un client Object Storage :

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

Les appels synchrones sont bloqués jusqu'à ce que la réponse soit disponible. Toutes les API de kit SDK renvoient un objet de réponse (que l'API renvoie du contenu ou non). L'objet de réponse contient généralement au moins un ID de demande que vous pouvez utiliser lorsque vous contactez le support technique Oracle en vue d'obtenir de l'aide sur une demande précise.

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

Appels asynchrones

Pour effectuer des appels asynchrones, créez une instance du client asynchrone. Le modèle général relatif aux clients asynchrones est le suivant : pour un service nommé Example, il existe une interface nommée ExampleServiceAsync et l'implémentation du client asynchrone est nommée ExampleServiceAsyncClient. Voici un exemple de création d'un client Object Storage :

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

Les appels asynchrones sont renvoyés immédiatement. Vous devez fournir un AsyncHandler qui sera appelé une fois que l'appel sera terminé, avec ou sans succès :

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

Interrogation avec des processus en attente

Le kit SDK inclut des processus en attente permettant au code d'attendre jusqu'à ce qu'une ressource spécifique atteigne un état souhaité. Un processus en attente peut être appelé de façon bloquante ou non bloquante (avec callback asynchrone) et attend que l'état souhaité soit atteint ou que le délai d'expiration soit dépassé. Les processus en attente extraient la logique d'interrogation, que vous devriez sinon écrire, dans un appel de méthode unique facile à utiliser.

Les processus en attente sont obtenus via le client de service (client.getWaiters()). A la fois Get<Resource>Request et l'état de cycle de vie souhaité sont transmis à la méthode waiters.for<Resource>. Par exemple :

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

Chaque méthode waiters.for<Resource> a deux versions :

  • Une version utilise les valeurs d'interrogation par défaut. Par exemple :

    waiters.forInstance(GetInstanceRequest, LifecycleState)
  • L'autre version offre un contrôle total sur la durée d'attente et sur l'intervalle de temps entre les tentatives d'interrogation. Par exemple :

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

Modèle de thread

Les threads d'un client sont sécurisés lorsque celui-ci est initialisé. Une fois son adresse définie, vous pouvez utiliser un client en toute sécurité dans plusieurs threads et appeler des méthodes simultanément sur celui-ci.

Vous pouvez réutiliser un client dans plusieurs demandes, sur des threads simultanés ou dans un même thread. A moins que les ressources de l'environnement ne soient limitées, vous devez fermer le client juste avant qu'il ne soit hors de portée.

Remarque

Cette garantie ne s'applique qu'à l'implémentation JAX-RS par défaut, Jersey. Lorsque vous utilisez une autre implémentation, vous devez gérer vous-même la sécurité des threads. Pour plus d'informations, reportez-vous à Configuration du kit SDK.

Téléchargement d'objets volumineux

Le service Object Storage prend en charge les téléchargements multipart pour simplifier les téléchargements d'objets volumineux en les divisant en plusieurs parties. Le kit SDK pour Java prend en charge les opérations de téléchargement multipart brutes pour les cas d'emploi avancés, ainsi qu'une classe de téléchargement de niveau supérieur utilisant les API de téléchargement multipart. La rubrique relative à l'utilisation des téléchargements multipart fournit des liens vers les API utilisées pour les opérations de téléchargement multipart. Les téléchargements multipart de niveau supérieur sont implémentés à l'aide d'UploadManager, qui fractionne un objet volumineux en plusieurs parties, télécharge les parties en parallèle, puis recombine et valide les parties en un seul objet dans le stockage.

L'exemple UploadObject montre comment utiliser UploadManager pour fractionner automatiquement un objet en plusieurs parties à télécharger afin de simplifier l'interaction avec le service Object Storage.

Nouvelles tentatives

A partir de la version 2.10.0, le kit SDK pour Java est configuré par défaut pour réessayer certaines de ses opérations en échec. Le kit SDK vous permet de spécifier la stratégie à utiliser pour la gestion des tentatives, y compris le nombre de tentatives, la condition dans laquelle le kit SDK doit retenter une opération et le moment auquel arrêter les tentatives. Vous pouvez définir ces paramètres au niveau du client et au niveau de la demande individuelle.

Afin de déterminer les opérations de service pour lesquelles les nouvelles tentatives sont activées par défaut, reportez-vous à la description des opérations de service dans le kit SDK.

Remarque

Les nouvelles tentatives ne sont actuellement pas prises en charge pour les clients asynchrones.

Par défaut, le kit SDK tente à nouveau les opérations sur les codes de statut de réponse HTTP 409 (avec code d'erreur IncorrectState), 429, 500, 502, 503, 504, les erreurs de délai d'expiration (comme les délais d'expiration de connexion HTTP et de lecture), les erreurs de connexion de demande, les exceptions de demande et les exceptions de disjoncteur.

La configuration par défaut la plus récente concernant les nouvelles tentatives et la liste des erreurs pouvant faire l'objet d'une nouvelle tentative sont consultables sur GitHub.

Désactivation des nouvelles tentatives par défaut

Pour renoncer à la fonctionnalité des nouvelles tentatives par défaut, vous pouvez effectuer l'une des opérations suivantes :

  1. Définissez la variable d'environnement OCI_SDK_DEFAULT_RETRY_ENABLED sur false pour désactiver globalement les nouvelles tentatives par défaut.
  2. Remplacez les nouvelles tentatives par défaut pour une instance client particulière. Cet exemple présente le remplacement des nouvelles tentatives par défaut pour objectStorageClient :

    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder()
                    .retryConfiguration(RetryConfiguration.builder().terminationStrategy(new MaxAttemptsTerminationStrategy(1))
                            .build())
                    .build();
    ObjectStorage objectStorageClient = ObjectStorageClient.builder().configuration(clientConfiguration).build(provider);
    
  3. Remplacez les nouvelles tentatives par défaut pour une instance de demande particulière. Cet exemple présente le remplacement des nouvelles tentatives pour putObjectRequest :

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

Priorité sur le comportement lié aux nouvelles tentatives

  • Toute configuration des nouvelles tentatives définie explicitement au niveau de la demande remplace la configuration des nouvelles tentatives au niveau du client, ou la configuration des nouvelles tentatives au niveau global et le remplacement via la variable d'environnement pour cette instance de demande spécifique.
  • Toute configuration des nouvelles tentatives définie explicitement au niveau du client remplace la configuration globale des nouvelles tentatives et le remplacement au niveau de la variable d'environnement pour cette instance client particulière.

Stratégies concernant les nouvelles tentatives

Vous pouvez spécifier la stratégie à utiliser pour la gestion des tentatives, y compris le nombre de tentatives, la condition dans laquelle le kit SDK doit retenter une opération et le moment auquel arrêter les tentatives. Vous pouvez définir ces paramètres au niveau du client et au niveau de la demande individuelle.
Remarque

La configuration par défaut la plus récente concernant les nouvelles tentatives et la liste des erreurs pouvant faire l'objet d'une nouvelle tentative sont consultables sur GitHub.

Stratégie de délai

Le paramètre delayStrategy détermine la durée d'attente entre chaque appel de tentative. Deux options sont disponibles pour ce paramètre :

  • FixedTimeDelayStrategy (millisecondes) : chaque tentative est retardée d'un nombre de millisecondes spécifié.
  • ExponentialBackoffDelayStrategy (millisecondes) : le délai pour les appels de tentative augmente selon un facteur exponentiel de 2 jusqu'à atteindre le délai maximal défini (en millisecondes), avec une valeur de base d'une milliseconde.

La stratégie de délai par défaut est définie sur ExponentialBackoffDelayStrategy avec une valeur de gigue comprise entre 0 et 1 000 millisecondes, et un temps d'attente maximal entre les appels de 30 secondes.

Condition de nouvelle tentative

retryCondition définit une fonction avec un argument d'erreur renvoyant une valeur booléenne qui indique si une nouvelle tentative est à effectuer. L'opération est retentée si cette fonction renvoie true.

Stratégie de terminaison

Le paramètre terminationStrategy détermine quand mettre fin aux tentatives. Ce paramètre prend en charge les options suivantes :

  • MaxTimeTerminationStrategy (millisecondes) : définit la durée totale en millisecondes pendant laquelle les nouvelles tentatives sont effectuées.
  • MaxAttemptsTerminationStrategy (tentatives) : définit le nombre total de nouvelles tentatives.

La stratégie de terminaison par défaut pour les kits SDK OCI est MaxAttemptsTerminationStrategy définie sur 8.

Exemples de nouvelle tentative

Java

Cet exemple montre comment configurer et utiliser les nouvelles tentatives avec le kit SDK pour 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());
    }
}

Disjoncteurs

A partir de la version 2.10.0, le kit SDK pour Java prend en charge par défaut les disjoncteurs pour les clients de service qui ont activé les disjoncteurs de kit SDK par défaut. Les disjoncteurs empêchent le client de submerger le service en bloquant l'envoi des demandes au service une fois qu'un certain seuil d'échec est atteint.

Remarque

Les disjoncteurs par défaut ne sont actuellement pas pris en charge pour les clients asynchrones.

Pour les disjoncteurs par défaut, toutes les erreurs pouvant faire l'objet d'une nouvelle tentative sont traitées comme des échecs. Afin de déterminer les clients de service pour lesquels les disjoncteurs sont activés, reportez-vous à la description des clients de service dans le kit SDK.

Remarque

Vous pouvez visualiser la configuration de disjoncteur par défaut sur GitHub.

Configuration de disjoncteur

Les paramètres suivants définissent un disjoncteur :

  • Seuil de taux d'échec : l'état du disjoncteur passe de CLOSED à OPEN lorsque le taux d'échec est supérieur ou égal à ce seuil. Par exemple, lorsque plus de 50 % des appels enregistrés ont échoué, le disjoncteur s'ouvre.
  • Délai d'expiration de réinitialisation : délai après lequel un disjoncteur ouvert tente une demande, le cas échéant.
  • Exceptions d'échec : liste des exceptions considérées comme des échecs dans le circuit.
  • Nombre minimal d'appels/Seuil de volume : nombre minimal d'appels requis (par période glissante) pour que le disjoncteur puisse calculer le taux d'erreur.

Configuration de disjoncteur par défaut

Voici la configuration de disjoncteur par défaut :

  • Seuil de taux d'échec : 80 %. Lorsque 80 % des demandes calculées sur une fenêtre de temps de 120 secondes échouent, le circuit passe de fermé à ouvert.
  • Nombre minimal d'appels/Seuil de volume : 10, pour la fenêtre de temps définie ci-dessus de 120 secondes.
  • Délai d'expiration de réinitialisation : le disjoncteur attend 30 secondes avant de passer à l'état halfOpen et de retenter l'action.
  • Exceptions d'échec : les échecs du circuit sont enregistrés uniquement pour les exceptions non persistantes ou avec possibilité de nouvelle tentative. Les codes de réponse HTTP 409 (avec IncorrectState), 429, 500, 502, 503 et 504, les délais d'expiration de demande HTTP et autres, les erreurs de connexion de demande et les exceptions sont tous traités comme des échecs qui déclenchent un disjoncteur.

Désactivation du disjoncteur par défaut

Pour renoncer à la fonctionnalité du disjoncteur par défaut, vous pouvez effectuer l'une des opérations suivantes :

  1. Définissez la variable d'environnement OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED sur false.
  2. Modifiez la configuration de disjoncteur par défaut pour une instance client. L'exemple suivant présente cette opération avec une instance IdentityClient :
    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder().circuitBreakerConfiguration(CircuitBreakerUtils.getNoCircuitBreakerConfiguration()).build();
     
            // Create Clients using above ClientConfiguration
            IdentityClient identityClient = new IdentityClient(provider, clientConfiguration);

Priorité sur le comportement lié aux disjoncteurs

Toute configuration de disjoncteur définie explicitement au niveau du client remplace la configuration globale de disjoncteur par défaut et le remplacement au niveau de l'environnement pour ce client.

Pour plus d'informations sur les disjoncteurs et sur la configuration de disjoncteur par défaut, reportez-vous à cet exemple sur GitHub.

Demandes brutes

Les demandes brutes sont utiles, et dans certains cas, nécessaires. Les cas d'emploi standard sont les suivants : lorsque vous utilisez votre propre client HTTP, lorsque vous effectuez une demande authentifiée par OCI à une autre adresse et lorsque vous effectuez une demande à une API OCI qui n'est pas prise en charge actuellement dans le kit SDK. Le kit SDK pour Java affiche la classe DefaultRequestSigner que vous pouvez utiliser afin de créer une instance RequestSigner pour les demandes non standard.

L'exemple de demande brute sur GitHub indique comment :

  • créer un fournisseur d'authentification et un signataire de demande,
  • effectuer l'intégration à un client HTTP (Jersey dans cet exemple) pour authentifier les demandes.

Définition des adresses

Les adresses de service peuvent être définies de trois façons.

  • Appel de setEndpoint() sur l'instance de service. Vous pouvez ainsi spécifier un nom d'hôte complet (par exemple, https://www.example.com).
  • Appel de setRegion() sur l'instance de service. Cette opération sélectionne le nom d'hôte approprié pour le service de la région donnée. Toutefois, si le service n'est pas pris en charge dans la région définie, le kit SDK pour Java renvoie une erreur.
  • Transmission de la région dans le fichier de configuration. Pour plus d'informations, reportez-vous à Fichier de configuration du kit SDK et de l'interface de ligne de commande.

Une instance de service ne peut pas être utilisée pour communiquer avec différentes régions. Si vous devez effectuer des demandes dans différentes régions, créez plusieurs instances de service.

Adresses dédiées

Les adresses dédiées sont les modèles d'adresse définis par le service pour un domaine spécifique au niveau du client. Le kit SDK Java OCI vous permet d'activer l'utilisation de la fonctionnalité de modèles d'adresse propres au domaine au niveau de l'application et au niveau du client. Cette fonctionnalité est désactivée par défaut.
Remarque

La valeur définie au niveau du client est prioritaire sur la valeur définie au niveau de l'application.

Activation des modèles d'adresse propres au domaine au niveau de l'application :

Pour activer la fonctionnalité de modèles d'adresse propres au domaine au niveau de l'application, définissez la variable d'environnement OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED sur true.
Remarque

La valeur booléenne n'est pas sensible à la casse.

Activation des modèles d'adresse propres au domaine au niveau de l'application :

Pour activer la fonctionnalité de modèles d'adresse propres au domaine au niveau du client, définissez l'indicateur dans le code comme indiqué :

Kit SDK OCI pour Java :

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

Pour obtenir un exemple complet, reportez-vous au fichier UseRealmSpecificEndpointsExample on Github.

Kit SDK OCI hérité pour Java :

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

Pour obtenir un exemple complet, reportez-vous à UseRealmSpecificEndpointsExample sur GitHub.

Enumérations et compatibilité descendante

Si vous avez une logique conditionnelle basée sur une énumération, assurez-vous que le code gère le cas UnknownEnumValue pour garantir la compatibilité descendante. Certains champs de réponse sont de type énumération mais, à l'avenir, les services individuels pourront renvoyer des valeurs non couvertes par les énumérations existantes pour ce champ. Pour répondre à cette possibilité, chaque champ de réponse de type énumération a une valeur supplémentaire nommée UnknownEnumValue. Lorsqu'un service renvoie une valeur non reconnue par votre version du kit SDK, le champ de réponse est défini sur cette valeur.

Prise en charge d'une nouvelle région

Si vous utilisez une version du kit SDK publiée avant l'annonce d'une nouvelle région, vous pouvez utiliser une solution de contournement pour l'atteindre.

Une région est une zone géographique localisée. Pour plus d'informations sur les régions et leur identification, reportez-vous à Régions et domaines de disponibilité.

Un domaine est un ensemble de régions qui partagent des entités. Vous pouvez identifier votre domaine en observant le nom de domaine à la fin de l'adresse réseau. Par exemple, le domaine de xyz.abc.123.oraclecloud.com est oraclecloud.com.

Vous devez tout d'abord appeler Region.register pour inscrire la nouvelle région, puis définir la région à l'aide du fichier de configuration ou en appelant la méthode setRegion.

Remarque

Une fois qu'une région est inscrite, l'adresse de fédération n'est plus requise lors de l'utilisation de principaux d'instance. Pour obtenir un exemple, reportez-vous à https://github.com/oracle/oci-java-sdk/blob/master/bmc-examples/src/main/java/NewRegionAndRealmSupportWithoutSDKUpdate.java.

Domaine oraclecloud.com

Pour les régions du domaine oraclecloud.com, vous pouvez transmettre les noms des nouvelles régions comme vous transmettriez les noms déjà définis dans l'énumération Région de votre version du kit SDK.

Remarque

Dans les exemples de code suivants, veillez à indiquer les adresses appropriées pour votre région.

Si vous utilisez la version 1.2.34 ou une version ultérieure du kit SDK pour Java, vous pouvez transmettre le nom de la nouvelle région en tant que chaîne à l'aide de l'une des méthodes suivantes :

  • Pour définir la région sur un client créé précédemment, procédez comme suit :

    client.setRegion("ca-toronto-1");
  • Pour définir une région lors de la création d'un client, procédez comme suit :

    Identity identityClient = IdentityClient.builder()
            .region("ca-toronto-1")
            .build(provider); 
  • Vous pouvez également transmettre la région dans le fichier de configuration. Pour plus d'informations, reportez-vous à Fichier de configuration du kit SDK et de l'interface de ligne de commande.

Autres domaines

Pour les régions dans des domaines autres que oraclecloud.com, vous pouvez utiliser les solutions de contournement suivantes afin d'atteindre les nouvelles régions disposant de versions antérieures du kit SDK.

Pour indiquer l'adresse, procédez comme suit :
AuthenticationDetailsProvider provider =
        new ConfigFileAuthenticationDetailsProvider(configurationFilePath, profile);

IdentityClient client = IdentityClient.builder()
        .endpoint("https://identity.ca-toronto-1.oraclecloud.com")
        .build(provider);
Si vous effectuez l'authentification par le biais de principaux d'instance, vous pouvez définir l'adresse et federationEndpoint via le processus suivant :
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);

Réponses paginées

Certaines API renvoient des ensembles de résultats paginés. Vous devez donc rechercher si des éléments supplémentaires existent et, si nécessaire, extraire la page suivante. Vous pouvez procéder manuellement ou utiliser un itérateur.

Extraction manuelle des pages

Les objets de réponse contiennent une méthode permettant d'extraire le jeton de page suivante. Si le jeton est NULL, il n'existe aucun autre élément. S'il n'est pas NULL, vous pouvez effectuer une demande supplémentaire en définissant le jeton sur l'objet Request afin d'obtenir la page de réponses suivante.

Remarque

Certaines API peuvent renvoyer un jeton même en l'absence de résultats supplémentaires. Vérifiez également si des éléments ont été renvoyés et arrêtez le processus si ce n'est pas le cas.

Cet exemple montre comment gérer les jetons de page renvoyés par l'API Object Storage :

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

Utilisation d'un itérateur

Au lieu de gérer manuellement les jetons de page, vous pouvez utiliser un itérateur. Chaque client de service affiche une méthode getPaginators() qui renvoie un objet Paginator. Cet objet contient des méthodes permettant de renvoyer des objets de type Iterable. Nous prenons en charge deux approches d'utilisation d'Iterable :

  • Itérateur de réponse : vous pouvez effectuer une itération sur les objets Response renvoyés par l'opération de liste. Ces itérateurs sont appelés ResponseIterators et leurs méthodes ont le suffixe "ResponseIterator". Par exemple, listUsersResponseIterator.
    Iterable<ListUsersResponse> responseIterator = identityClient.getPaginators().listUsersResponseIterator(request);
    for (ListUsersResponse response : responseIterator) {
        for (User user : response.getItems()) {
            System.out.println(user);
        }
    }
  • Itérateur d'enregistrement : vous pouvez effectuer une itération sur les ressources/enregistrements répertoriés. Ces itérateurs sont appelés RecordIterator et leurs méthodes présentent le suffixe "RecordIterator". Par exemple, listUsersRecordIterator.
    Iterable<User> recordIterator = identityClient.getPaginators().listUsersRecordIterator(request)
    for (User user : recordIterator) {
        System.out.println(user);
    }

Cryptage côté client

Le cryptage côté client vous permet de crypter les données côté client avant de les stocker en local ou de les utiliser avec d'autres services Oracle Cloud Infrastructure.

Pour utiliser le cryptage côté client, vous devez créer une clé de cryptage maître (MEK) à l'aide du service Key Management. Pour ce faire, vous pouvez utiliser l'opération CreateKey ou ImportKey.

La clé MEK permet de générer une clé de cryptage de données (DEK) utilisée pour crypter chaque charge utile. Une copie cryptée de cette clé DEK (sous la clé MEK) et d'autres métadonnées sont incluses dans la charge utile cryptée renvoyée par les kits SDK en vue d'être utilisées pour le décryptage.

Prérequis pour Java

Les fichiers de stratégie illimités pour les versions antérieures sont uniquement requis pour les mises à jour de JDK 8, 7 et 6 antérieures à 8u161, 7u171 et 6u16. A partir de ces versions, les fichiers de stratégie sont inclus, mais ne sont pas activés par défaut.

Les fichiers de stratégie sont inutiles pour les versions en cours de JDK. Ils sont fournis ici à des fins d'utilisation avec les anciennes versions de JDK. JDK version 9 ou ultérieure est fourni avec les fichiers de stratégie illimités et les utilise par défaut.

Exemples

L'exemple de code suivant montre comment crypter une chaîne :


// 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'exemple suivant montre comment crypter un flux de fichier :


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

Gestion des exceptions

Lors de la gestion d'une exception, vous pouvez obtenir plus d'informations sur la demande HTTP qui l'a générée, comme le code de statut ou le délai d'expiration. Vous pouvez également obtenir l'ID de la demande lors de la gestion d'une exception BmcException à l'aide de la méthode getOpcRequestId.

Cet exemple présente un bloc try-catch qui gère une exception BmcException et imprime l'ID de la demande.

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

Les exceptions dans le kit SDK pour Java sont des exceptions d'exécution (non vérifiées). Elles n'apparaissent donc pas dans les signatures de méthode. Toutes les API peuvent générer une exception BmcException.