Migrating from Legacy Java SDK to Java Core
This guide will help you migrate from the legacy Java/Kotlin Server SDK to the new Java Core SDK. The Java Core SDK offers significant performance improvements and new features, as it's built on a shared Rust core library.
Why Migrate?
- Performance: Java Core evaluates 3-5x faster than the legacy SDK
- New Features: Access to Parameter Stores, CMAB (Contextual Multi-Armed Bandits), observabilityClient, and more
- Future Support: All new features and improvements will only be available in Java Core
- Maintenance: The legacy Java SDK is in maintenance mode and will only receive critical bug fixes
Installation Differences
Legacy Java/Kotlin SDK
- Gradle
- Maven
repositories {
mavenCentral()
}
dependencies {
implementation 'com.statsig:serversdk:X.X.X'
}
<dependencies>
<dependency>
<groupId>com.statsig</groupId>
<artifactId>serversdk</artifactId>
<version>X.X.X</version>
</dependency>
</dependencies>
Java Core SDK
Java Core requires both the core library and a platform-specific native library:
- Gradle
- Maven
repositories {
mavenCentral()
}
dependencies {
// Core library (required)
implementation 'com.statsig:javacore:X.X.X'
// Platform-specific library (required)
implementation 'com.statsig:javacore:X.X.X:YOUR-OS-ARCHITECTURE'
}
<dependencies>
<!-- Core library (required) -->
<dependency>
<groupId>com.statsig</groupId>
<artifactId>javacore</artifactId>
<version>X.X.X</version>
</dependency>
<!-- Platform-specific library (required) -->
<dependency>
<groupId>com.statsig</groupId>
<artifactId>javacore</artifactId>
<version>X.X.X</version>
<classifier>YOUR-OS-ARCHITECTURE</classifier>
</dependency>
</dependencies>
To determine the correct platform-specific dependency, you can run this code:
import com.statsig.*;
StatsigOptions options = new StatsigOptions.Builder().build();
Statsig statsig = new Statsig("your-secret-key", options);
This will output the appropriate dependency for your system.
API Differences
Key Package and Class Changes
Feature | Legacy Java SDK | Java Core SDK |
---|---|---|
Package | com.statsig.sdk.* | com.statsig.* |
Main Class | Statsig (static methods) | Statsig (instance methods) |
Options | StatsigOptions | StatsigOptions.Builder() |
User | StatsigUser | StatsigUser.Builder() |
Check Gate | Statsig.checkGateSync() | statsig.checkGate() |
Get Config | Statsig.getConfigSync() | statsig.getDynamicConfig() |
Get Experiment | Statsig.getExperimentSync() | statsig.getExperiment() |
Get Layer | Statsig.getLayerSync() | statsig.getLayer() |
Log Event | Statsig.logEvent() | statsig.logEvent() |
Initialization
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
import com.statsig.sdk.Statsig;
StatsigOptions options = new StatsigOptions();
// Customize options as needed
// options.initTimeoutMs = 9999;
Future initFuture = Statsig.initializeAsync("server-secret-key", options);
initFuture.get();
import com.statsig.sdk.Statsig
val options = StatsigOptions().apply {
// Customize options as needed
initTimeoutMs = 9999
}
async { Statsig.initialize("server-secret-key", options) }.await()
import com.statsig.*;
// All StatsigOptions are optional
StatsigOptions options = new StatsigOptions.Builder()
.setSpecsSyncIntervalMs(10000)
.setEventLoggingFlushIntervalMs(10000)
.setOutputLoggerLevel(OutputLogger.LogLevel.INFO)
.build();
Statsig statsig = new Statsig("server-secret-key", options);
statsig.initialize().get();
Checking Gates
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
StatsigUser user = new StatsigUser("user_id");
Boolean isFeatureOn = Statsig.checkGateSync(user, "use_new_feature");
if (isFeatureOn) {
// Gate is on, use new feature
} else {
// Gate is off
}
val user = StatsigUser("user_id")
val featureOn = Statsig.checkGateSync(user, "use_new_feature")
if (featureOn) {
// Gate is on, use new feature
} else {
// Gate is off
}
StatsigUser user = new StatsigUser.Builder().setUserID("user_id").build();
boolean isFeatureOn = statsig.checkGate(user, "use_new_feature");
if (isFeatureOn) {
// Gate is on, use new feature
} else {
// Gate is off
}
Getting Configs
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
DynamicConfig config = Statsig.getConfigSync(user, "awesome_product_details");
String itemName = config.getString("product_name", "Awesome Product v1");
Double price = config.getDouble("price", 10.0);
Boolean shouldDiscount = config.getBoolean("discount", false);
val config = Statsig.getConfigSync(user, "awesome_product_details")
val itemName = config.getString("product_name", "Awesome Product v1")
val price = config.getDouble("price", 10.0)
val shouldDiscount = config.getBoolean("discount", false)
DynamicConfig config = statsig.getDynamicConfig(user, "awesome_product_details");
String itemName = config.getString("product_name", "Awesome Product v1");
Double price = config.getDouble("price", 10.0);
Boolean shouldDiscount = config.getBoolean("discount", false);
Getting Experiments
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
DynamicConfig experiment = Statsig.getExperimentSync(user, "new_user_promo_title");
String promoTitle = experiment.getString("title", "Welcome to Statsig!");
Double discount = experiment.getDouble("discount", 0.1);
val experiment = Statsig.getExperimentSync(user, "new_user_promo_title")
val promoTitle = experiment.getString("title", "Welcome to Statsig!")
val discount = experiment.getDouble("discount", 0.1)
Experiment experiment = statsig.getExperiment(user, "new_user_promo_title");
String promoTitle = experiment.getString("title", "Welcome to Statsig!");
Double discount = experiment.getDouble("discount", 0.1);
Getting Layers
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
Layer layer = Statsig.getLayerSync(user, "user_promo_experiments");
String promoTitle = layer.getString("title", "Welcome to Statsig!");
Double discount = layer.getDouble("discount", 0.1);
val layer = Statsig.getLayerSync(user, "user_promo_experiments")
val promoTitle = layer.getString("title", "Welcome to Statsig!")
val discount = layer.getDouble("discount", 0.1)
Layer layer = statsig.getLayer(user, "user_promo_experiments");
String promoTitle = layer.getString("title", "Welcome to Statsig!");
Double discount = layer.getDouble("discount", 0.1);
Logging Events
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
Statsig.logEvent(user, "purchase", 2.99, Map.of("item_name", "remove_ads"));
Statsig.logEvent(user, "purchase", 2.99, mapOf("item_name" to "remove_ads"))
Map<String, String> metadata = new HashMap<>();
metadata.put("item_name", "remove_ads");
statsig.logEvent(user, "purchase", "2.99", metadata);
Configuration Options Differences
- Legacy Java SDK
- Legacy Kotlin SDK
- Java Core SDK
StatsigOptions options = new StatsigOptions();
options.setInitTimeoutMs(3000);
options.setTier("staging");
options.setLocalMode(false);
options.setApi("https://api.statsig.com/v1");
options.setRulesetsSyncIntervalMs(10 * 1000);
options.setIdListsSyncIntervalMs(60 * 1000);
options.setDisableAllLogging(false);
val options = StatsigOptions().apply {
initTimeoutMs(3000)
disableAllLogging(false)
}
StatsigOptions options = new StatsigOptions.Builder()
.setInitTimeoutMs(3000)
.setEnvironment("staging")
.setDisableNetwork(false) // Replaces localMode
.setSpecsUrl("https://api.statsig.com/v1")
.setSpecsSyncIntervalMs(10 * 1000)
.setIdListsSyncIntervalMs(60 * 1000)
.setDisableAllLogging(false)
.build();
Migration Steps
- Java Migration
- Kotlin Migration
-
Update Dependencies
- Replace
com.statsig:serversdk
withcom.statsig:javacore
- Add the platform-specific dependency
- Replace
-
Update Imports
- Replace
import com.statsig.sdk.*
withimport com.statsig.*
- Replace
-
Update Initialization
- Change from static methods to instance methods
- Use the builder pattern for options and StatsigUser
- Replace
new StatsigUser("user_id")
withnew StatsigUser.Builder().setUserID("user_id").build()
- Initialize with
new Statsig(key, options)
and callinitialize()
-
Update User Creation
- Use the builder pattern:
new StatsigUser.Builder().setUserID("user_id").build()
- Use the builder pattern:
-
Update Method Calls
- Replace static methods with instance methods
- Remove
Sync
suffix from method names - Update method signatures as needed
-
Test Thoroughly
- Verify all feature gates, experiments, and configs work as expected
- Check that event logging is functioning correctly
-
Update Dependencies
- Replace
com.statsig:serversdk
withcom.statsig:javacore
- Add the platform-specific dependency
- Replace
-
Update Imports
- Replace
import com.statsig.sdk.*
withimport com.statsig.*
- Replace
-
Update Initialization
- Change from static methods to instance methods
- Replace
.apply {}
blocks with the builder pattern - Replace
val user = StatsigUser("user_id")
withval user = StatsigUser.Builder().setUserID("user_id").build()
- Initialize with
val statsig = Statsig("key", options)
and callinitialize()
-
Update User Creation
- Use the builder pattern:
val user = StatsigUser.Builder().setUserID("user_id").build()
- Use the builder pattern:
-
Update Method Calls
- Replace static methods with instance methods
- Remove
Sync
suffix from method names - Update method signatures as needed
- Replace
mapOf("key" to "value")
with appropriate map creation methods
-
Test Thoroughly
- Verify all feature gates, experiments, and configs work as expected
- Check that event logging is functioning correctly
New Features in Java Core
Parameter Stores
Java Core introduces Parameter Stores, which allow you to manage parameters across multiple feature gates, experiments, and dynamic configs:
ParameterStore parameterStore = statsig.getParameterStore(user, "my_parameter_store");
String value = parameterStore.getString("parameter_name", "default_value");
Improved Performance
Java Core offers significantly better performance:
- Faster evaluation times
- More efficient network usage
- Reduced CPU usage
- Better memory management
Troubleshooting
Common Issues
-
Missing Platform-Specific Dependency
- Error:
java.lang.UnsatisfiedLinkError: no statsig_jni in java.library.path
- Solution: Add the correct platform-specific dependency
- Error:
-
Incompatible Method Calls
- Error:
java.lang.NoSuchMethodError
- Solution: Update method calls to match the new API
- Error:
-
Configuration Differences
- Issue: Features not evaluating as expected
- Solution: Verify options are correctly configured in the new format
Need Help?
If you encounter any issues during migration, please reach out to us: