LaunchDarkly Java SDK Implementation Guide
/**
* POST TITLE: Implementing LaunchDarkly Feature Flags in Java
* 
* Comprehensive guide to using LaunchDarkly Java SDK for feature management
*/
import com.launchdarkly.sdk.*;
import com.launchdarkly.sdk.server.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class LaunchDarklyDemo {
private static LDClient ldClient;
private static final String SDK_KEY = "sdk-12345678-1234-1234-1234-123456789012";
public static void main(String[] args) {
initializeLaunchDarkly();
demonstrateFeatureFlags();
demonstrateUserTargeting();
demonstrateCustomEvents();
cleanup();
}
/**
* Initialize LaunchDarkly client
*/
public static void initializeLaunchDarkly() {
try {
LDConfig config = new LDConfig.Builder()
.events(
Components.sendEvents()
.flushInterval(3000) // Flush events every 3 seconds
)
.logging(
Components.logging().level(com.launchdarkly.logging.LDLogLevel.INFO)
)
.build();
ldClient = new LDClient(SDK_KEY, config);
System.out.println("✅ LaunchDarkly client initialized successfully");
} catch (Exception e) {
System.err.println("❌ Failed to initialize LaunchDarkly client: " + e.getMessage());
}
}
/**
* Demonstrate basic feature flag usage
*/
public static void demonstrateFeatureFlags() {
System.out.println("\n=== FEATURE FLAG DEMONSTRATION ===");
// Create a basic user context
LDUser user = new LDUser.Builder("user-12345")
.email("[email protected]")
.firstName("John")
.lastName("Doe")
.custom("plan", "premium")
.build();
// Check various types of feature flags
checkBooleanFlag(user, "new-ui-feature");
checkStringFlag(user, "theme-color");
checkNumericFlag(user, "max-search-results");
checkJsonFlag(user, "feature-config");
// Check flag with detailed evaluation
checkFlagWithDetail(user, "new-ui-feature");
}
/**
* Check boolean feature flag
*/
public static void checkBooleanFlag(LDUser user, String flagKey) {
boolean flagValue = ldClient.boolVariation(flagKey, user, false);
System.out.println("🔘 Boolean Flag '" + flagKey + "': " + flagValue);
if (flagValue) {
System.out.println("   → New feature enabled for user: " + user.getKey());
} else {
System.out.println("   → Using default/old behavior for user: " + user.getKey());
}
}
/**
* Check string feature flag
*/
public static void checkStringFlag(LDUser user, String flagKey) {
String flagValue = ldClient.stringVariation(flagKey, user, "blue");
System.out.println("🔘 String Flag '" + flagKey + "': " + flagValue);
}
/**
* Check numeric feature flag
*/
public static void checkNumericFlag(LDUser user, String flagKey) {
int flagValue = ldClient.intVariation(flagKey, user, 10);
System.out.println("🔘 Numeric Flag '" + flagKey + "': " + flagValue);
}
/**
* Check JSON feature flag
*/
public static void checkJsonFlag(LDUser user, String flagKey) {
LDValue defaultConfig = LDValue.buildObject()
.put("enabled", false)
.put("threshold", 50)
.put("message", "default")
.build();
LDValue config = ldClient.jsonValueVariation(flagKey, user, defaultConfig);
System.out.println("🔘 JSON Flag '" + flagKey + "': " + config.toJsonString());
}
/**
* Check flag with detailed evaluation information
*/
public static void checkFlagWithDetail(LDUser user, String flagKey) {
EvaluationDetail<Boolean> detail = ldClient.boolVariationDetail(flagKey, user, false);
System.out.println("\n📊 Detailed Evaluation for '" + flagKey + "':");
System.out.println("   Value: " + detail.getValue());
System.out.println("   Variation Index: " + detail.getVariationIndex());
System.out.println("   Reason: " + detail.getReason());
}
/**
* Demonstrate user targeting and segmentation
*/
public static void demonstrateUserTargeting() {
System.out.println("\n=== USER TARGETING DEMONSTRATION ===");
// Different user types
LDUser[] users = {
// Premium user from US
new LDUser.Builder("premium-user-001")
.email("[email protected]")
.country("US")
.custom("plan", "premium")
.custom("signupDate", "2024-01-15")
.build(),
// Free user from EU
new LDUser.Builder("free-user-001")
.email("[email protected]")
.country("DE")
.custom("plan", "free")
.custom("signupDate", "2024-03-01")
.build(),
// Beta tester
new LDUser.Builder("beta-tester-001")
.email("[email protected]")
.custom("betaTester", true)
.custom("plan", "premium")
.build()
};
String[] flagsToCheck = {"new-ui-feature", "advanced-search", "export-feature"};
for (LDUser user : users) {
System.out.println("\n👤 User: " + user.getKey() + 
" (Plan: " + user.getCustom("plan") + 
", Country: " + user.getCountry() + ")");
for (String flag : flagsToCheck) {
boolean isEnabled = ldClient.boolVariation(flag, user, false);
System.out.println("   " + flag + ": " + (isEnabled ? "✅" : "❌"));
}
}
}
/**
* Demonstrate tracking custom events
*/
public static void demonstrateCustomEvents() {
System.out.println("\n=== CUSTOM EVENTS DEMONSTRATION ===");
LDUser user = new LDUser.Builder("user-999")
.email("[email protected]")
.custom("plan", "premium")
.build();
// Track a feature flag evaluation
boolean searchEnabled = ldClient.boolVariation("advanced-search", user, false);
ldClient.track("search-feature-evaluated", user, LDValue.of(searchEnabled));
// Track custom conversion events
if (searchEnabled) {
ldClient.track("advanced-search-used", user, 
LDValue.buildObject()
.put("searchTerm", "java sdk")
.put("resultsCount", 15)
.build());
System.out.println("📊 Tracked advanced search usage for user: " + user.getKey());
}
// Track revenue event
ldClient.track("purchase-completed", user, 
LDValue.buildObject()
.put("product", "enterprise-plan")
.put("amount", 299.99)
.put("currency", "USD")
.build());
System.out.println("💰 Tracked purchase event for user: " + user.getKey());
}
/**
* Advanced: Feature flag manager class for real-world usage
*/
public static class FeatureFlagManager {
private LDClient client;
public FeatureFlagManager(LDClient client) {
this.client = client;
}
public boolean isFeatureEnabled(String featureKey, LDUser user) {
return client.boolVariation(featureKey, user, false);
}
public String getFeatureString(String featureKey, LDUser user, String defaultValue) {
return client.stringVariation(featureKey, user, defaultValue);
}
public int getFeatureInt(String featureKey, LDUser user, int defaultValue) {
return client.intVariation(featureKey, user, defaultValue);
}
public Map<String, Boolean> getFeatureStates(LDUser user, String... featureKeys) {
Map<String, Boolean> states = new HashMap<>();
for (String key : featureKeys) {
states.put(key, isFeatureEnabled(key, user));
}
return states;
}
public void trackFeatureUsage(String eventName, LDUser user, String featureKey, boolean enabled) {
client.track(eventName, user, 
LDValue.buildObject()
.put("feature", featureKey)
.put("enabled", enabled)
.put("timestamp", System.currentTimeMillis())
.build());
}
}
/**
* Example usage in a web application context
*/
public static class UserService {
private FeatureFlagManager flagManager;
public UserService(FeatureFlagManager flagManager) {
this.flagManager = flagManager;
}
public void processUserRegistration(String userId, String email, String country) {
LDUser user = new LDUser.Builder(userId)
.email(email)
.country(country)
.custom("registrationDate", java.time.LocalDate.now().toString())
.build();
// Check feature flags for new user
boolean showWelcomeBonus = flagManager.isFeatureEnabled("welcome-bonus", user);
String theme = flagManager.getString("ui-theme", user, "light");
int maxStorage = flagManager.getFeatureInt("max-storage-mb", user, 100);
System.out.println("\n🎯 Processing registration for: " + email);
System.out.println("   Welcome Bonus: " + (showWelcomeBonus ? "✅" : "❌"));
System.out.println("   UI Theme: " + theme);
System.out.println("   Max Storage: " + maxStorage + "MB");
// Track the registration event
flagManager.trackFeatureUsage("user-registered", user, "registration-flow", true);
}
}
/**
* Clean up resources
*/
public static void cleanup() {
if (ldClient != null) {
try {
ldClient.flush();
ldClient.close();
System.out.println("\n✅ LaunchDarkly client closed successfully");
} catch (IOException e) {
System.err.println("❌ Error closing LaunchDarkly client: " + e.getMessage());
}
}
}
}

