Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 81 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
This is the official Mixpanel tracking library for Java.
This is the official Mixpanel tracking library for Java.

## Latest Version

Latest Version
--------------
##### _May 08, 2024_ - [v1.5.3](https://github.com/mixpanel/mixpanel-java/releases/tag/mixpanel-java-1.5.3)

```
<dependency>
<groupId>com.mixpanel</groupId>
Expand All @@ -13,8 +14,8 @@ Latest Version

You can alternatively download the library jar directly from Maven Central [here](https://central.sonatype.com/artifact/com.mixpanel/mixpanel-java).

How To Use
----------
## How To Use

The library is designed to produce events and people updates in one process or thread, and
consume the events and people updates in another thread or process. Specially formatted JSON objects
are built by `MessageBuilder` objects, and those messages can be consumed by the
Expand Down Expand Up @@ -42,17 +43,84 @@ Gzip compression can reduce bandwidth usage and improve performance, especially

The library supports importing historical events (events older than 5 days that are not accepted using /track) via the `/import` endpoint. Project token will be used for basic auth.

Learn More
----------
## Feature Flags

The Mixpanel Java SDK supports feature flags with both local and remote evaluation modes.

### Local Evaluation (Recommended)

Fast, low-latency flag checks with background polling for flag definitions:

```java
import com.mixpanel.mixpanelapi.*;
import com.mixpanel.mixpanelapi.featureflags.config.*;
import java.util.*;

// Initialize with your project token
LocalFlagsConfig config = LocalFlagsConfig.builder()
.projectToken("YOUR_PROJECT_TOKEN")
.pollingIntervalSeconds(60)
.build();

MixpanelAPI mixpanel = new MixpanelAPI(config);

// Start polling for flag definitions
mixpanel.getLocalFlags().startPollingForDefinitions();

// Wait for flags to be ready (optional but recommended)
while (!mixpanel.getLocalFlags().areFlagsReady()) {
Thread.sleep(100);
}

// Evaluate flags
Map<String, Object> context = new HashMap<>();
context.put("distinct_id", "user-123");

// Check if a feature is enabled
boolean isEnabled = mixpanel.getLocalFlags().isEnabled("new-feature", context);

// Get a variant value with fallback
String theme = mixpanel.getLocalFlags().getVariantValue("ui-theme", "light", context);

// Cleanup
mixpanel.close();
```

### Remote Evaluation

Real-time flag evaluation with server-side API calls:

```java
import com.mixpanel.mixpanelapi.*;
import com.mixpanel.mixpanelapi.featureflags.config.*;
import java.util.*;

RemoteFlagsConfig config = RemoteFlagsConfig.builder()
.projectToken("YOUR_PROJECT_TOKEN")
.build();

try (MixpanelAPI mixpanel = new MixpanelAPI(config)) {
Map<String, Object> context = new HashMap<>();
context.put("distinct_id", "user-456");

boolean isEnabled = mixpanel.getRemoteFlags().isEnabled("premium-features", context);
}
```

For complete feature flags documentation, configuration options, advanced usage, and best practices, see:

https://docs.mixpanel.com/docs/tracking-methods/sdks/java/java-flags

## Learn More

This library in particular has more in-depth documentation at

https://mixpanel.com/docs/integration-libraries/java

Mixpanel maintains documentation at

http://www.mixpanel.com/docs


The library also contains a simple demo application, that demonstrates
using this library in an asynchronous environment.

Expand All @@ -62,9 +130,9 @@ support for persistent properties, etc. Two interesting ones are at:

https://github.com/eranation/mixpanel-java
https://github.com/scalascope/mixpanel-java
Other Mixpanel Libraries
------------------------

## Other Mixpanel Libraries

Mixpanel also maintains a full-featured library for tracking events from Android apps at https://github.com/mixpanel/mixpanel-android

And a full-featured client side library for web applications, in Javascript, that can be loaded
Expand All @@ -73,8 +141,7 @@ directly from Mixpanel servers. To learn more about our Javascript library, see:
This library is intended for use in back end applications or API services that can't take
advantage of the Android libraries or the Javascript library.

License
-------
## License

```
See LICENSE File for details. The Base64Coder class used by this software
Expand Down
12 changes: 11 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>com.mixpanel</groupId>
<artifactId>mixpanel-java</artifactId>
<version>1.5.4</version>
<version>1.6.0-flags</version>
<packaging>jar</packaging>
<name>mixpanel-java</name>
<description>
Expand Down Expand Up @@ -50,6 +50,16 @@
</distributionManagement>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>

