OpenFeature Provider
AI-Powered Install
MCP Install
Follow the MCP Getting Started guide to quickly set up the DevCycle MCP server and connect your AI tool.
- Run this prompt:
"Install DevCycle into this app"
📦 Install in Cursor
📦 Install in VS Code
claude mcp add --transport http devcycle https://mcp.devcycle.com/mcp
OpenFeature is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with DevCycle.
DevCycle provides a Java implementation of the OpenFeature Provider interface, if you prefer to use the OpenFeature API.
Installation
The Provider implementation is built into the Java SDK.
Maven
You can use the Java SDK in your Maven project by adding the following to your pom.xml:
<dependency>
<groupId>com.devcycle</groupId>
<artifactId>java-server-sdk</artifactId>
<version>LATEST</version>
<scope>compile</scope>
</dependency>
Refer to the latest version of the SDK on maven central if you would not prefer Maven or Gradle to pull the latest version automatically by using +
Gradle
Alternatively you can use the SDK in your Gradle project by adding the following to build.gradle:
implementation("com.devcycle:java-server-sdk:+")
Usage
Start by creating and configuring the DevCycleLocalClient. Once the DevCycle client is configured, call the getOpenFeatureProvider() function to obtain the OpenFeature provider and set it into the OpenFeature API.
import com.devcycle.sdk.server.local.api.DevCycleLocalClient;
import com.devcycle.sdk.server.local.model.DevCycleLocalOptions;
import dev.openfeature.sdk.*;
public class OpenFeatureExample {
public static void main(String[] args) {
// Initialize DevCycle Client
DevCycleLocalOptions options = DevCycleLocalOptions.builder().build();
DevCycleLocalClient devCycleClient = new DevCycleLocalClient(System.getenv("DEVCYCLE_SERVER_SDK_KEY"), options);
// Set the provider into the OpenFeature API
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(devCycleClient.getOpenFeatureProvider());
// Get the OpenFeature client
Client openFeatureClient = api.getClient();
}
}
Evaluate a Variable
Use a Variable value by passing the Variable key, default value, and EvaluationContext to one of the OpenFeature flag evaluation methods.
MutableContext context = new MutableContext("user-1234");
// Retrieve a boolean flag value
Boolean boolValue = openFeatureClient.getBooleanValue("boolean-flag", false, context);
// Retrieve a string flag value
String stringValue = openFeatureClient.getStringValue("string-flag", "default", context);
// Retrieve an integer flag value
Integer intValue = openFeatureClient.getIntegerValue("integer-flag", 0, context);
// Retrieve a double flag value
Double doubleValue = openFeatureClient.getDoubleValue("double-flag", 0.0, context);
// Retrieve a json flag value
Map<String,Object> defaultJsonData = new LinkedHashMap<>();
defaultJsonData.put("default", "value");
Value jsonResult = openFeatureClient.getObjectValue("json-flag", new Value(Structure.mapToStructure(defaultJsonData)), context);
// Use the returned values in your application logic
if (boolValue) {
// Feature is enabled
System.out.println("Feature is enabled! String value: " + stringValue);
} else {
// Feature is disabled, default value was returned
System.out.println("Feature is disabled");
}
NOTE: use DevCycleCloudClient \ DevCycleCloudOptions for Cloud Bucketing mode.
Required Targeting Key
For DevCycle SDK to work we require either a targeting key or user_id attribute to be set on the OpenFeature context.
This value is used to identify the user as the user_id property for a DevCycleUser in DevCycle.
Mapping Context Properties to DevCycleUser
The provider will automatically translate known DevCycleUser properties from the OpenFeature context to the DevCycleUser object.
DevCycleUser Java Interface
For example all these properties will be set on the DevCycleUser:
MutableContext context = new MutableContext("test-1234");
context.add("email", "email@devcycle.com");
context.add("name", "name");
context.add("country", "CA");
context.add("language", "en");
context.add("appVersion", "1.0.11");
context.add("appBuild", 1000);
Map<String,Object> customData = new LinkedHashMap<>();
customData.put("custom", "value");
context.add("customData", Structure.mapToStructure(customData));
Map<String,Object> privateCustomData = new LinkedHashMap<>();
privateCustomData.put("private", "data");
context.add("privateCustomData", Structure.mapToStructure(privateCustomData));
Context properties that are not known DevCycleUser properties will be automatically added to the customData property of the DevCycleUser.
DevCycle allows the following data types for custom data values: boolean, integer, double, float, and String. Other data types will be ignored.
JSON Flag Limitations
The OpenFeature spec for JSON flags allows for any type of valid JSON value to be set as the flag value.
For example the following are all valid default value types to use with OpenFeature:
MutableContext context = new MutableContext("user-1234");
// Invalid JSON values for the DevCycle SDK, will return the default value with a TYPE_MISMATCH error
Value listResult = openFeatureClient.getObjectValue("json-flag", new Value(new ArrayList<String>(Arrays.asList("value1", "value2"))), context);
Value intResult = openFeatureClient.getObjectValue("json-flag", new Value(610), context);
Value boolResult = openFeatureClient.getObjectValue("json-flag", new Value(false), context);
Value stringResult = openFeatureClient.getObjectValue("json-flag", new Value("string"), context);
Value nullResult = openFeatureClient.getObjectValue("json-flag", new Value(), context);
However, these are not valid types for the DevCycle SDK, the DevCycle SDK only supports JSON Objects (as Map<String,Object>):
MutableContext context = new MutableContext("user-1234");
Map<String,Object> defaultJsonData = new LinkedHashMap<>();
defaultJsonData.put("default", "value");
Value jsonResult = openFeatureClient.getObjectValue("json-flag", new Value(Structure.mapToStructure(defaultJsonData)), context);
// Convert the returned Value back to a Map<String, Object>
Map<String, Object> jsonMap = jsonResult.asStructure().asObjectMap();
This is enforced for both the flag values and the default values supplied to the getObjectValue() method. Invalid types will return the default value with a TYPE_MISMATCH error code and an ERROR reason in the evaluation details.