Conceitos

Este tópico explica alguns dos principais conceitos para usar o Oracle Cloud Infrastructure SDK for Java.

Este tópico explica alguns dos principais conceitos para usar o Oracle Cloud Infrastructure SDK for Java.

Chamadas Síncronas

Para fazer chamadas síncronas, crie uma instância do cliente síncrono. O padrão geral para clientes síncronos é que para um serviço chamado Example haverá uma interface ExampleService, e a implementação do cliente síncrono será denominada ExampleServiceClient. Este é um exemplo de criação de um cliente do 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);

As chamadas síncronas serão bloqueadas até que a resposta esteja disponível. Todas as APIs SDK retornam um objeto de resposta (independentemente de a API enviar ou não conteúdo). O objeto de resposta normalmente contém pelo menos um ID de solicitação que você pode usar ao entrar em contato com o suporte da Oracle para obter ajuda sobre uma solicitação específica.

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

Chamadas Assíncronas

Para fazer chamadas assíncronas, crie uma instância do cliente assíncrono. O padrão geral para clientes assíncronos é que para um serviço chamado Example haverá uma interface ExampleServiceAsync, e a implementação do cliente assíncrono será denominada ExampleServiceAsyncClient. Este é um exemplo de criação de um cliente do 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);

As chamadas assíncronas são retornadas imediatamente. Você precisa fornecer um AsyncHandler que será invocado após a chamada ser concluída com ou sem sucesso:

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

Sondagem com Waiters

O SDK oferece waiters que permitem ao seu código aguardar até que um recurso específico atinja um estado desejado. Um waiter pode ser chamado com ou sem bloqueio (utilizando callback assíncrono) e aguarda até que o estado desejado seja atingido ou um timeout seja excedido. Os waiters já incorporam a lógica de sondagem que você teria de criar como uma chamada de método único fácil de usar.

Os waiters são obtidos por meio do cliente de serviço (client.getWaiters()). Get<Resource>Request e o estado do ciclo de vida desejado são especificados para o método waiters.for<Resource>. Por exemplo:

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

Cada método waiters.for<Resource> tem duas versões:

  • Uma versão usa os valores de sondagem padrão. Por exemplo:

    waiters.forInstance(GetInstanceRequest, LifecycleState)
  • A outra versão oferece controle total sobre o tempo de espera e o tempo entre as tentativas de sondagem. Por exemplo:

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

Modelo de Threading

Um cliente torna-se thread-safe quando é inicializado. Após definir o ponto final, você pode usar com segurança um cliente em vários threads e com vários métodos de chamada concorrente.

Você pode reutilizar um cliente em várias solicitações, em threads concorrentes ou em um único thread. A menos que os recursos do ambiente sejam restritos, você só deverá fechar o cliente imediatamente se ele estiver prestes a sair do escopo.

Observação

Essa garantia se aplica somente à implementação JAX-RS padrão, Jersey. Ao usar uma implementação alternativa, você deverá gerenciar a segurança do thread. Para obter mais informações, consulte Configurando o SDK

Upload de Objetos Grandes

O serviço Object Storage suporta uploads em várias partes para facilitar a divisão de objetos grandes em partes. O SDK para Java suporta operações de upload em várias partes brutas para casos de uso avançado e aceita uma classe de upload de nível mais alto que usa APIs de upload em várias partes. A seção Usando Uploads em várias partes fornece links para as APIs usadas para operações de upload em várias partes. Os uploads em várias partes de nível mais alto são implementados com o UploadManager, que: dividirá um objeto grande em partes para você, fará o upload das partes em paralelo e recalculará e confirmará as partes como um único objeto no armazenamento.

O exemplo UploadObject mostra como usar o UploadManager para dividir automaticamente um objeto em partes para que o upload simplifique a interação com o serviço Object Storage.

Repetições

A partir da versão 2.10.0, o SDK para Java é configurado por padrão para repetir determinadas operações do SDK que falham. O SDK permite especificar a estratégia a ser usada de como as repetições são tratadas, incluindo o número de repetições, a condição sob a qual o SDK deve repetir uma operação e quando interromper a repetição de uma operação. Você pode definir esses parâmetros no nível de cliente e no nível de solicitação individual.

Para determinar quais operações de serviço têm repetições ativadas por padrão, consulte a descrição das operações de serviço no SDK.

Observação

No momento, repetições não são suportadas para clientes assíncronos

Por padrão, o SDK repetirá operações com códigos de status de resposta HTTP 409 (com um código de erro IncorrectState), 429, 500, 502, 503, 504, erros de timeout (como timeouts de conexão HTTP e de leitura), erros de conexão de solicitação, exceções de solicitação e exceções de disjuntor.

A configuração de repetição padrão mais atual e a lista de erros que podem ser repetidos podem ser exibidas no Github.

Desativando Repetições Padrão

Para recusar o recurso de repetições padrão, você pode fazer o seguinte:

  1. Defina a variável de ambiente OCI_SDK_DEFAULT_RETRY_ENABLED como false para desativar repetições padrão globalmente
  2. Substitua as repetições padrão de uma instância cliente específica. Este exemplo mostra como substituir as repetições padrão de objectStorageClient:

    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder()
                    .retryConfiguration(RetryConfiguration.builder().terminationStrategy(new MaxAttemptsTerminationStrategy(1))
                            .build())
                    .build();
    ObjectStorage objectStorageClient = ObjectStorageClient.builder().configuration(clientConfiguration).build(provider);
    
  3. Substitua as repetições padrão de uma instância de solicitação específica. Este exemplo mostra como substituir repetições de putObjectRequest:

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

Repetir Precedência de Comportamento

  • Qualquer configuração de repetição definida explicitamente no nível da solicitação substituirá a configuração de repetição no nível do cliente ou a configuração de repetição no nível global e a substituição da variável de ambiente, para essa instância de solicitação específica.
  • Qualquer configuração de repetição definida explicitamente no nível do cliente substituirá a configuração de repetição global e a substituição no nível da variável de ambiente, para essa instância cliente específica.

Estratégias de Repetição

Você pode especificar a estratégia a ser usada de como as repetições são tratadas, incluindo o número de repetições, a condição sob a qual o SDK deve repetir uma operação e quando interromper a repetição de uma operação. Você pode definir esses parâmetros no nível de cliente e no nível de solicitação individual.
Observação

A configuração de repetição padrão mais atual e a lista de erros que podem ser repetidos podem ser exibidas no Github.

Estratégia de Atraso

O parâmetro delayStrategy determina quanto tempo esperar entre cada chamada de repetição. Há duas opções para esse parâmetro:

  • FixedTimeDelayStrategy (milliseconds) - Cada repetição é atrasada em um número especificado de milissegundos.
  • ExponentialBackoffDelayStrategy (milliseconds) - O tempo de atraso para chamadas de repetição subsequentes aumenta em um fator exponencial de 2 até atingir o atraso máximo definido (em milissegundos), com um valor base de um milissegundo.

A estratégia de atraso padrão é definida como ExponentialBackoffDelayStrategy com um valor jitter entre 0 e 1.000 milissegundos e um tempo máximo de espera entre chamadas de 30 segundos.

Condição de Repetição

retryCondition define uma função com argumento de erro que retorna um booliano que indica se deve ser repetido ou não. A operação será repetida se essa função retornar true.

Estratégia de Encerramento

O parâmetro terminationStrategy define quando encerrar as tentativas de repetição. Este parâmetro suporta as seguintes opções:

  • MaxTimeTerminationStrategy (milliseconds) - Define a duração total em milissegundos para a tentativa de repetição.
  • MaxAttemptsTerminationStrategy (attempts) - Define o número total de tentativas de repetição.

A estratégia de encerramento padrão para SDKs do OCI é uma MaxAttemptsTerminationStrategy de 8.

Exemplos de Repetição

Java

Este exemplo mostra como configurar e usar repetições com o SDK para 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());
    }
}

Disjuntores

A partir da versão 2.10.0, o SDK para Java fornece suporte padrão para disjuntores para clientes de serviço que ativaram disjuntores SDK padrão. Os disjuntores ajudam a impedir que o cliente sobrecarregue o serviço, bloqueando as solicitações e impedindo o envio ao serviço após um determinado limite de falha ser atingido.

