App Lifecycle Manager-Funktions-Flags mit Java verwenden

In dieser Anleitung wird beschrieben, wie Sie Ihre Java-Anwendungen in App Lifecycle Manager-Funktions-Flags einbinden. Sie erfahren, wie Sie das OpenFeature SDK mit dem flagd-Anbieter verwenden, um Flags auszuwerten, die von App Lifecycle Manager verwaltet werden. So können Sie die Verfügbarkeit und das Verhalten von Funktionen in Ihren Java-Diensten dynamisch steuern.

In dieser Anleitung wird davon ausgegangen, dass Sie die erforderlichen App Lifecycle Manager-Ressourcen (z. B. App-Angebote, Einheitentypen, Einheiten, Flags und Roll-outs) bereits eingerichtet haben. Führen Sie dazu eine der folgenden Kurzanleitungen aus:

Vorbereitung

Prüfen Sie vor Beginn, ob Sie Folgendes haben:

  1. Java installiert:JDK 17 oder höher.
  2. Kurzanleitung zu App Lifecycle Manager-Funktions-Flags ausgeführt:
    • Sie haben entweder die integrierte oder die eigenständige Kurzanleitung zu Funktions-Flags erfolgreich ausgeführt, um Ihre Zieleinheit bereitzustellen.
    • Sie sollten Umgebungsvariablen oder Werte aus dieser Kurzanleitung haben, z. B. PROJECT_ID, LOCATION_1 (die Region Ihrer Einheit), UNIT_ID und FLAG_KEY.
  3. Authentifiziertes gcloud für Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC): Die Java-Anwendung verwendet ADC zur Authentifizierung bei Google Cloud Diensten. Prüfen Sie, ob Sie sich in Ihrer Umgebung authentifiziert haben:

    gcloud auth application-default login
    
  4. IAM-Berechtigungen:Die Identität, mit der Ihre Java-Anwendung ausgeführt wird, benötigt die roles/saasconfig.viewer Identity and Access Management-Rolle für Ihr Google Cloud Projekt, um Flag-Konfigurationen lesen zu können:

    gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
        --member="user:YOUR_EMAIL_ADDRESS" \
        --role="roles/saasconfig.viewer"
    

    Ersetzen Sie YOUR_PROJECT_ID und YOUR_EMAIL_ADDRESS entsprechend.

Wichtige Umgebungsvariablen

Ihre Java-Anwendung verwendet Umgebungsvariablen, um eine Verbindung zur richtigen Flag-Konfiguration herzustellen.

  • FLAGD_SOURCE_PROVIDER_ID: Gibt an, welche Funktions-Flag-Konfiguration aus dem App Lifecycle Manager-Dienst abgerufen werden soll. Es muss der vollständige Ressourcenname der FeatureFlagConfig sein, die mit Ihrer Einheit verknüpft ist.
    • Format: projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID
    • Beispiel: projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01

Java-Projekt einrichten

