Skip to content

Commit 14c3b7e

Browse files
authored
add Java Feature Flags SDK (#2181)
1 parent 1924504 commit 14c3b7e

File tree

5 files changed

+230
-1
lines changed

5 files changed

+230
-1
lines changed

cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@
243243
"Signup",
244244
"Signups",
245245
"skus",
246+
"Sonatype",
247+
"Sonatype's",
246248
"splitlines",
247249
"SPRT",
248250
"Stackdriver",

pages/docs/featureflags.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ See our developer guides on implementing feature flags on these platforms below:
198198
<Cards.Card icon title="iOS" href="/docs/tracking-methods/sdks/swift/swift-flags" />
199199
<Cards.Card icon title="Android" href="/docs/tracking-methods/sdks/android/android-flags" />
200200
<Cards.Card icon title="Python" href="/docs/tracking-methods/sdks/python/python-flags" />
201+
<Cards.Card icon title="Java" href="/docs/tracking-methods/sdks/java/java-flags" />
201202
</Cards>
202203

203-
Coming soon: React Native, Java, Ruby, Node.js, Go
204+
Coming soon: React Native, Ruby, Node.js, Go
204205

205206
<Callout type="info">
206207
If you'd like to see Feature Flags availability in other SDKs, please [reach out to the Support team](https://mixpanel.com/get-support).
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
"index": "Java",
3+
"java-flags": "Feature Flags (Java)",
4+
}
File renamed without changes.
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import { Callout } from "nextra/components";
2+
3+
# Implement Feature Flags (Java)
4+
5+
<Callout type="info">
6+
The Java feature flags implementation is currently in Beta.
7+
</Callout>
8+
9+
## Overview
10+
11+
This developer guide will assist you in configuring your server-side Java platform for [Feature Flags](/docs/featureflags) using the [Mixpanel Java SDK](/docs/tracking-methods/sdks/java). Feature Flags allow you to control the rollout of your features, conduct A/B testing, and manage application behavior without deploying new code.
12+
13+
## Prerequisites
14+
15+
Before implementing [Feature Flags](/docs/featureflags), ensure:
16+
17+
- You are on an Enterprise subscription plan and have the appropriate version of the SDK installed (minimum supported version is `1.6.0-SNAPSHOT`). If not, please follow [this doc](/docs/quickstart/install-mixpanel) to install the SDK.
18+
- You have your Project Token from your [Mixpanel Project Settings](/docs/orgs-and-projects/managing-projects#find-your-project-tokens)
19+
20+
<Callout type="info">
21+
The Java Feature Flags SDK is currently in Beta and uses a `-SNAPSHOT` version (`1.6.0-SNAPSHOT`). You'll need to configure your build tool to pull snapshot versions from Sonatype's snapshot repository. See the [Sonatype snapshot documentation](https://central.sonatype.org/publish/publish-portal-snapshots/) for instructions on configuring Maven or Gradle.
22+
</Callout>
23+
24+
## Flag Evaluation Modes
25+
26+
There are two modes available for using the Java SDK for feature flagging: Local Evaluation and Remote Evaluation.
27+
28+
For local evaluation, the SDK will poll Mixpanel servers for feature flag configurations. Assignment of user contexts to variants will be done locally within the SDK. This mode is recommended for low latency since there is no network call made at assignment time.
29+
30+
For remote evaluation, the SDK will make a network call to Mixpanel servers at assignment time. This mode is recommended for use cases where you want to leverage Mixpanel cohorts for user targeting or sticky variants for persistent variant assignments.
31+
32+
## Local Evaluation
33+
34+
<Callout type="warning">
35+
Targeting by Mixpanel cohorts and sticky variants are not supported in Local
36+
Evaluation mode.
37+
</Callout>
38+
39+
- The SDK is configured with a `LocalFlagsConfig` object that specifies parameters:
40+
41+
1. `apiHost` - If your project is in the EU/IN region, this should be set to route to `api-eu.mixpanel.com`/`api-in.mixpanel.com` respectively.
42+
2. `enablePolling` - This should be set to `true` to enable local evaluation.
43+
3. `pollingIntervalSeconds` - This is the interval in seconds at which the SDK will poll Mixpanel servers for feature flag configurations.
44+
45+
- The SDK will continue to poll for the lifetime of the SDK instance or until stopped.
46+
47+
```java
48+
import com.mixpanel.mixpanelapi.MixpanelAPI;
49+
import com.mixpanel.mixpanelapi.featureflags.config.LocalFlagsConfig;
50+
import java.util.HashMap;
51+
import java.util.Map;
52+
53+
// Configure local flags
54+
LocalFlagsConfig localConfig = LocalFlagsConfig.builder()
55+
.projectToken("YOUR_PROJECT_TOKEN")
56+
.apiHost("api.mixpanel.com")
57+
.enablePolling(true)
58+
.pollingIntervalSeconds(60)
59+
.requestTimeoutSeconds(10)
60+
.build();
61+
62+
// Initialize MixpanelAPI
63+
MixpanelAPI mixpanel = new MixpanelAPI(localConfig);
64+
65+
// Start polling for flag definitions
66+
mixpanel.getLocalFlags().startPollingForDefinitions();
67+
68+
// This should be the 'key' of the feature flag from Mixpanel's UX.
69+
String flagKey = "sample-flag";
70+
71+
// This is the fallback variant to return if the user context is not in a rollout group for the flag.
72+
String fallbackVariant = "control";
73+
74+
// Current user context for evaluation.
75+
// At minimum, this needs to include the user's distinct_id.
76+
// If any of your feature flags use a Variant Assignment Key other than 'distinct_id', this should also include those keys for evaluation. For example, 'company_id' below
77+
// If any of your feature flags use Runtime targeting, this should also include 'custom_properties' for evaluation
78+
Map<String, Object> userContext = new HashMap<>();
79+
userContext.put("distinct_id", "1234");
80+
userContext.put("company_id", "X");
81+
82+
Map<String, Object> customProperties = new HashMap<>();
83+
customProperties.put("platform", "java");
84+
userContext.put("custom_properties", customProperties);
85+
86+
// Get variant value for the flag
87+
String variantValue = mixpanel.getLocalFlags().getVariantValue(flagKey, fallbackVariant, userContext);
88+
89+
// Check if flag is enabled (boolean check)
90+
boolean isEnabled = mixpanel.getLocalFlags().isEnabled(flagKey, userContext);
91+
92+
// Clean up resources when done
93+
mixpanel.close();
94+
```
95+
96+
## Remote Evaluation
97+
98+
- The SDK is configured with a `RemoteFlagsConfig` object to use remote evaluation.
99+
100+
```java
101+
import com.mixpanel.mixpanelapi.MixpanelAPI;
102+
import com.mixpanel.mixpanelapi.featureflags.config.RemoteFlagsConfig;
103+
import java.util.HashMap;
104+
import java.util.Map;
105+
106+
// Configure remote flags
107+
RemoteFlagsConfig remoteConfig = RemoteFlagsConfig.builder()
108+
.projectToken("YOUR_PROJECT_TOKEN")
109+
.apiHost("api.mixpanel.com")
110+
.requestTimeoutSeconds(5)
111+
.build();
112+
113+
// Initialize MixpanelAPI
114+
MixpanelAPI mixpanel = new MixpanelAPI(remoteConfig);
115+
116+
// Context for evaluation
117+
Map<String, Object> userContext = new HashMap<>();
118+
userContext.put("distinct_id", "user-123");
119+
120+
Map<String, Object> customProperties = new HashMap<>();
121+
customProperties.put("platform", "java");
122+
userContext.put("custom_properties", customProperties);
123+
124+
String flagKey = "sample-flag";
125+
String fallbackVariant = "control";
126+
127+
// getVariantValue usage is the same as for local evaluation, but will make a network call to Mixpanel servers at assignment time.
128+
String variantValue = mixpanel.getRemoteFlags().getVariantValue(flagKey, fallbackVariant, userContext);
129+
System.out.println("Variant value: " + variantValue);
130+
131+
// Check if flag is enabled (boolean check)
132+
boolean isEnabled = mixpanel.getRemoteFlags().isEnabled(flagKey, userContext);
133+
134+
// Clean up resources when done
135+
mixpanel.close();
136+
```
137+
138+
## Configuration Options
139+
140+
### LocalFlagsConfig Builder Options
141+
142+
- `projectToken(String)` - Your Mixpanel project token (required)
143+
- `apiHost(String)` - API host without protocol (default: `"api.mixpanel.com"`)
144+
- For EU region: `"api-eu.mixpanel.com"`
145+
- For India region: `"api-in.mixpanel.com"`
146+
- `enablePolling(boolean)` - Whether to enable automatic polling (default: `true`)
147+
- `pollingIntervalSeconds(int)` - Polling interval in seconds (default: `60`)
148+
- `requestTimeoutSeconds(int)` - Request timeout in seconds (default: `10`)
149+
150+
### RemoteFlagsConfig Builder Options
151+
152+
- `projectToken(String)` - Your Mixpanel project token (required)
153+
- `apiHost(String)` - API host without protocol (default: `"api.mixpanel.com"`)
154+
- For EU region: `"api-eu.mixpanel.com"`
155+
- For India region: `"api-in.mixpanel.com"`
156+
- `requestTimeoutSeconds(int)` - Request timeout in seconds (default: `5`)
157+
158+
## Additional Methods
159+
160+
### Evaluating All Flags
161+
162+
You can evaluate all flags at once using the `getAllVariants()` method:
163+
164+
```java
165+
import com.mixpanel.mixpanelapi.MixpanelAPI;
166+
import com.mixpanel.mixpanelapi.featureflags.config.LocalFlagsConfig;
167+
import com.mixpanel.mixpanelapi.featureflags.model.SelectedVariant;
168+
import java.util.HashMap;
169+
import java.util.List;
170+
import java.util.Map;
171+
172+
LocalFlagsConfig config = LocalFlagsConfig.builder()
173+
.projectToken("YOUR_PROJECT_TOKEN")
174+
.build();
175+
176+
MixpanelAPI mixpanel = new MixpanelAPI(config);
177+
mixpanel.getLocalFlags().startPollingForDefinitions();
178+
179+
Map<String, Object> userContext = new HashMap<>();
180+
userContext.put("distinct_id", "user-123");
181+
182+
// Evaluate all flags at once
183+
List<SelectedVariant<Object>> allVariants = mixpanel.getLocalFlags().getAllVariants(userContext, true);
184+
185+
for (SelectedVariant<Object> variant : allVariants) {
186+
if (variant.isSuccess()) {
187+
System.out.println("Flag: " + variant.getVariantKey() + " = " + variant.getVariantValue());
188+
}
189+
}
190+
191+
// Clean up resources when done
192+
mixpanel.close();
193+
```
194+
195+
## Best Practices
196+
197+
### Context Management
198+
199+
- Always include `distinct_id` in your user context
200+
- Include any custom properties used in your flag targeting rules
201+
- Use consistent data types for context values across your application
202+
203+
### Resource Management
204+
205+
- Initialize the `MixpanelAPI` once and reuse it throughout your application
206+
- Always call `close()` when shutting down to stop polling and release resources:
207+
208+
```java
209+
MixpanelAPI mixpanel = new MixpanelAPI(config);
210+
try {
211+
// Use mixpanel here
212+
} finally {
213+
mixpanel.close(); // Stops polling and releases resources
214+
}
215+
```
216+
217+
- For local evaluation, remember to start polling with `startPollingForDefinitions()`
218+
- For local evaluation, you can also explicitly stop polling with `stopPollingForDefinitions()`:
219+
220+
```java
221+
mixpanel.getLocalFlags().stopPollingForDefinitions();
222+
```

0 commit comments

Comments
 (0)