Observação

No momento, os disjuntores padrão não são suportados para clientes assíncronos.

Para disjuntores padrão, todos os erros que podem ser repetidos serão tratados como falhas para os disjuntores. Para determinar quais clientes de serviço têm disjuntores ativados, consulte a descrição do cliente de serviço no SDK.

Observação

A configuração de disjuntor padrão pode ser exibida no Github.

Configuração do Disjuntor

Os seguintes parâmetros definem um disjuntor:

  • Limite de Taxa de Falha - o estado do disjuntor muda de CLOSED para OPEN quando a taxa de falha é igual ou maior que esse limite. Por exemplo, quando mais de 50% das chamadas registradas falharem, o disjuntor será aberto.
  • Redefinir Timeout - o timeout após o qual um disjuntor aberto tentará uma solicitação se uma for feita
  • Exceções de Falha - a lista de exceções que serão consideradas falhas para o circuito
  • Número mínimo de chamadas/Limite de volume - o número mínimo de chamadas necessárias (por período de janela deslizante) para que o disjuntor possa calcular a taxa de erro

Configuração do Disjuntor Padrão

Veja a seguir a configuração do disjuntor padrão:

  • Limite de Taxa de Falha: 80%. Quando 80% das solicitações calculadas para uma janela de tempo de 120 segundos falharem, o circuito passará de fechado para aberto.
  • Número mínimo de chamadas/limite de volume: 10, para a janela de tempo de 120 segundos definida acima.
  • Redefinir Timeout: O disjuntor aguardará 30 segundos antes da definição com o estado halfOpen e da tentativa da ação novamente.
  • Exceções de Falha: As falhas do circuito só serão registradas para exceções repetíveis ou temporárias. Os códigos de resposta HTTP 409 (com um IncorrectState), 429, 500, 502, 503 e 504, solicitação HTTP e outros timeouts, erros de conexão de solicitação e exceções são tratados como falhas que acionarão um disjuntor.

Desativando o Disjuntor Padrão

Para optar por não utilizar o recurso de disjuntor padrão, você pode executar um dos seguintes procedimentos:

  1. Defina a variável de ambiente OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED como false.
  2. Altere a configuração do disjuntor padrão para uma instância cliente. O seguinte exemplo mostra como fazer isso com uma instância IdentityClient:
    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder().circuitBreakerConfiguration(CircuitBreakerUtils.getNoCircuitBreakerConfiguration()).build();
     
            // Create Clients using above ClientConfiguration
            IdentityClient identityClient = new IdentityClient(provider, clientConfiguration);

Precedência de Comportamento do Disjuntor

Qualquer configuração de disjuntor definida explicitamente no nível do cliente substituirá a configuração global do disjuntor padrão e a substituição no nível do ambiente desse cliente.

Para obter informações adicionais sobre disjuntores e a configuração do disjuntor padrão, consulte este exemplo no Github.

Solicitações Brutas

As solicitações brutas são úteis e, em alguns casos, necessárias. Os casos de uso típicos são: para usar o seu próprio cliente HTTP, fazer uma solicitação autenticada pelo OCI para um ponto final alternativo e fazer uma solicitação para uma API do OCI não suportada atualmente no SDK. O SDK para Java expõe a classe DefaultRequestSigner que você pode usar para criar uma instância RequestSigner para solicitações não padrão.

O exemplo Solicitação Bruta no GitHub mostra como:

  • criar um provedor de autenticação e o signatário da solicitação
  • integrar-se com um cliente HTTP (Jersey neste exemplo) para autenticar solicitações

Definindo os Pontos Finais