Maven Dependency

<!-- pom.xml -->
<dependencies>
<dependency>
<groupId>com.launchdarkly</groupId>
<artifactId>launchdarkly-java-server-sdk</artifactId>
<version>6.3.0</version>
</dependency>
</dependencies>

Configuration Class

/**
* Configuration class for LaunchDarkly setup
*/
public class LaunchDarklyConfig {
@Value("${launchdarkly.sdk.key:}")
private String sdkKey;
@Value("${launchdarkly.environment:production}")
private String environment;
@Bean
public LDClient ldClient() {
if (sdkKey == null || sdkKey.trim().isEmpty()) {
// Return a mock client for local development
return createMockClient();
}
LDConfig config = new LDConfig.Builder()
.events(Components.sendEvents().flushInterval(5000))
.logging(Components.logging().level(com.launchdarkly.logging.LDLogLevel.WARN))
.build();
return new LDClient(sdkKey, config);
}
@Bean
public FeatureFlagManager featureFlagManager(LDClient ldClient) {
return new FeatureFlagManager(ldClient);
}
private LDClient createMockClient() {
System.out.println("⚠️  Using mock LaunchDarkly client - feature flags will return default values");
// In a real implementation, you might use a test LDClient or mock
return null; // Simplified for example
}
}

This implementation provides:

  1. SDK Initialization with proper configuration
  2. Multiple Flag Types (boolean, string, numeric, JSON)
  3. User Targeting based on attributes and custom properties
  4. Custom Event Tracking for analytics
  5. Production-ready Manager Class for easy integration
  6. Proper Resource Cleanup to prevent memory leaks

The code follows LaunchDarkly best practices and can be easily integrated into Spring Boot applications or other Java frameworks.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper