Konzepte

In diesem Thema werden einige der Schlüsselkonzepte bei der Verwendung des Oracle Cloud Infrastructure-SDK für Java erläutert.

In diesem Thema werden einige der Schlüsselkonzepte bei der Verwendung des Oracle Cloud Infrastructure-SDK für Java erläutert.

Synchrone Aufrufe

Um synchrone Aufrufe durchzuführen, erstellen Sie eine Instanz des synchronen Clients. Das allgemeine Muster für synchrone Clients sieht wie folgt aus: Für einen Service mit dem Namen Example gibt es eine Schnittstelle mit dem Namen ExampleService, und die Implementierung des synchronen Clients wird als ExampleServiceClient bezeichnet. Im Folgenden finden Sie ein Beispiel für das Erstellen eines Object Storage-Clients:

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

Synchrone Aufrufe werden blockiert, bis die Antwort verfügbar ist. Alle SDK-APIs geben ein Antwortobjekt zurück (unabhängig davon, ob die API Inhalt zurücksendet oder nicht). Das Antwortobjekt enthält im Allgemeinen mindestens eine Anforderungs-ID, die Sie beim Kontaktieren von Oracle Support angeben können, um Hilfe zu einer bestimmten Anforderung zu erhalten.

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

Asynchrone Aufrufe

Um asynchrone Aufrufe durchzuführen, erstellen Sie eine Instanz des asynchronen Clients. Das allgemeine Muster für asynchrone Clients sieht wie folgt aus: Für einen Service mit dem Namen Example gibt es eine Schnittstelle mit dem Namen ExampleServiceAsync, und die Implementierung des asynchronen Clients wird als ExampleServiceAsyncClient bezeichnet. Im Folgenden finden Sie ein Beispiel für das Erstellen eines Object Storage-Clients:

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

Asynchrone Aufrufe werden sofort zurückgegeben. Sie müssen einen AsyncHandler angeben, der aufgerufen wird, nachdem der Aufruf entweder erfolgreich oder nicht erfolgreich abgeschlossen wurde:

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

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

Polling mit Wartenden

Das SDK bietet Wartende, mit denen Ihr Code warten kann, bis eine bestimmte Ressource den gewünschten Status erreicht. Ein Wartender kann sowohl blockierend als auch nicht blockierend (mit asynchronem Callback) aufgerufen werden und wartet, bis der gewünschte Status erreicht oder ein Timeout überschritten wird. Wartende abstrahieren die Polling-Logik, die Sie sonst in einen benutzerfreundlichen einzelnen Methodenaufruf schreiben müssten.

Wartende werden über den Serviceclient abgerufen (client.getWaiters()). Sowohl eine Get<Resource>Request-Anforderung als auch der gewünschte Lebenszyklusstatus werden an die Methode waiters.for<Resource> übergeben. Beispiel:

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

Jede waiters.for<Resource>-Methode hat zwei Versionen:

  • Eine Version nutzt die Standard-Polling-Werte. Beispiel:

    waiters.forInstance(GetInstanceRequest, LifecycleState)
  • Die andere Version bietet Ihnen volle Kontrolle über die Wartezeit und die Zeit zwischen Polling-Versuchen. Beispiel:

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

Threading-Modell

Ein Client wird bei der Initialisierung threadsicher. Nachdem Sie den Endpunkt festgelegt haben, können Sie einen Client sicher in mehreren Threads und nebenläufig in Aufrufmethoden verwenden.

Sie können einen Client in mehreren Anforderungen sowohl über nebenläufige Threads als auch innerhalb eines einzelnen Threads wiederverwenden. Wenn die Ressourcen der Umgebung nicht eingeschränkt sind, sollten Sie den Client erst kurz vor Überschreiten des Geltungsbereichs schließen.

Hinweis

Diese Garantie gilt nur für die standardmäßige JAX-RS-Implementierung, Jersey. Wenn Sie eine alternative Implementierung verwenden, müssen Sie die Threadsicherheit selbst verwalten. Weitere Informationen finden Sie unter SDK konfigurieren.

Large Objects hochladen

Der Object Storage-Service unterstützt Multipart-Uploads, um Large-Object-Uploads zu vereinfachen, indem das Large Object in Teile aufgeteilt wird. Das SDK für Java unterstützt Raw-Vorgänge für mehrteilige Uploads für erweiterte Anwendungsfälle sowie eine Uploadklasse auf höherer Ebene, die die APIs für Multipart-Uploads verwendet. Unter Mehrteilige Uploads verwenden finden Sie Links zu den APIs, die für mehrteilige Uploadvorgänge verwendet werden. Multipart-Uploads auf höherer Ebene werden mit UploadManager implementiert. Dabei wird ein Large Object für Sie in Teile aufgeteilt, und die Teile werden parallel hochgeladen und dann wieder zusammengesetzt, sodass die Teile als einzelnes Objekt im Speicher festgeschrieben werden.

Das Beispiel UploadObject zeigt, wie mit UploadManager ein Objekt für den Upload automatisch aufgeteilt wird, um die Interaktion mit dem Object Storage-Service zu vereinfachen.

Wiederholungen

Ab Version 2.10.0 ist das SDK für Java standardmäßig so konfiguriert, dass bestimmte nicht erfolgreiche SDK-Vorgänge wiederholt werden. Mit dem SDK können Sie die Strategie für Wiederholungen angeben, einschließlich der Anzahl der Wiederholungsversuche, der Bedingung, unter der das SDK einen Vorgang wiederholen soll, und wann die Wiederholung eines Vorgangs gestoppt werden soll. Sie können diese Parameter auf Clientebene und auf individueller Anforderungsebene festlegen.

Um zu bestimmen, für welche Servicevorgänge standardmäßig Wiederholungen aktiviert sind, lesen Sie die Beschreibung der Servicevorgänge im SDK.

Hinweis

Wiederholungen werden derzeit für asynchrone Clients nicht unterstützt.

Standardmäßig wiederholt das SDK Vorgänge mit HTTP-Antwortstatuscodes 409 (mit einem IncorrectState-Fehlercode), 429, 500, 502, 503, 504, Timeoutfehlern (wie HTTP-Verbindungs- und Lesetimeouts), Verbindungsanforderungsfehlern, Anforderungsausnahmen und Circuit-Breaker-Ausnahmen.

Die aktuelle Standardwiederholungskonfiguration und die Liste der wiederholbaren Fehler finden Sie auf GitHub.

Standardwiederholungen deaktivieren

Um ein Opt-out aus dem Standardwiederholungsfeature vorzunehmen, können Sie einen der folgenden Schritte ausführen:

  1. Setzen Sie die Umgebungsvariable OCI_SDK_DEFAULT_RETRY_ENABLED auf false, um die Standardwiederholungen global zu deaktivieren.
  2. Setzen Sie die Standardwiederholungen für eine bestimmte Clientinstanz außer Kraft. Dieses Beispiel zeigt, wie die Standardwiederholungen für objectStorageClient außer Kraft gesetzt werden:

    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder()
                    .retryConfiguration(RetryConfiguration.builder().terminationStrategy(new MaxAttemptsTerminationStrategy(1))
                            .build())
                    .build();
    ObjectStorage objectStorageClient = ObjectStorageClient.builder().configuration(clientConfiguration).build(provider);
    
  3. Setzen Sie Standardwiederholungen für eine bestimmte Anforderungsinstanz außer Kraft. Dieses Beispiel zeigt, wie Wiederholungen für putObjectRequest außer Kraft gesetzt werden:

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

Priorität für Wiederholungsverhalten

  • Jede Wiederholungskonfiguration, die Sie explizit auf Anforderungsebene definieren, setzt die Wiederholungskonfiguration auf Clientebene oder auf globaler Ebene und den Override der Umgebungsvariablen für die betreffende Anforderungsinstanz außer Kraft.
  • Jede explizit auf Clientebene definierte Wiederholungskonfiguration setzt die globale Wiederholungskonfiguration und den Override auf Umgebungsvariablenebene für die betreffende Clientinstanz außer Kraft.

Wiederholungsstrategien

Sie können die Strategie für Wiederholungen angeben, einschließlich der Anzahl der Wiederholungsversuche, der Bedingung, unter der das SDK einen Vorgang wiederholen soll, und wann die Wiederholung eines Vorgangs gestoppt werden soll. Sie können diese Parameter auf Clientebene und auf individueller Anforderungsebene festlegen.
Hinweis

Die aktuelle Standardwiederholungskonfiguration und die Liste der wiederholbaren Fehler finden Sie auf GitHub.

Verzögerungsstrategie

