You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[Sticky features and variables](#sticky-features-and-variables)
29
28
-[Setting datafile](#setting-datafile)
30
29
-[Merging by default](#merging-by-default)
31
30
-[Replacing](#replacing)
@@ -38,7 +37,8 @@ This SDK supports Featurevisor v3 behavior and v2 datafiles. Generated datafiles
38
37
-[Events](#events)
39
38
-[`datafile_set`](#datafile_set)
40
39
-[`context_set`](#context_set)
41
-
-[`sticky_set`](#sticky_set)
40
+
-[`sticky_features_set`](#sticky_features_set)
41
+
-[`sticky_variables_set`](#sticky_variables_set)
42
42
-[`error`](#error)
43
43
-[Evaluation details](#evaluation-details)
44
44
-[Modules](#modules)
@@ -86,7 +86,7 @@ Add the Featurevisor Java SDK as a dependency with your desired version:
86
86
<dependency>
87
87
<groupId>com.featurevisor</groupId>
88
88
<artifactId>featurevisor-java</artifactId>
89
-
<version>3.0.0</version>
89
+
<version>4.0.0</version>
90
90
</dependency>
91
91
</dependencies>
92
92
```
@@ -136,7 +136,7 @@ Featurevisor f = Featurevisor.createFeaturevisor(
136
136
137
137
Most applications only need `Featurevisor.createFeaturevisor`, the `Featurevisor` instance type, and `Featurevisor.FeaturevisorOptions`. Public extension and observability types include `FeaturevisorModule`, `FeaturevisorDiagnostic`, and the datafile model types.
138
138
139
-
Concurrent evaluations are safe after an instance is configured. Do not call state-changing methods such as `setDatafile`, `setContext`, `setSticky`, `addModule`, `removeModule`, or `close` concurrently with evaluations or with each other. Apply those changes from a serialized update path. Module, event, and diagnostic callbacks must synchronize mutable state that they capture.
139
+
Concurrent evaluations are safe after an instance is configured. Do not call statechanging methods such as `setDatafile`, `setContext`, `setStickyFeatures`, `setStickyVariables`, `addModule`, `removeModule`, or `close` concurrently with evaluations or with each other. Apply those changes from a serialized update path. Module, event, and diagnostic callbacks must synchronize mutable state that they capture.
140
140
141
141
## Initialization
142
142
@@ -167,11 +167,12 @@ We will learn about several different options in the next sections.
167
167
168
168
## Evaluation types
169
169
170
-
We can evaluate 3 types of values against a particular [feature](https://featurevisor.com/docs/features/):
170
+
We can evaluate flags, variations, variables inside features, and [global variables](https://featurevisor.com/docs/global-variables/):
171
171
172
172
-[**Flag**](#check-if-enabled) (`boolean`): whether the feature is enabled or not
173
173
-[**Variation**](#getting-variation) (`Object`): the variation of the feature (if any)
174
174
-[**Variables**](#getting-variables): variable values of the feature (if any)
175
+
-[**Global variables**](#getting-global-variables): reusable values that are not owned by a feature
175
176
176
177
These evaluations are run against the provided context.
177
178
@@ -384,15 +385,29 @@ If a variable schema type is `json` and the resolved value is a malformed string
384
385
-`getVariableJSONNode(...)`
385
386
-`getVariableJSON(...)`
386
387
387
-
## Getting all evaluations
388
+
## Getting global variables
389
+
390
+
Global variables use the same overloaded methods as variables inside features. A call with one key evaluates a global variable, while a call with a feature key and variable key evaluates a variable owned by that feature:
The type specific methods are `getVariableBoolean`, `getVariableString`, `getVariableInteger`, `getVariableDouble`, `getVariableArray`, `getVariableObject`, and `getVariableJSON`.
399
+
400
+
Global variables resolve sticky values first, then required features, then the first matching override, and finally their default value. If required features are unmet, `disabledValue` is used unless `useDefaultWhenDisabled` is enabled. Caller defaults are only used when the evaluation itself has no value.
401
+
402
+
## Getting aggregate evaluations
388
403
389
404
You can get evaluations of all features available in the SDK instance:
This is handy especially when you want to pass all evaluations from a backend application to the frontend.
418
433
419
-
## Sticky
434
+
Global variables can be evaluated together as well:
420
435
421
-
For the lifecycle of the SDK instance in your application, you can set some features with sticky values, meaning that they will not be evaluated against the fetched [datafile](https://featurevisor.com/docs/building-datafiles/):
Sticky values belong to an SDK or child instance. Evaluation options do not accept sticky overrides; use `new Featurevisor.SpawnOptions().sticky(...)` when a child needs its own sticky state.
440
+
## Sticky features and variables
424
441
425
-
### Initialize with sticky
442
+
For the lifecycle of the SDK instance in your application, you can set some features with sticky values, meaning that they will not be evaluated against the fetched [datafile](https://featurevisor.com/docs/building-datafiles/):
443
+
444
+
Sticky values belong to an SDK or child instance. Feature sticky values and global variable sticky values are independent.
Once initialized with sticky features, the SDK will look for values there first before evaluating the targeting conditions and going through the bucketing process.
450
470
451
-
### Set sticky afterwards
452
-
453
471
You can also set sticky features after the SDK is initialized:
By default, `setDatafile(datafile)` merges the incoming datafile with the SDK's stored datafile. Incoming top-level metadata is used, and incoming segments/featuresoverride existing segments/features with the same keys.
491
+
By default, `setDatafile(datafile)` merges the incoming datafile with the SDK's stored datafile. Incoming toplevel metadata is used, and incoming segments, features, and global variables override existing entities with the same keys.
473
492
474
493
This means you can call `setDatafile` more than once with different datafiles, and the SDK instance accumulates their features and segments together. This is what makes [loading datafiles on demand](#loading-datafiles-on-demand) possible.
The returned `Evaluation` exposes the following properties:
@@ -673,6 +707,8 @@ And optionally these properties depending on whether you are evaluating a featur
673
707
674
708
Modules allow you to intercept the evaluation process and customize it further as per your needs.
675
709
710
+
For feature evaluations, all `before` callbacks run in registration order, followed by all `beforeEvaluation` callbacks. After evaluation and caller defaults, all `afterEvaluation` callbacks run, followed by all `after` callbacks. Global variable evaluations use only `beforeEvaluation` and `afterEvaluation`. Required feature checks run through the complete module pipeline, and transformed defaults are preserved.
711
+
676
712
### Defining a module
677
713
678
714
A module is a `FeaturevisorModule` with a unique `name` and optional lifecycle functions:
@@ -692,6 +728,9 @@ FeaturevisorModule myCustomModule = new FeaturevisorModule("my-custom-module")
692
728
return options.copy().context(context);
693
729
})
694
730
731
+
// before any feature or global variable evaluation
732
+
.beforeEvaluation(options -> options)
733
+
695
734
// configure bucket key
696
735
.bucketKey(options -> {
697
736
String bucketKey = options.getBucketKey();
@@ -707,6 +746,9 @@ FeaturevisorModule myCustomModule = new FeaturevisorModule("my-custom-module")
707
746
// after evaluation
708
747
.after((evaluation, options) -> evaluation)
709
748
749
+
// after any feature or global variable evaluation
Use `checkout` for a flag, `checkout:variation` for its variation, and `checkout:title` for its `title` variable. Boolean variables use the boolean resolver. Lists, structures, and JSON variables use the object resolver.
927
+
Use `checkout` for a flag, `checkout:variation` for its variation, `checkout:title` for its `title` variable, and `variable:welcomeMessage` for a global variable. Boolean variables use the boolean resolver. Lists, structures, and JSON variables use the object resolver.
884
928
885
-
OpenFeature's targeting key maps to `userId` by default. `targetingKeyField`, `keySeparator`, and `variationKey` on `FeaturevisorOpenFeatureProvider.Options` can customize the mapping.
929
+
OpenFeature's targeting key maps to `userId` by default. `targetingKeyField`, `keySeparator`, `variationKey`, and `globalVariablePrefix` on `FeaturevisorOpenFeatureProvider.Options` can customize the mapping. The global variable prefix defaults to `variable` and cannot contain the configured separator.
886
930
887
931
You can also reuse an existing Featurevisor instance:
888
932
@@ -927,7 +971,7 @@ $ make verify-artifacts
927
971
### Releasing
928
972
929
973
1. Merge the release changes into `main`.
930
-
2. Tag the release with a `v` prefix, such as `v3.0.0`, and push the tag.
974
+
2. Tag the release with a `v` prefix, such as `v4.0.0`, and push the tag.
931
975
3. GitHub Actions verifies and publishes the parent POM, Java SDK, and OpenFeature provider to [GitHub Packages](https://github.com/orgs/featurevisor/packages?repo_name=featurevisor-java).
932
976
4. Create the corresponding [GitHub release](https://github.com/featurevisor/featurevisor-java/releases).
0 commit comments