OpenFeature is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.
Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition.
- Java 8+ (compiler target is 1.8)
Note that this library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices.
<dependency>
<groupId>dev.openfeature</groupId>
<artifactId>sdk</artifactId>
<version>1.4.0</version>
</dependency>
If you would like snapshot builds, this is the relevant repository information:
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonartype</id>
<name>Sonartype Repository</name>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
dependencies {
implementation 'dev.openfeature:sdk:1.4.0'
}
We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts.
- support for various backend providers
- easy integration and extension via hooks
- bool, string, numeric, and object flag types
- context-aware evaluation
public void example(){
// configure a provider
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProvider(new MyProviderOfChoice());
// create a client
Client client = api.getClient();
// get a bool flag value
boolean flagValue = client.getBooleanValue("boolFlag", false);
}
Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server.
In OpenFeature, we refer to this as targeting
.
If the flag system you're using supports targeting, you can provide the input data using the EvaluationContext
.
// global context for static data
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
Map<String, Value> attributes = new HashMap<>();
attributes.put("appVersion", new Value(System.getEnv("APP_VERSION")));
EvaluationContext apiCtx = new ImmutableContext(attributes);
api.setEvaluationContext(apiCtx);
// request context
Map<String, Value> attributes = new HashMap<>();
attributes.put("email", new Value(session.getAttribute("email")));
attributes.put("product", new Value(productId));
String targetingKey = session.getId();
EvaluationContext reqCtx = new ImmutableContext(targetingKey, attributes);
// use merged contextual data to determine a flag value
boolean flagValue = client.getBooleanValue("some-flag", false, reqCtx);
Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions.
Initialization events (PROVIDER_READY
on success, PROVIDER_ERROR
on failure) are dispatched for every provider.
Some providers support additional events, such as PROVIDER_CONFIGURATION_CHANGED
.
Please refer to the documentation of the provider you're using to see what events are supported.
// add an event handler to a client
client.onProviderConfigurationChanged((EventDetails eventDetails) -> {
// do something when the provider's flag settings change
});
// add an event handler to the global API
OpenFeatureAPI.getInstance().onProviderStale((EventDetails eventDetails) -> {
// do something when the provider's cache goes stale
});
A hook is a mechanism that allows for adding arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validating the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking.
public class MyHook implements Hook {
/**
*
* @param ctx Information about the particular flag evaluation
* @param details Information about how the flag was resolved, including any resolved values.
* @param hints An immutable mapping of data for users to communicate to the hooks.
*/
@Override
public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) {
System.out.println("After evaluation!");
}
}
See here for a catalog of available hooks.
The Java SDK uses SLF4J. See the SLF4J manual for complete documentation.
Clients can be given a name. A name is a logical identifier which can be used to associate clients with a particular provider. If a name has no associated provider, clients with that name use the global provider.
FeatureProvider scopedProvider = new MyProvider();
// set this provider for clients named "my-name"
OpenFeatureAPI.getInstance().setProvider("my-name", provider);
// create a client bound to the provider above
Client client = OpenFeatureAPI.getInstance().getClient("my-name");
To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency.
This can be a new repository or included in the existing contrib repository available under the OpenFeature organization.
Finally, youβll then need to write the provider itself.
This can be accomplished by implementing the FeatureProvider
interface exported by the OpenFeature SDK.
public class MyProvider implements FeatureProvider {
@Override
public Metadata getMetadata() {
return () -> "My Provider";
}
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
// resolve a boolean flag value
}
@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
// resolve a string flag value
}
@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
// resolve an int flag value
}
@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
// resolve a double flag value
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
// resolve an object flag value
}
}
See here for a catalog of available providers.
The OpenFeature API provides a close function to perform a cleanup of all registered providers. This should only be called when your application is in the process of shutting down.
// shut down all providers
OpenFeatureAPI.getInstance().shutdown();
See here for the complete API documentation.
- Give this repo a βοΈ!
- Follow us on social media:
- Twitter: @openfeature
- LinkedIn: OpenFeature
- Join us on Slack
- For more, check out our community page
Interested in contributing? Great, we'd love your help! To get started, take a look at the CONTRIBUTING guide.
Made with contrib.rocks.