Der Parameter delayStrategy bestimmt, wie lange zwischen jedem Wiederholungsaufruf gewartet werden soll. Für diesen Parameter sind zwei Optionen verfügbar:

  • FixedTimeDelayStrategy (milliseconds): Jede Wiederholung wird um eine angegebene Anzahl Millisekunden verzögert.
  • ExponentialBackoffDelayStrategy (milliseconds): Die Verzögerungszeit für nachfolgende Wiederholungsaufrufe erhöht sich um den exponentiellen Faktor 2, bis sie die definierte maximale Verzögerung (in Millisekunden) mit einem Basiswert von einer Millisekunde erreicht.

Die Standardverzögerungsstrategie wird auf ExponentialBackoffDelayStrategy gesetzt. Der Jitter-Wert beträgt zwischen 0 und 1000 Millisekunden, und die maximale Wartezeit zwischen Aufrufen beträgt 30 Sekunden.

Wiederholungsbedingung

retryCondition definiert eine Funktion mit einem Fehlerargument, die einen booleschen Wert zurückgibt, der angibt, ob der Vorgang wiederholt werden soll oder nicht. Der Vorgang wird erneut ausgeführt, wenn diese Funktion true zurückgibt.

Beendigungsstrategie

Der Parameter terminationStrategy definiert, wann die Wiederholungsversuche beendet werden sollen. Dieser Parameter unterstützt die folgenden Optionen:

  • MaxTimeTerminationStrategy (milliseconds): Definiert die Gesamtdauer für die Wiederholungsversuche in Millisekunden.
  • MaxAttemptsTerminationStrategy (attempts): Definiert die Gesamtanzahl der Wiederholungsversuche.

Die Standardbeendigungsstrategie für OCI-SDKs ist eine MaxAttemptsTerminationStrategy von 8.

Wiederholungsbeispiele

Java

In diesem Beispiel wird gezeigt, wie Sie Wiederholungen mit dem SDK für Java konfigurieren und verwenden:

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

Circuit Breaker

Ab Version 2.10.0 bietet das SDK für Java Standardunterstützung für Circuit Breaker für Serviceclients, bei denen Standard-SDK-Circuit-Breaker aktiviert sind. Circuit Breaker verhindern, dass der Client den Service überlastet, indem sie Anforderungen an den Service blockieren, nachdem ein bestimmter Fehlerschwellenwert erreicht wurde.

Hinweis

Standard-Circuit-Breaker werden derzeit nicht für asynchrone Clients unterstützt.

Bei Standard-Circuit-Breakern werden alle wiederholbaren Fehler als Fehler für die Circuit Breaker behandelt. Informationen zum Bestimmen, für welche Serviceclients Circuit Breaker aktiviert sind, finden Sie in der Beschreibung des Serviceclients im SDK.

Hinweis

Die Circuit-Breaker-Standardkonfiguration finden Sie auf GitHub.

Circuit-Breaker-Konfiguration

Die folgenden Parameter definieren einen Circuit Breaker:

  • Schwellenwert für Fehler: Der Status des Circuit Breakers ändert sich von CLOSED in OPEN, wenn die Fehlerrate größer oder gleich diesem Schwellenwert ist. Beispiel: Wenn mehr als 50 % der aufgezeichneten Aufrufe nicht erfolgreich sind, wird der Circuit Breaker geöffnet.
  • Rücksetztimeout : Zeit, nach der ein offener Circuit Breaker eine Anforderung versucht, wenn eine Anforderung erfolgt.
  • Fehlerausnahmen: Liste der Ausnahmen, die als Fehler für den Circuit betrachtet werden.
  • Mindestanzahl Aufrufe/Volumenschwellenwert: Die Mindestanzahl von Aufrufen, die erforderlich sind (pro gleitendem Zeitraum), bevor der Circuit Breaker die Fehlerrate berechnen kann.

Circuit-Breaker-Standardkonfiguration

Die Circuit-Breaker-Standardkonfiguration lautet wie folgt:

  • Schwellenwert für Fehlerrate: 80 %. Wenn 80 % der Anforderungen, die für ein Zeitfenster von 120 Sekunden berechnet wurden, nicht erfolgreich sind, geht der Circuit von "Geschlossen" in "Offen" über.
  • Mindestanzahl Aufrufe/Volumenschwellenwert: 10 für das oben definierte Zeitfenster von 120 Sekunden.
  • Rücksetztimeout: Der Circuit Breaker wird nach 30 Sekunden in den Status halfOpen versetzt, und die Aktion wird erneut versucht.
  • Fehlerausnahmen: Die Fehler für den Circuit werden nur für wiederholbare oder transiente Ausnahmen aufgezeichnet. HTTP-Antwortcodes 409 (mit IncorrectState), 429, 500, 502, 503 und 504, HTTP-Anforderungs- und andere Timeouts, Anforderungsverbindungsfehler und Ausnahmen werden alle als Fehler behandelt, die einen Circuit Breaker auslösen.