Os pontos finais de serviço podem ser definidos de três maneiras.

  • Chamar setEndpoint() na instância de serviço. Isso permite especificar um nome de host completo (por exemplo, https://www.example.com).
  • Chamar o setRegion() na instância do serviço. Isso seleciona o nome do host apropriado para o serviço na região em questão. No entanto, se o serviço não for suportado na região definida, o SDK para Java retornará um erro.
  • Especificar a região no arquivo de configuração. Para obter mais informações, consulte Arquivo de Configuração da CLI e do SDK.

Observe que uma instância de serviço não pode ser usada para comunicação com regiões distintas. Se você precisar fazer solicitações para regiões distintas, crie várias instâncias de serviço.

Pontos Finais Dedicados

Pontos finais dedicados são os modelos de ponto final definidos pelo serviço para um realm específico no nível do cliente. O OCI Java SDK permite ativar o uso do recurso de modelos de ponto final específicos do realm no nível do aplicativo e no nível do cliente. Esse recurso é desativado por padrão.
Observação

O conjunto de valores no nível do cliente tem precedência sobre o valor definido no nível do aplicativo.

Ativando modelos de ponto final específicos do realm no nível do aplicativo:

Para ativar o recurso de modelos de ponto final específicos do realm no nível do aplicativo, defina a variável de ambiente OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED como true.
Observação

O valor booliano não distingue maiúsculas de minúsculas.

Ativando modelos de ponto final específicos do realm no nível do aplicativo:

Para ativar o recurso de modelos de ponto final específicos do realm no nível do cliente, defina o flag no código conforme mostrado:

Para o OCI SDK for Java:

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

Para obter um exemplo completo, consulte UseRealmSpecificEndpointsExample no Github.

Para o OCI SDK para Java legado:

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

Para obter um exemplo completo, consulte UseRealmSpecificEndpointsExample em GitHub.

Compatibilidade Futura e enumerações

Se você tiver uma lógica condicional baseada em enumeração, certifique-se de que o seu código seja capaz de lidar com o caso UnknownEnumValue para garantir uma compatibilidade futura. Alguns campos de resposta são do tipo enum. No entanto, no futuro, os serviços individuais podem retornar valores não cobertos pelas enumerações existentes para esse campo. Para abranger essa possibilidade, todos os campos de resposta do tipo enum têm um valor adicional chamado UnknownEnumValue. Se um serviço retornar um valor que não seja reconhecido pela sua versão do SDK, o campo de resposta será definido para esse valor.

Suporte a uma Nova Região

Se você estiver usando uma versão do SDK liberada antes do anúncio de uma nova região, poderá usar uma solução alternativa para acessá-la.

Uma região é uma área geográfica localizada. Para obter mais informações sobre regiões e como identificá-las, consulte Regiões e Domínios de Disponibilidade.

Um realm é um conjunto de regiões que compartilham entidades. Você pode identificar o seu realm examinando o nome do domínio no final do endereço da rede. Por exemplo, o realm para xyz.abc.123.oraclecloud.com é oraclecloud.com.

Primeiro, chame Region.register para registrar a nova região e, em seguida, você pode definir a região usando o arquivo de configuração ou chamando o método setRegion.

Observação

Quando uma região é registrada, o ponto final da federação não é mais necessário durante a utilização de 'instance principals'. Para obter um exemplo, consulte https://github.com/oracle/oci-java-sdk/blob/master/bmc-examples/src/main/java/NewRegionAndRealmSupportWithoutSDKUpdate.java.

Realm oraclecloud.com

Para regiões no realm oraclecloud.com, você pode especificar novos nomes de região, da mesma forma que especificaria as que já estão definidas na enumeração Região para a sua versão do SDK.

Observação

Para os exemplos de código a seguir, não se esqueça de fornecer os pontos finais apropriados para a sua região.

Se você estiver usando a versão 1.2.34 ou mais recente do SDK para Java, poderá especificar o nome da nova região como uma string usando um dos seguintes métodos:

  • Para definir a região em um cliente criado anteriormente:

    client.setRegion("ca-toronto-1");
  • Para definir uma região ao criar um novo cliente:

    Identity identityClient = IdentityClient.builder()
            .region("ca-toronto-1")
            .build(provider); 
  • Você também pode especificar a região no arquivo de configuração. Para obter mais informações, consulte Arquivo de Configuração da CLI e do SDK.

Outros Realms

Para regiões em outros realms além de oraclecloud.com, você pode usar a solução alternativa a seguir para acessar novas regiões com versões mais antigas do SDK.

Para especificar o ponto final:
AuthenticationDetailsProvider provider =
        new ConfigFileAuthenticationDetailsProvider(configurationFilePath, profile);

IdentityClient client = IdentityClient.builder()
        .endpoint("https://identity.ca-toronto-1.oraclecloud.com")
        .build(provider);
Se você estiver autenticando por meio de 'instance principals', poderá definir o ponto final e o federationEndpoint usando o seguinte processo:
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);