<plugins>
<!-- Central Publishing Maven Plugin for Maven Central Portal -->
<plugin>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.mixpanel.mixpanelapi.featureflags.demo;

import com.mixpanel.mixpanelapi.MixpanelAPI;
import com.mixpanel.mixpanelapi.featureflags.config.LocalFlagsConfig;
import com.mixpanel.mixpanelapi.featureflags.model.SelectedVariant;

import java.util.HashMap;
import java.util.Map;

/**
* Example demonstrating local feature flag evaluation.
*
* This example shows how to:
* 1. Configure and initialize a local flags client
* 2. Start polling for flag definitions
* 3. Evaluate flags with different contexts
* 4. Properly clean up resources
*/
public class LocalEvaluationExample {

public static void main(String[] args) throws Exception {
// Replace with your actual Mixpanel project token
String projectToken = "YOUR_PROJECT_TOKEN";

// 1. Configure local evaluation
LocalFlagsConfig config = LocalFlagsConfig.builder()
.projectToken(projectToken)
.apiHost("api.mixpanel.com") // Use "api-eu.mixpanel.com" for EU
.pollingIntervalSeconds(60) // Poll every 60 seconds
.enablePolling(true) // Enable background polling
.requestTimeoutSeconds(10) // 10 second timeout for HTTP requests
.build();

try (MixpanelAPI mixpanel = new MixpanelAPI(config)) {

// 2. Start polling for flag definitions
System.out.println("Starting flag polling...");
mixpanel.getLocalFlags().startPollingForDefinitions();

System.out.println("Waiting for flags to be ready...");
int retries = 0;
while (!mixpanel.getLocalFlags().areFlagsReady() && retries < 50) {
Thread.sleep(100);
retries++;
}

if (!mixpanel.getLocalFlags().areFlagsReady()) {
System.err.println("Warning: Flags not ready after 5 seconds, will use fallback values");
} else {
System.out.println("Flags are ready!");
}

// 3. Example 1: Simple boolean flag check
System.out.println("\n=== Example 1: Boolean Flag ===");
Map<String, Object> context1 = new HashMap<>();
context1.put("distinct_id", "user-123");

boolean newFeatureEnabled = mixpanel.getLocalFlags().isEnabled(
"new-checkout-flow",
context1
);

System.out.println("New checkout flow enabled: " + newFeatureEnabled);

// Example 2: String variant value
System.out.println("\n=== Example 2: String Variant ===");
String buttonColor = mixpanel.getLocalFlags().getVariantValue(
"button-color",
"blue", // fallback value
context1
);

System.out.println("Button color: " + buttonColor);

// Example 3: With custom properties for targeting
System.out.println("\n=== Example 3: Targeted Flag ===");
Map<String, Object> context2 = new HashMap<>();
context2.put("distinct_id", "user-456");

// Add custom properties for runtime evaluation
Map<String, Object> customProps = new HashMap<>();
customProps.put("subscription_tier", "premium");
customProps.put("country", "US");
context2.put("custom_properties", customProps);

boolean premiumFeatureEnabled = mixpanel.getLocalFlags().isEnabled(
"premium-analytics-dashboard",
context2
);

System.out.println("Premium analytics enabled: " + premiumFeatureEnabled);

// Example 4: Get full variant information
System.out.println("\n=== Example 4: Full Variant Info ===");
SelectedVariant<Object> variant = mixpanel.getLocalFlags().getVariant(
"recommendation-algorithm",
new SelectedVariant<>("default-algorithm"), // fallback
context1
);

if (variant.isSuccess()) {
System.out.println("Variant key: " + variant.getVariantKey());
System.out.println("Variant value: " + variant.getVariantValue());
} else {
System.out.println("Using fallback variant");
}

// Example 5: Number variant
System.out.println("\n=== Example 5: Number Variant ===");
Integer maxItems = mixpanel.getLocalFlags().getVariantValue(
"max-cart-items",
10, // fallback value
context1
);

System.out.println("Max cart items: " + maxItems);

System.out.println("\n=== Example Complete ===");
System.out.println("MixpanelAPI will be automatically closed");

// 4. Properly clean up resources
mixpanel.close();

}

System.out.println("Resources cleaned up successfully");
}
}
Loading
Loading