Standard-Circuit-Breaker deaktivieren

Um ein Opt-out aus dem Circuit-Breaker-Standardfeature vorzunehmen, können Sie einen der folgenden Schritte ausführen:

  1. Setzen Sie die Umgebungsvariable OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED auf false.
  2. Ändern Sie die Circuit-Breaker-Standardkonfiguration für eine Clientinstanz. Das folgende Beispiel zeigt die Vorgehensweise mit einer IdentityClient-Instanz:
    ClientConfiguration clientConfiguration =
            ClientConfiguration.builder().circuitBreakerConfiguration(CircuitBreakerUtils.getNoCircuitBreakerConfiguration()).build();
     
            // Create Clients using above ClientConfiguration
            IdentityClient identityClient = new IdentityClient(provider, clientConfiguration);

Prioritätsfolge des Circuit-Breaker-Verhaltens

Jede explizit auf Clientebene definierte Circuit-Breaker-Konfiguration setzt die globale Circuit-Breaker-Konfiguration und den Override auf Umgebungsebene für den betreffenden Client außer Kraft.

Weitere Informationen zu Circuit Breakern und zur Circuit-Breaker-Standardkonfiguration finden Sie in diesem Beispiel auf GitHub.

Raw-Anforderungen

Raw-Anforderungen sind nützlich und in einigen Fällen erforderlich. Typische Anwendungsfälle sind die Verwendung Ihres eigenen HTTP-Clients, die Durchführung einer OCI-authentifizierten Anforderung an einen alternativen Endpunkt und die Durchführung einer Anforderung an eine OCI-API, die aktuell im SDK nicht unterstützt wird. Das SDK für Java zeigt die Klasse DefaultRequestSigner an, mit der Sie eine RequestSigner-Instanz für Nicht-Standardanforderungen erstellen können.

Das Beispiel für Raw-Anforderungen auf GitHub zeigt, wie Sie Folgendes durchführen:

  • Authentifizierungsprovider erstellen und Signaturgeber anfordern
  • Integration mit einem HTTP-Client (in diesem Beispiel Jersey) durchführen, um Anforderungen zu authentifizieren

Endpunkte festlegen