Bevor Sie Ihre Anwendung ausführen können, müssen Sie Ihr Projekt initialisieren und die erforderlichen Abhängigkeiten konfigurieren.

  1. Projektverzeichnis erstellen :

    mkdir java-featureflag-app
    cd java-featureflag-app
    
  2. Abhängigkeiten hinzufügen:Konfigurieren Sie Ihr Buildsystem (Maven oder Gradle) so, dass die folgenden Bibliotheken enthalten sind. Verwenden Sie Versionen, die höher als OpenFeature 1.14.1, flagd 0.11.5 und gRPC 1.71.0 sind, um die Kompatibilität zu gewährleisten.

    • dev.openfeature:javasdk:1.14.1+
    • dev.openfeature.contrib.providers:flagd:0.11.5+
    • io.grpc:grpc-netty-shaded:1.71.0+
    • io.grpc:grpc-auth:1.71.0+
    • com.google.auth:google-auth-library-oauth2-http
  3. Initialisierungscode erstellen:Fügen Sie eine Datei mit dem Namen FeatureManagement.java und dem folgenden Inhalt hinzu. Diese Klasse richtet gRPC-Interceptors ein, um Standardanmeldedaten für Anwendungen- und regionale Routing-Header anzuhängen, und initialisiert den FlagdProvider mit der In-Process-Auflösung.

    import com.google.auth.oauth2.GoogleCredentials;
    import dev.openfeature.contrib.providers.flagd.Config;
    import dev.openfeature.contrib.providers.flagd.FlagdOptions;
    import dev.openfeature.contrib.providers.flagd.FlagdProvider;
    import dev.openfeature.sdk.OpenFeatureAPI;
    import io.grpc.*;
    import io.grpc.auth.MoreCallCredentials;
    import java.util.ArrayList;
    import java.util.List;
    
    public class FeatureManagement {
        public static void initialize() throws Exception {
            // Read the full Unit resource name
            String flagConfigId = System.getenv("FLAGD_SOURCE_PROVIDER_ID");
            if (flagConfigId == null || flagConfigId.isEmpty()) {
                throw new IllegalStateException("FLAGD_SOURCE_PROVIDER_ID environment variable is not set.");
            }
    
            // Configure gRPC Security and Routing
            GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
            CallCredentials callCredentials = MoreCallCredentials.from(credentials);
    
            List<ClientInterceptor> interceptors = new ArrayList<>();
    
            // Interceptor to inject the Unit name into headers for regional routing
            interceptors.add(new ClientInterceptor() {
                @Override
                public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
                    return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
                        @Override
                        public void start(Listener<RespT> responseListener, Metadata headers) {
                            headers.put(Metadata.Key.of("x-goog-request-params", Metadata.ASCII_STRING_MARSHALLER), "name=" + flagConfigId);
                            super.start(responseListener, headers);
                        }
                    };
                }
            });
    
            // Interceptor to attach ADC to the gRPC calls
            interceptors.add(new ClientInterceptor() {
                @Override
                public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
                    return next.newCall(method, callOptions.withCallCredentials(callCredentials));
                }
            });
    
            // Initialize the flagd provider with In-Process resolution
            FlagdProvider provider = new FlagdProvider(
                FlagdOptions.builder()
                    .resolverType(Config.Resolver.IN_PROCESS)
                    .host("saasconfig.googleapis.com").port(443)
                    .tls(true)
                    .providerId(flagConfigId)
                    .clientInterceptors(interceptors)
                    .syncMetadataDisabled(true)
                    .deadline(10000)
                    .build()
            );
    
            // Set the global provider
            OpenFeatureAPI.getInstance().setProviderAndWait(provider);
        }
    }
    
  4. Anwendungslogik erstellen:Fügen Sie eine Datei mit dem Namen Main.java und dem folgenden Inhalt hinzu, um die Flag-Auswertung auszuführen.

    import dev.openfeature.sdk.OpenFeatureAPI;
    import dev.openfeature.sdk.MutableContext;
    
    public class Main {
        public static void main(String[] args) throws Exception {
    
        // 1. Get Client
        var client = OpenFeatureAPI.getInstance().getClient("simple-api");
    
        // 2. Create Evaluation Context 
        var context = new dev.openfeature.sdk.MutableContext();
    
        // 3. Evaluate Flag
        // Default to false if evaluation fails or service is unreachable
        boolean isEnhanced = client.getBooleanValue("enhanced-search", false, context);
    
        // 4. Execute business logic based on result
        if (isEnhanced) {
            System.out.println("Executing enhanced search algorithm...");
        } else {
            System.out.println("Standard search algorithm...");
        }
    
        }
    }
    

Java-Anwendung ausführen

Sie können die Anwendung entweder lokal mit Ihrer eigenständigen Konfiguration oder als Container bereitgestellt ausführen.

Eigenständig ausführen (lokal)

  1. Umgebungsvariablen festlegen :

    export PROJECT_ID="your-gcp-project-id"
    export LOCATION_1="us-central1"
    export UNIT_ID="my-app-instance-01"
    export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"
    
  2. Anwendung ausführen:Führen Sie das Projekt mit dem Befehl Ihres bevorzugten Buildtools aus (z.B. mvn compile exec:java oder ./gradlew run).

Integriert ausführen (containerisiert)

  1. Dockerfile erstellen:Definieren Sie einen Container-Build, der die Java-Binärdatei packt.

    FROM maven:3.9-eclipse-temurin-17 AS builder
    WORKDIR /app
    COPY pom.xml .
    COPY src ./src
    RUN mvn clean package
    
    FROM eclipse-temurin:17-jre
    WORKDIR /app
    COPY --from=builder /app/target/java-featureflag-app.jar app.jar
    ENTRYPOINT ["java", "-jar", "app.jar"]
    
  2. Image erstellen und per Push übertragen :

    export PROJECT_ID="your-gcp-project-id"
    docker build -t gcr.io/${PROJECT_ID}/my-java-app:latest .
    docker push gcr.io/${PROJECT_ID}/my-java-app:latest
    
  3. Dienst bereitstellen:Aktualisieren Sie Ihren Einheiten-Blueprint, um auf gcr.io/${PROJECT_ID}/my-java-app:latest zu verweisen, und stellen Sie die neue Version mit einem App Lifecycle Manager-Roll-out bereit.

Flag-Änderungen prüfen

Nachdem Ihre Anwendung ausgeführt wurde, prüfen Sie, ob Flags korrekt ausgewertet werden.

  1. Anfangswert beobachten:Prüfen Sie, ob in der Konsolenausgabe der ausgewertete Wert protokolliert wird, der dem ursprünglichen Konfigurationsstatus entspricht.
  2. Flag in App Lifecycle Manager aktualisieren: Ändern Sie die Flag-Nutzlast oder die Targeting-Regeln über die Google Cloud Console oder gcloud.
  3. Aktualisierten Wert prüfen:Führen Sie die lokale Ausführung noch einmal aus oder beobachten Sie die Containerlogs, um den neuen ausgewerteten Status zu bestätigen.

Nächste Schritte