From 62f2328315d6af6326d770e62c082e6e401d30d9 Mon Sep 17 00:00:00 2001 From: Agustin Grognetti Date: Mon, 8 Dec 2025 13:49:36 -0300 Subject: [PATCH 1/4] Add plugins registration result handling Plugins now receive registration results via onPluginsReady, and PluginMetadata requires a version. Creates RegistrationCompleteResult to track plugin registration success or failure. Updates tests and interfaces to support these changes. --- .../sdk/android/LDClientPluginsTest.java | 8 +++++++- .../launchdarkly/sdk/android/LDClient.java | 20 +++++++++++++++++-- .../sdk/android/integrations/Plugin.java | 8 ++++++-- .../android/integrations/PluginMetadata.java | 3 +++ .../RegistrationCompleteResult.kt | 18 +++++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt diff --git a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java index 017c55e9..ef90382b 100644 --- a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java +++ b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java @@ -151,7 +151,13 @@ public PluginMetadata getMetadata() { @NonNull @Override public String getName() { - return "mock-plugin"; + return "mock-plugin-name"; + } + + @NonNull + @Override + public String getVersion() { + return "mock-plugin-version"; } }; } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java index d334d837..13ba3455 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java @@ -11,21 +11,23 @@ import com.launchdarkly.sdk.EvaluationReason; import com.launchdarkly.sdk.LDContext; import com.launchdarkly.sdk.LDValue; +import com.launchdarkly.sdk.android.DataModel.Flag; import com.launchdarkly.sdk.android.env.EnvironmentReporterBuilder; import com.launchdarkly.sdk.android.env.IEnvironmentReporter; import com.launchdarkly.sdk.android.integrations.EnvironmentMetadata; import com.launchdarkly.sdk.android.integrations.Hook; import com.launchdarkly.sdk.android.integrations.IdentifySeriesResult; import com.launchdarkly.sdk.android.integrations.Plugin; +import com.launchdarkly.sdk.android.integrations.RegistrationCompleteResult; import com.launchdarkly.sdk.android.integrations.SdkMetadata; import com.launchdarkly.sdk.android.subsystems.ApplicationInfo; import com.launchdarkly.sdk.android.subsystems.Callback; -import com.launchdarkly.sdk.android.DataModel.Flag; import com.launchdarkly.sdk.android.subsystems.EventProcessor; import com.launchdarkly.sdk.android.subsystems.PersistentDataStore; import java.io.Closeable; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -198,7 +200,7 @@ public static Future init(@NonNull Application application, resultFuture.setException(e); return resultFuture; } - }; + } primaryClient = createdPrimaryClient; // this indirect way of setting primaryClient is simply to make it easier to reference // it within an inner class below, since it is "effectively final" @@ -223,9 +225,23 @@ public static Future init(@NonNull Application application, } } + List pluginFailures = new ArrayList<>(); for (Plugin plugin : instance.plugins) { try { plugin.register(instance, metadata); + } catch (Exception e) { + pluginFailures.add(new RegistrationCompleteResult.Failure.PluginFailure(plugin.getMetadata().getName(), e.getMessage(), e)); + logger.error("Exception thrown registering plugin " + plugin.getMetadata().getName() + "."); + } + } + + RegistrationCompleteResult pluginsRegistrationResult = pluginFailures.isEmpty() + ? RegistrationCompleteResult.success() + : RegistrationCompleteResult.failure(pluginFailures); + + for (Plugin plugin : instance.plugins) { + try { + plugin.onPluginsReady(pluginsRegistrationResult, metadata); } catch (Exception e) { logger.error("Exception thrown registering plugin " + plugin.getMetadata().getName() + "."); } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java index f42a9e72..a4119611 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java @@ -26,7 +26,7 @@ public abstract class Plugin { * the SDK is configured with multiple environments. Use the metadata to distinguish * environments. * - * @param client for the plugin to use + * @param client for the plugin to use * @param metadata metadata about the environment where the plugin is running. */ public abstract void register(LDClient client, EnvironmentMetadata metadata); @@ -40,11 +40,15 @@ public abstract class Plugin { * environments. * * @param metadata metadata about the environment where the plugin is running. - * @return + * @return a non-null, possibly empty, list of {@link Hook} instances */ @NonNull public List getHooks(EnvironmentMetadata metadata) { // default impl return Collections.emptyList(); } + + public void onPluginsReady(RegistrationCompleteResult result, EnvironmentMetadata metadata) { + // default: do nothing + } } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java index 1b9b36d7..17663dcd 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java @@ -6,4 +6,7 @@ public abstract class PluginMetadata { @NonNull public abstract String getName(); + + @NonNull + public abstract String getVersion(); } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt new file mode 100644 index 00000000..45b0b71e --- /dev/null +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt @@ -0,0 +1,18 @@ +package com.launchdarkly.sdk.android.integrations + +import com.launchdarkly.sdk.android.integrations.RegistrationCompleteResult.Failure.PluginFailure + +sealed class RegistrationCompleteResult { + object Success : RegistrationCompleteResult() + data class Failure(val failures: List) : RegistrationCompleteResult() { + data class PluginFailure(val pluginName: String, val message: String?, val cause: Throwable?) + } + + companion object { + @JvmStatic + fun success() = Success + + @JvmStatic + fun failure(failures: List) = Failure(failures) + } +} From 6754fa6da2f0cbc5b82b81667c8cc3456e76d8ec Mon Sep 17 00:00:00 2001 From: Agustin Grognetti Date: Mon, 8 Dec 2025 15:29:31 -0300 Subject: [PATCH 2/4] Improve plugin error log message in LDClient Updated the error log message in LDClient to clarify that the exception occurred during execution of onPluginsReady for a plugin, rather than during registration. --- .../src/main/java/com/launchdarkly/sdk/android/LDClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java index 13ba3455..d081870e 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java @@ -243,7 +243,7 @@ public static Future init(@NonNull Application application, try { plugin.onPluginsReady(pluginsRegistrationResult, metadata); } catch (Exception e) { - logger.error("Exception thrown registering plugin " + plugin.getMetadata().getName() + "."); + logger.error("Exception thrown executing onPluginsReady for plugin " + plugin.getMetadata().getName() + "."); } } } From b8ab9f952c16b8279cb72fa78602ab94a092176f Mon Sep 17 00:00:00 2001 From: Agustin Grognetti Date: Thu, 11 Dec 2025 15:46:17 -0300 Subject: [PATCH 3/4] Add `getId` and `getVersion` to `PluginMetadata` Adds a new `getId()` and `getVersion` methods to the `PluginMetadata` abstract class, returning empty strings by default. --- .../sdk/android/integrations/PluginMetadata.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java index 17663dcd..2d54b1f6 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java @@ -4,9 +4,16 @@ public abstract class PluginMetadata { + @NonNull + public String getId() { + return ""; + } + @NonNull public abstract String getName(); @NonNull - public abstract String getVersion(); + public String getVersion() { + return ""; + } } From a14d9c3da7ab76f50da15b14ec11e6b2382dea9b Mon Sep 17 00:00:00 2001 From: Agustin Grognetti Date: Thu, 11 Dec 2025 15:47:59 -0300 Subject: [PATCH 4/4] Update LDClientPluginsTest.java --- .../com/launchdarkly/sdk/android/LDClientPluginsTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java index ef90382b..8f08239b 100644 --- a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java +++ b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java @@ -159,6 +159,12 @@ public String getName() { public String getVersion() { return "mock-plugin-version"; } + + @NonNull + @Override + public String getId() { + return "mock-plugin-id"; + } }; }