Serviceendpunkte können auf drei Arten festgelegt werden.

  • Rufen Sie setEndpoint() in der Serviceinstanz auf. Auf diese Weise können Sie einen vollständigen Hostnamen angeben (z.B. https://www.example.com).
  • Rufen Sie setRegion() in der Serviceinstanz auf. Dadurch wird der entsprechende Hostname für den Service für die angegebene Region ausgewählt. Wenn der Service jedoch in der von Ihnen festgelegten Region nicht unterstützt wird, gibt das SDK für Java einen Fehler zurück.
  • Übergeben Sie die Region in der Konfigurationsdatei. Weitere Informationen finden Sie unter SDK- und CLI-Konfigurationsdatei.

Beachten Sie, dass eine Serviceinstanz nicht zur Kommunikation mit verschiedenen Regionen verwendet werden kann. Wenn Sie Anforderungen an verschiedene Regionen durchführen müssen, erstellen Sie mehrere Serviceinstanzen.

Dedizierte Endpunkte

Dedizierte Endpunkte sind die Endpunktvorlagen, die vom Service für eine bestimmte Realm auf Client-Ebene definiert werden. Mit dem OCI-Java-SDK können Sie die Verwendung des Realm-spezifischen Endpunktvorlagenfeatures sowohl auf Anwendungsebene als auch auf Clientebene aktivieren. Dieses Feature ist standardmäßig deaktiviert.
Hinweis

Der auf Client-Ebene festgelegte Wert hat Vorrang vor dem auf Anwendungsebene festgelegten Wert.

Realm-spezifische Endpunktvorlagen auf Anwendungsebene aktivieren:

Um das Realm-spezifische Endpunktvorlagenfeature auf Anwendungsebene zu aktivieren, setzen Sie die Umgebungsvariable OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED auf true.
Hinweis

Bei dem booleschen Wert wird die Groß- und Kleinschreibung nicht berücksichtigt.

Realm-spezifische Endpunktvorlagen auf Anwendungsebene aktivieren:

Um das Realm-spezifische Endpunktvorlagenfeature auf Client-Ebene zu aktivieren, setzen Sie das Kennzeichen in Code wie dargestellt:

Für das OCI-SDK für Java:

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

Ein vollständiges Beispiel finden Sie unter UseRealmSpecificEndpointsExample on Github.

Für das Legacy-OCI-SDK für Java:

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

Ein vollständiges Beispiel finden Sie unter UseRealmSpecificEndpointsExample on GitHub.

Aufwärtskompatibilität und enums

Wenn Sie über eine bedingte Logik basierend auf einem enum verfügen, stellen Sie sicher, dass Ihr Code den Fall UnknownEnumValue verarbeitet, um die Aufwärtskompatibilität zu gewährleisten. Einige Antwortfelder haben den Typ "enum", in Zukunft geben aber möglicherweise einzelne Services Werte zurück, die nicht durch vorhandene enums für dieses Feld abgedeckt sind. Aus diesem Grund hat jedes Antwortfeld vom Typ "enum" einen zusätzlichen Wert mit dem Namen UnknownEnumValue. Wenn ein Service einen Wert zurückgibt, der von Ihrer SDK-Version nicht erkannt wird, wird das Antwortfeld auf diesen Wert gesetzt.

Support für neue Regionen

Wenn Sie eine SDK-Version verwenden, die vor der Ankündigung einer neuen Region veröffentlicht wurde, können Sie diese mit einem Workaround erreichen.

Eine Region ist ein lokalisierter geografischer Bereich. Weitere Informationen zu Regionen und deren Identifizierung finden Sie unter Regionen und Availability-Domains.

Eine Realm besteht aus einer Reihe von Regionen, die gemeinsame Entitys haben. Sie können Ihre Realm identifizieren, indem Sie sich den Domainnamen am Ende der Netzwerkadresse ansehen. Beispiel: Die Realm für xyz.abc.123.oraclecloud.com ist oraclecloud.com.

Sie müssen zunächst Region.register aufrufen, um die neue Region zu registrieren. Anschließend können Sie die Region entweder mit der Konfigurationsdatei oder durch Aufrufen der Methode setRegion festlegen.

Hinweis

Sobald eine Region registriert wurde, ist der Föderationsendpunkt bei der Verwendung von Instanz-Principals nicht mehr erforderlich. Ein Beispiel finden Sie unter https://github.com/oracle/oci-java-sdk/blob/master/bmc-examples/src/main/java/NewRegionAndRealmSupportWithoutSDKUpdate.java.

Realm "oraclecloud.com"

Für Regionen in der Realm oraclecloud.com können Sie neue Regionsnamen ebenso übergeben, wie Sie bereits in der enum Region für Ihre SDK-Version definierte Regionen übergeben würden.

Hinweis

Bei den folgenden Codebeispielen müssen Sie die entsprechenden Endpunkte für Ihre Region angeben.

Wenn Sie Version 1.2.34 oder höher des SDK für Java verwenden, können Sie den neuen Regionsnamen als Zeichenfolge mit einer der folgenden Methoden übergeben:

  • So legen Sie die Region auf einem zuvor erstellten Client fest:

    client.setRegion("ca-toronto-1");
  • So legen Sie eine Region fest, wenn Sie einen neuen Client erstellen:

    Identity identityClient = IdentityClient.builder()
            .region("ca-toronto-1")
            .build(provider); 
  • Sie können die Region auch in der Konfigurationsdatei übergeben. Weitere Informationen finden Sie unter SDK- und CLI-Konfigurationsdatei.

Weitere Realms

Bei Regionen in anderen Realms als oraclecloud.com können Sie mit den folgenden Workarounds neue Regionen mit früheren Versionen des SDK erreichen.

So geben Sie den Endpunkt an:
AuthenticationDetailsProvider provider =
        new ConfigFileAuthenticationDetailsProvider(configurationFilePath, profile);

IdentityClient client = IdentityClient.builder()
        .endpoint("https://identity.ca-toronto-1.oraclecloud.com")
        .build(provider);
Wenn Sie die Authentifizierung über Instanz-Principals durchführen, können Sie den Endpunkt und federationEndpoint über den folgenden Prozess festlegen:
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);

Paginierte Antworten

Einige APIs geben paginierte Ergebnismengen zurück. Sie müssen also nach zusätzlichen Elementen suchen und bei Bedarf die nächste Seite abrufen. Dies kann manuell geschehen, oder Sie können einen Iterator verwenden.

Seiten manuell abrufen