Respostas Paginadas

Algumas APIs retornam conjuntos de resultados paginados; portanto, você deve verificar itens adicionais e, se necessário, extrair a próxima página. Você pode fazer isso manualmente ou usar um iterador.

Extraindo Páginas Manualmente

Os objetos de Resposta contêm um método para extrair o próximo token de página. Se o token for nulo, não haverá mais itens. Se o token não for nulo, você poderá fazer uma solicitação adicional, definindo o token no objeto Request, para obter a próxima página de respostas.

Observação

Algumas APIs podem retornar um token mesmo que não haja resultados adicionais. Verifique também se algum item foi retornado e interrompa a operação se não houver um.

Esse exemplo mostra como tratar tokens de página retornados pela API do serviço 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);

Usando um Iterador

Em vez de trabalhar manualmente com tokens de página, você pode usar um iterador. Cada cliente de serviço expõe um método getPaginators() que retorna um objeto Paginator. Esse objeto contém métodos para retornar objetos do tipo Iterable. Suportamos duas abordagens para usar o tipo iterable:

  • Iterador de Resposta: você pode iterar sobre os objetos Response retornados pela operação de lista. Eles são chamados de ResponseIterators, e seus métodos recebem o sufixo "ResponseIterator"; por exemplo, listUsersResponseIterator.
    Iterable<ListUsersResponse> responseIterator = identityClient.getPaginators().listUsersResponseIterator(request);
    for (ListUsersResponse response : responseIterator) {
        for (User user : response.getItems()) {
            System.out.println(user);
        }
    }
  • Iterador de Registro: você pode iterar sobre os recursos/registros listados. São chamados de RecordIterator e seus métodos são sufixados com "RecordIterator", por exemplo, listUsersRecordIterator.
    Iterable<User> recordIterator = identityClient.getPaginators().listUsersRecordIterator(request)
    for (User user : recordIterator) {
        System.out.println(user);
    }

Criptografia do Cliente

A Criptografia do Cliente permite criptografar dados no cliente antes de armazená-los localmente ou usá-los com outros serviços do Oracle Cloud Infrastructure.

Para usar a criptografia do cliente, é necessário criar uma chave de criptografia mestra (MEK) usando o Serviço Key Management. Isso pode ser feito usando as operações CreateKey ou ImportKey.

A MEK é usada para gerar uma Chave de Criptografia de Dados (DEK) para criptografar cada payload. Uma cópia criptografada dessa DEK (criptografada na MEK) e outras partes de metadados são incluídas no payload criptografado retornado pelos SDKs para que possam ser usadas para decriptografia.

Pré-requisitos Java

Os arquivos de política ilimitados de releases anteriores são necessários somente para atualizações do JDK 8, 7 e 6 anteriores a 8u161, 7u171 e 6u16. Para essas versões e posteriores, os arquivos de políticas são incluídos, mas não ativados por padrão.

As versões atuais do JDK não exigem esses arquivos de política. Eles são fornecidos aqui para serem usados com versões mais antigas do JDK. O JDK 9 e posteriores são fornecidos com os arquivos de políticas ilimitados e os utilizam por padrão.

Exemplos

O exemplo de código a seguir mostra como criptografar uma string:


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

O exemplo a seguir mostra como criptografar um stream de arquivos:


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

Tratamento de Exceções

Ao tratar uma exceção, você pode obter mais informações sobre a solicitação HTTP que a causou, como o código de status ou o timeout. Você também pode obter o ID da solicitação ao tratar uma BmcException usando o método getOpcRequestId.

Este exemplo mostra um bloco try-catch que trata uma BmcExceptione imprime o ID da solicitação.

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

As exceções no SDK para Java são exceções de runtime (não são verificadas). Portanto, elas não são mostradas nas assinaturas de método. Todas as APIs podem gerar uma BmcException.