Files
posthog.com/contents/docs/libraries/java/index.mdx
Dustin Byrne 01c1e6f0ce docs(sdk): Update Java SDK documentation (#12992)
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-09-30 23:19:12 +00:00

238 lines
8.3 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Java
sidebarTitle: Java
sidebar: Docs
showTitle: true
github: 'https://github.com/PostHog/posthog-android'
icon: >-
https://res.cloudinary.com/dmukukwp6/image/upload/posthog.com/contents/images/docs/integrate/java.svg
features:
eventCapture: true
userIdentification: true
featureFlags: true
groupAnalytics: true
surveys: false
llmAnalytics: false
---
This is an optional library you can install if you're working with server-side Java applications. It uses an internal queue to make calls fast and non-blocking. It also batches requests and flushes asynchronously, making it perfect to use in any part of your web app or other server side application that needs performance.
## Installation
import JavaInstall from '../../integrate/_snippets/install-java.mdx'
<JavaInstall />
## Capturing events
import JavaSendEvents from '../../integrate/send-events/_snippets/send-events-java.mdx'
<JavaSendEvents />
## Person profiles and properties
The Java SDK captures identified events by default. These create [person profiles](/docs/data/persons). To set [person properties](/docs/data/user-properties) in these profiles, include them when capturing an event:
```java
postHog.capture(
"distinct_id_of_the_user",
"event_name",
PostHogCaptureOptions
.builder()
.userProperty("name", "Max Hedgehog")
.userPropertySetOnce("initial_url", "/blog")
.build()
);
```
For more details on the difference between `$set` and `$set_once`, see our [person properties docs](/docs/data/user-properties#what-is-the-difference-between-set-and-set_once).
To capture [anonymous events](/docs/data/anonymous-vs-identified-events) without person profiles, set the event's `$process_person_profile` property to `false`:
```java
postHog.capture(
"distinct_id_of_the_user",
"event_name",
PostHogCaptureOptions
.builder()
.property("$process_person_profile", false)
.build()
);
```
## Alias
Sometimes, you want to assign multiple distinct IDs to a single user. This is helpful when your primary distinct ID is inaccessible. For example, if a distinct ID used on the frontend is not available in your backend.
In this case, you can use `alias` to assign another distinct ID to the same user.
```java
postHog.alias("distinct_id", "alias_id");
```
We strongly recommend reading our docs on [alias](/docs/data/identify#alias-assigning-multiple-distinct-ids-to-the-same-user) to best understand how to correctly use this method.
## Group analytics
Group analytics allows you to associate an event with a group (e.g. teams, organizations, etc.). Read the [group analytics](/docs/product-analytics/group-analytics) guide for more information.
> **Note:** This is a paid feature and is not available on the open-source or free cloud plan. Learn more on our [pricing page](/pricing).
To create a group, use the `group` method. This associates a user with a group and optionally sets properties on the group:
```java
postHog.group(
"user_distinct_id",
"company",
"company_id_in_your_db",
Map.of(
"name", "Acme Corporation",
"industry", "Technology",
"employee_count", 500
)
);
```
You can also create a group without setting properties:
```java
postHog.group("user_distinct_id", "organization", "org_123");
```
To associate an event with a group, include the group information when capturing the event:
```java
postHog.capture(
"user_distinct_id",
"some_event",
PostHogCaptureOptions
.builder()
.group("company", "company_id_in_your_db")
.build()
);
```
## Feature flags
import FeatureFlagsLibsIntro from "../_snippets/feature-flags-libs-intro.mdx"
<FeatureFlagsLibsIntro />
### Boolean feature flags
```java
boolean isEnabled = postHog.isFeatureEnabled("user_distinct_id", "use_optimized_query", false);
if (isEnabled) {
// Do something differently for this user
}
```
### Multivariate feature flags
```java
Object flagValue = postHog.getFeatureFlag("user_distinct_id", "recommendation_algorithm", "control");
String algorithm = flagValue instanceof String ? (String) flagValue : "control";
switch (algorithm) {
case "collaborative_filtering":
useCollaborativeFiltering();
break;
case "neural_network":
useNeuralNetwork();
break;
default:
useControlAlgorithm();
}
```
### Feature flag payloads
```java
Object payload = postHog.getFeatureFlagPayload("user_distinct_id", "recommendation_algorithm");
if (payload instanceof Map) {
Map<String, Object> config = (Map<String, Object>) payload;
String modelVersion = config.get("model_version") instanceof String
? (String) config.get("model_version") : "v1.0";
boolean enableFallback = config.get("enable_fallback") instanceof Boolean
? (Boolean) config.get("enable_fallback") : true;
}
```
### Sending `$feature_flag_called` events
Capturing `$feature_flag_called` events enable PostHog to know when a flag was accessed by a user and thus provide [analytics and insights](/docs/product-analytics/insights) on the flag. By default, we send these events when:
1. You call `postHog.getFeatureFlag()` or `postHog.isFeatureEnabled()`, AND
2. It's a new user, or the value of the flag has changed.
> *Note:* Tracking whether it's a new user or if a flag value has changed happens in a local cache. This means that if you reinitialize the PostHog client, the cache resets as well causing `$feature_flag_called` events to be sent again when calling `getFeatureFlag` or `isFeatureEnabled`. PostHog is built to handle this, and so duplicate `$feature_flag_called` events won't affect your analytics.
You can control the automatic capture of `$feature_flag_called` events using the `sendFeatureFlagEvent` configuration option when initializing PostHog:
```java
PostHogConfig config = PostHogConfig
.builder(POSTHOG_API_KEY)
.host(POSTHOG_HOST)
.sendFeatureFlagEvent(false) // Disable automatic feature flag events
.build();
```
### Local evaluation
While planned, local evaluation of feature flags is not yet supported in the Java SDK. All feature flag evaluations occur remotely via the PostHog API.
### Feature flag caching
To improve performance and reduce API calls, the Java SDK caches feature flag results in memory. You can configure the cache behavior when initializing PostHog:
```java
PostHogConfig config = PostHogConfig
.builder(POSTHOG_API_KEY)
.featureFlagCacheSize(1000) // Maximum number of cached flag results (default: 1000)
.featureFlagCacheMaxAgeMs(300000) // Cache expiry in milliseconds (default: 300000 = 5 minutes)
.build();
```
**Configuration options:**
- `featureFlagCacheSize`: The maximum number of feature flag results to cache in memory (default: `1000`)
- `featureFlagCacheMaxAgeMs`: The maximum age of a cached feature flag result in milliseconds (default: `300000` or 5 minutes)
Cached results are stored per distinct ID and flag key combination. When a cached result expires or the cache is full, the SDK will fetch fresh results from the PostHog API.
## Experiments (A/B tests)
Since [experiments](/docs/experiments/manual) use feature flags, the code for running an experiment is very similar to the feature flags code:
```java
Object flagValue = postHog.getFeatureFlag("user_distinct_id", "recommendation_algorithm", "control");
String variant = flagValue instanceof String ? (String) flagValue : "control";
if (variant.equals("neural_network")) {
// Do something differently for this user
}
```
It's also possible to [run experiments without using feature flags](/docs/experiments/running-experiments-without-feature-flags).
## GeoIP properties
The `posthog-server` library disregards the server IP, does not add the GeoIP properties, and does not use the values for feature flag evaluations.
## Serverless environments
By default, the library buffers events before sending them to the `/batch` endpoint for better performance. This can lead to lost events in serverless environments if the Java process is terminated by the platform before the buffer is fully flushed.
To avoid this, call `postHog.flush()` after processing every request. This allows `postHog.capture()` to remain asynchronous for better performance.
```java
postHog.flush();
```
## Shutdown
When you're done using PostHog, make sure to call `close()` to ensure all events are flushed before your application exits:
```java
postHog.close();
```