Die Antwortobjekte enthalten eine Methode zum Abrufen des nächsten Seitentokens. Wenn das Token null ist, sind keine weiteren Elemente vorhanden. Wenn es nicht null ist, können Sie eine zusätzliche Anforderung erstellen, indem Sie das Token auf dem Objekt Request festlegen, um die nächste Seite mit Antworten abzurufen.

Hinweis

Einige APIs können auch dann ein Token zurückgeben, wenn keine weiteren Ergebnisse vorliegen. Prüfen Sie auch, ob Elemente zurückgegeben wurden, und stoppen Sie, wenn keine Elemente vorhanden sind.

Dieses Beispiel zeigt, wie Seitentoken verarbeitet werden, die von der Object Storage-API zurückgegeben werden:

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

Iterator verwenden

Anstatt manuell mit Seitentoken zu arbeiten, können Sie einen Iterator verwenden. Jeder Serviceclient gibt eine getPaginators()-Methode an, die ein Paginator-Objekt zurückgibt. Dieses Objekt enthält Methoden zur Rückgabe von Objekten des Typs Iterable. Wir unterstützen zwei Ansätze für die Verwendung von iterable:

  • Antwortiterator: Sie können über die Response-Objekte iterieren, die vom Listenvorgang zurückgegeben werden. Diese werden als ResponseIterators bezeichnet, und ihre Methoden werden mit dem Suffix "ResponseIterator" versehen (Beispiel: listUsersResponseIterator).
    Iterable<ListUsersResponse> responseIterator = identityClient.getPaginators().listUsersResponseIterator(request);
    for (ListUsersResponse response : responseIterator) {
        for (User user : response.getItems()) {
            System.out.println(user);
        }
    }
  • Datensatziterator: Sie können über die aufgeführten Ressourcen/Datensätze iterieren. Diese werden als RecordIterator bezeichnet, und ihre Methoden werden mit dem Suffix "RecordIterator" versehen (Beispiel: listUsersRecordIterator).
    Iterable<User> recordIterator = identityClient.getPaginators().listUsersRecordIterator(request)
    for (User user : recordIterator) {
        System.out.println(user);
    }

Clientseitige Verschlüsselung

Mit der clientseitigen Verschlüsselung können Sie Daten auf Clientseite verschlüsseln, bevor Sie sie lokal speichern oder mit anderen Oracle Cloud Infrastructure-Services verwenden.

Um die clientseitige Verschlüsselung zu verwenden, müssen Sie einen Masterverschlüsselungsschlüssel (Master Encryption Key, MEK) mit dem Key Management-Service erstellen. Dies kann mit CreateKey - oder ImportKey-Vorgängen geschehen.

Mit dem MEK wird ein Datenverschlüsselungsschlüssel (Data Encryption Key, DEK) generiert, um jede Payload zu verschlüsseln. Eine verschlüsselte Kopie dieses DEK (mit dem MEK verschlüsselt) und andere Metadaten werden in die verschlüsselte Payload aufgenommen, die von den SDKs zurückgegeben wird, damit sie zur Entschlüsselung verwendet werden können.

Voraussetzungen für Java

Die unbegrenzten Policy-Dateien für frühere Releases sind nur für JDK 8, 7 und 6 Updates vor 8u161, 7u171 und 6u16 erforderlich. Bei diesen und späteren Versionen sind die Policy-Dateien enthalten, jedoch nicht standardmäßig aktiviert.

Für aktuelle Versionen von JDK sind diese Policy-Dateien nicht erforderlich. Sie werden hier zur Verwendung mit älteren Versionen von JDK bereitgestellt. JDK 9 und höher werden mit unbegrenzten Policy-Dateien geliefert und verwenden diese standardmäßig.

Beispiele

Das folgende Codebeispiel zeigt, wie eine Zeichenfolge verschlüsselt wird:


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

Das folgende Beispiel zeigt, wie ein Dateistream verschlüsselt wird:


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

Ausnahmenverarbeitung

Bei der Verarbeitung einer Ausnahme können Sie weitere Informationen zu der HTTP-Anforderung erhalten, die diese verursacht hat, wie Statuscode oder Timeout. Sie können die Anforderungs-ID auch bei der Verarbeitung einer BmcException mit der Methode getOpcRequestId abrufen.

Dieses Beispiel zeigt einen Try-Catch-Block, der eine BmcException verarbeitet und die Anforderungs-ID ausgibt.

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

Ausnahmen im SDK für Java sind Laufzeitausnahmen (ungeprüft), sodass sie nicht in Methodensignaturen angezeigt werden. Alle APIs können eine BmcException auslösen.