Menggunakan tombol fitur App Lifecycle Manager dengan Java

Panduan ini menjelaskan cara mengintegrasikan aplikasi Java Anda dengan tombol fitur App Lifecycle Manager. Anda akan mempelajari cara menggunakan OpenFeature SDK dengan penyedia flagd untuk mengevaluasi flag yang dikelola oleh App Lifecycle Manager, sehingga Anda dapat mengontrol ketersediaan dan perilaku fitur secara dinamis di layanan Java Anda.

Panduan ini mengasumsikan bahwa Anda telah menyiapkan resource App Lifecycle Manager yang diperlukan (seperti penawaran Aplikasi, jenis unit, unit, tanda, dan peluncuran) dengan menyelesaikan salah satu panduan memulai berikut:

Prasyarat

Sebelum memulai, pastikan Anda memiliki hal-hal berikut:

  1. Java yang diinstal: JDK 17 atau yang lebih baru.
  2. Menyelesaikan Panduan memulai tombol fitur App Lifecycle Manager:
    • Berhasil menyelesaikan panduan memulai tombol fitur terintegrasi atau mandiri untuk menyediakan unit target Anda.
    • Anda harus memiliki variabel lingkungan atau nilai dari panduan memulai tersebut, seperti PROJECT_ID, LOCATION_1 (region Unit Anda), UNIT_ID, dan FLAG_KEY.
  3. gcloud yang diautentikasi untuk Kredensial Default Aplikasi (ADC): Aplikasi Java menggunakan ADC untuk melakukan autentikasi dengan layanan Google Cloud . Pastikan Anda telah melakukan autentikasi di lingkungan Anda:

    gcloud auth application-default login
    
  4. Izin IAM: Identitas yang menjalankan aplikasi Java Anda memerlukan peran Identity and Access Management roles/saasconfig.viewer di project Google Cloud Anda untuk membaca konfigurasi flag:

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

    Ganti YOUR_PROJECT_ID dan YOUR_EMAIL_ADDRESS dengan yang sesuai.

Memahami variabel lingkungan utama

Aplikasi Java Anda mengandalkan variabel lingkungan untuk terhubung ke konfigurasi flag yang benar.

  • FLAGD_SOURCE_PROVIDER_ID: Menentukan konfigurasi tombol fitur mana yang akan diambil dari layanan App Lifecycle Manager. Nama resource lengkap FeatureFlagConfig yang terkait dengan unit Anda.
    • Format: projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID
    • Contoh: projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01

Menyiapkan project Java

Sebelum dapat menjalankan aplikasi, Anda harus melakukan inisialisasi project dan mengonfigurasi dependensi yang diperlukan.

  1. Buat direktori project:

    mkdir java-featureflag-app
    cd java-featureflag-app
    
  2. Tambahkan dependensi: Konfigurasikan sistem build Anda (Maven atau Gradle) untuk menyertakan library berikut. Pastikan kompatibilitas dengan menggunakan versi yang lebih tinggi dari OpenFeature 1.14.1, flagd 0.11.5, dan gRPC 1.71.0.

    • 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. Buat kode inisialisasi: Tambahkan file bernama FeatureManagement.java dengan konten berikut. Class ini menyiapkan interceptor gRPC untuk melampirkan ADC dan header pemilihan rute regional, serta menginisialisasi FlagdProvider menggunakan resolusi dalam proses.

    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. Buat logika aplikasi: Tambahkan file bernama Main.java dengan konten berikut untuk menjalankan evaluasi flag.

    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...");
        }
    
        }
    }
    

Menjalankan aplikasi Java

Anda dapat menjalankan aplikasi secara lokal menggunakan konfigurasi mandiri atau di-deploy sebagai container.

Menjalankan secara mandiri (lokal)

  1. Menetapkan variabel lingkungan:

    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. Jalankan aplikasi: Jalankan project menggunakan perintah alat build pilihan Anda (misalnya, mvn compile exec:java atau ./gradlew run).

Menjalankan aplikasi terintegrasi (dalam container)

  1. Buat Dockerfile: Tentukan build container yang mengemas biner Java.

    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. Bangun dan kirim image:

    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. Deploy layanan: Perbarui blueprint unit Anda untuk mereferensikan gcr.io/${PROJECT_ID}/my-java-app:latest dan deploy rilis baru menggunakan peluncuran App Lifecycle Manager.

Memverifikasi perubahan tanda

Setelah aplikasi Anda berjalan, pastikan aplikasi tersebut mengevaluasi flag dengan benar.

  1. Amati nilai awal: Pastikan output konsol mencatat nilai yang dievaluasi sesuai dengan status konfigurasi awal.
  2. Perbarui tanda di App Lifecycle Manager: Ubah payload tanda atau aturan penargetan menggunakan konsol Google Cloud atau gcloud.
  3. Verifikasi nilai yang diperbarui: Jalankan kembali eksekusi lokal atau amati log penampung untuk mengonfirmasi status baru yang dievaluasi.

Langkah berikutnya