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 von App Lifecycle Manager verwaltete Flags auszuwerten. 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. SaaS-Angebote, Einheitentypen, Einheiten, Flags und Roll-outs) bereits eingerichtet haben. Dazu haben Sie eine der folgenden Kurzanleitungen abgeschlossen:

Vorbereitung

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

  1. Java installiert:JDK 17 oder höher.
  2. Eine Kurzanleitung zu App Lifecycle Manager-Funktions-Flags abgeschlossen:
    • Sie haben entweder die integrierte oder die eigenständige Kurzanleitung zu Funktions-Flags abgeschlossen, 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 Build-System (Maven oder Gradle) so, dass die folgenden Bibliotheken enthalten sind. Verwenden Sie Versionen, die mit OpenFeature 1.14.1, flagd 0.11.5 und gRPC 1.71.0 kompatibel sind.

    • 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 ADC- 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 Build-Tools aus (z.B. mvn compile exec:java oder ./gradlew run).

Integriert ausführen (Container)

  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 Einheits-Blueprint, um auf gcr.io/${PROJECT_ID}/my-java-app:latest zu verweisen, und stellen Sie die Neuveröffentlichung 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 mit der Google Cloud Konsole 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