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.
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 section relative à l'utilisation des téléchargements multipart vers le serveur 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.
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 :
- Définissez la variable d'environnement
OCI_SDK_DEFAULT_RETRY_ENABLED
surfalse
pour désactiver globalement les nouvelles tentatives par défaut. -
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);
-
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é au 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
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 fin de contrat
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.
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.
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 :
- Définissez la variable d'environnement
OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED
surfalse
. - 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
La valeur définie au niveau du client est prioritaire sur la valeur définie au niveau de l'application.
Activer des modèles d'adresse propres au domaine au niveau de l'application :
OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED
sur true
. La valeur booléenne n'est pas sensible à la casse.
Activer 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é :
Pour le kit SDK OCI pour Java :
ObjectStorage client = ObjectStorageClient.builder().build(provider);
client.useRealmSpecificEndpointTemplate(true);
Pour obtenir un exemple complet, reportez-vous à UseRealmSpecificEndpointsExample sur Github.
Pour le 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
.
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.
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.
AuthenticationDetailsProvider provider =
new ConfigFileAuthenticationDetailsProvider(configurationFilePath, profile);
IdentityClient client = IdentityClient.builder()
.endpoint("https://identity.ca-toronto-1.oraclecloud.com")
.build(provider);
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.
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 ont 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
.