Skip to content

featureflow/featureflow-java-sdk

Repository files navigation

featureflow-java-sdk

Featureflow Java Client SDK

Get your Featureflow account at featureflow.io

Get Started

The easiest way to get started is to follow the Featureflow quick start guides

Change Log

Please see CHANGELOG.

Installation

Using Maven

<dependency>
    <groupId>io.featureflow</groupId>
    <artifactId>featureflow-java-sdk</artifactId>
    <version>1.1.3</version>
</dependency>

Usage

Create a featureflow client

Get your 'Server Environment Api Key' from the environment page in featureflow and instantiate a singleton client:

String apiKey = "<Your Server Environment Api Key goes here>";
FeatureflowClient featureflow = FeatureflowClient.builder(apiKey).build();

This is a singleton, so if you're using spring you should make it a @Bean in a @Configuration class.

Evaluate a feature

In your code, you can test the value of your feature where the value of my-feature-key is equal to 'on'

  if (featureflow.evaluate('my-feature-key', user).is('on')){
    // this feature code will be run because 'my-feature-key' is set to 'on'
  }

Because the default variants for any feature are 'on' and 'off', we have provided two helper methods .isOn() and .isOff()

if(featureflow.evaluate("my-feature-key", user).isOn()){
  // this feature code will be run because 'my-feature-key' is set to 'on'
}

if(featureflow.evaluate("my-feature-key", user).isOff()){
  // this feature code won't be run because 'my-feature-key' is not set to 'off'
}

Variants can be any value based on your feature rules:

    if (featureflow.evaluate("my-feature-key", user).is("red")){
        System.out.println("my-feature-key is " + featureflow.evaluate("my-feature-key").value());
    }

Evaluating a User

You can pass user information in to allow features to be targeted. At the point in time of evaluation (e.g. on a rest call or other call) you can create and pass in a user by creating a FeatureflowUser object. We have a builder to help:

FeatureflowUser user = new FeatureflowUser("uniqueuserId")
    .withAttribute("tier", "silver")
    .withAttribute("age", 32)
    .withAttribute("signup_date", new DateTime(2017, 1, 1, 12, 0, 0, 0))    
    .withAttribute("name", "Joe User")
    .withAttribute("email", "[email protected]")
    .withAttributes("user_role", Arrays.asList("pvt_tester", "administrator"))
    .build();

User attributes can be of type DateTime, Number, String or List<DateTime>, List<Number>, List<String>

When a list of user attributes is passed in, each rule may match any of the attribute values, additionally each attribute is stored in featureflow for subsequent lookup in rule creation.

If you do not want the user saved in featureflow set '.saveUser(false)' on the FeatureflowUser object.

Evaluate by passing the user into the evaluate method:

featureflow.evaluate("example-feature", user).isOn();

Advanced uses

UserProviders

You can create a common 'userProvider' - featureflow will use the userProvider when evaluating any features. This can be useful, for example, to obtain a common user (such as logged in user details) when evaluating features.

Implement a FeatureflowUserProvider to obtain a user without requiring a lookup key, for example if you know you can get a user from a current login - an example that may use spring:

...
    @Bean
    public FeatureflowClient featureflowClient(){
        return FeatureflowClient.builder("apiKey").withUserProvider(() -> getFeatureflowUser()).build();
    }

    private FeatureflowUser getFeatureflowUser(){
        User myAppLogin = userService.getCurrentUser();
        return new FeatureflowUser(myAppLogin.getId())
            .withAttribute("name", myAppLogin.getName())
            .withStringAttributes("user_role", myAppLogin.getRoles().stream().map(Role::getName).collect(Collectors.toList()));
        //etc
    }

If you require a lookup then implement a FeatureflowUserLookupProvider

This provider will attempt to obtain the user when a feature is evaluated passing in a userId - i.e. when calling public Evaluate evaluate (String featureKey, String userId) {

@Bean
    public FeatureflowClient featureflowClient(){
        return FeatureflowClient.builder("apiKey").withUserLookupProvider((userId) -> getFeatureflowUser(userId)).build();
    }

    private FeatureflowUser getFeatureflowUser(String userId){
        User myAppLogin = userService.findOneById(userId);
        return new FeatureflowUser(myAppLogin.getId())
            .withAttribute("name", myAppLogin.getName())
            .withStringAttributes("user_role", myAppLogin.getRoles().stream().map(Role::getName).collect(Collectors.toList()));
        //etc
    }
    
    ...
    
        client.evaluate("my-feature", "user1").isOn();
    }

Callbacks

You can declare callbacks to act upon a feature control being updated:

FeatureflowClient featureflowClient = FeatureflowClient.builder(PROD_API_KEY)
                .withFeatures(Arrays.asList(
                        new Feature(FeatureKeys.FEATURE_ONE),
                        new Feature(FeatureKeys.FEATURE_TWO),
                        new Feature(FeatureKeys.FEATURE_THREE),
                        new Feature(FeatureKeys.FEATURE_FOUR)

                ))
                .withUpdateCallback(control -> System.out.println("Received a control update event: " + control.getKey()))
                .build();

Further documentation can be found here

About featureflow

Roadmap

  • Multiple callbacks
  • Offline mode
  • Read only mode

License

Apache-2.0