From f51d0201c62b558a89a1e3ab77e666ce98ecba0b Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 11 Apr 2023 15:27:57 -0400 Subject: [PATCH] chore: update readme using template (#382) * chore: update readme using template Signed-off-by: Todd Baert * fixup: add complete API documentation Signed-off-by: Todd Baert * Update README.md Co-authored-by: Justin Abrahms Signed-off-by: Todd Baert * Update README.md Co-authored-by: Justin Abrahms Signed-off-by: Todd Baert --------- Signed-off-by: Todd Baert Co-authored-by: Justin Abrahms --- CONTRIBUTING.md | 20 ++++- README.md | 225 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 169 insertions(+), 76 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84c8d017..f18fa1af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -Welcome! Super happy to have you here. +## Welcome! Super happy to have you here. A few things. @@ -10,10 +10,26 @@ We're not keen on vendor-specific stuff in this library, but if there are change Any contributions you make are expected to be tested with unit tests. You can validate these work with `gradle test`, or the automation itself will run them for you when you make a PR. -Your code is supposed to work with Java 11+. +Your code is supposed to work with Java 8+. If you think we might be out of date with the spec, you can check that by invoking `python spec_finder.py` in the root of the repository. This will validate we have tests defined for all of the specification entries we know about. If you're adding tests to cover something in the spec, use the `@Specification` annotation like you see throughout the test suites. +## Integration tests + +The continuous integration runs a set of [gherkin integration tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with + +``` +docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest +``` +and then run +``` +mvn test -P integration-test +``` + +## Releasing + +See [releasing](./docs/release.md). + Thanks and looking forward to your issues and pull requests. diff --git a/README.md b/README.md index 1b135dfb..aef00380 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,43 @@ -# OpenFeature SDK for Java + +

+ + + + OpenFeature Logo + +

+

OpenFeature Java SDK

+ +[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.5.2&color=yellow)](https://github.com/open-feature/spec/tree/v0.5.2) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk) [![javadoc](https://javadoc.io/badge2/dev.openfeature/sdk/javadoc.svg)](https://javadoc.io/doc/dev.openfeature/sdk) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) -[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.5.2&color=yellow)](https://github.com/open-feature/spec/tree/v0.5.2) [![Known Vulnerabilities](https://snyk.io/test/github/open-feature/java-sdk/badge.svg)](https://snyk.io/test/github/open-feature/java-sdk) [![on-merge](https://github.com/open-feature/java-sdk/actions/workflows/merge.yml/badge.svg)](https://github.com/open-feature/java-sdk/actions/workflows/merge.yml) [![codecov](https://codecov.io/gh/open-feature/java-sdk/branch/main/graph/badge.svg?token=XMS9L7PBY1)](https://codecov.io/gh/open-feature/java-sdk) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6241/badge)](https://bestpractices.coreinfrastructure.org/projects/6241) -This is the Java implementation of [OpenFeature](https://openfeature.dev), a vendor-agnostic abstraction library for evaluating feature flags. - -We support multiple data types for flags (numbers, strings, booleans, objects) as well as hooks, which can alter the lifecycle of a flag evaluation. +## 👋 Hey there! Thanks for checking out the OpenFeature Java SDK -This library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices. - -## Usage - -While `Boolean` provides the simplest introduction, we offer a variety of flag types. - -```java -import dev.openfeature.sdk.Structure; - -class MyClass { - public UI booleanExample() { - // Should we render the redesign? Or the default webpage? - if (client.getBooleanValue("redesign_enabled", false)) { - return render_redesign(); - } - return render_normal(); - } +### What is OpenFeature? - public Template stringExample() { - // Get the template to load for the custom new homepage - String template = client.getStringValue("homepage_template", "default-homepage.html"); - return render_template(template); - } +[OpenFeature][openfeature-website] is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. - public List numberExample() { - // How many modules should we be fetching? - Integer count = client.getIntegerValue("module-fetch-count", 4); - return fetch_modules(count); - } +### Why standardize feature flags? - public HomepageModule structureExample() { - Structure obj = client.getObjectValue("hero-module", previouslyDefinedDefaultStructure); - return HomepageModule.builder() - .title(obj.getValue("title")) - .body(obj.getValue("description")) - .build(); - } -} -``` +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. -For complete documentation, visit: https://docs.openfeature.dev/docs/category/concepts +## 🔍 Requirements: -## Requirements - Java 8+ (compiler target is 1.8) -## Installation +Note that this library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices. -### Add it to your build +## 📦 Installation: + +### Maven -#### Maven ```xml @@ -88,7 +63,7 @@ If you would like snapshot builds, this is the relevant repository information: ``` -#### Gradle +### Gradle ```groovy dependencies { @@ -97,51 +72,153 @@ dependencies { ``` -### Configure it -To configure it, you'll need to add a provider to the global singleton `OpenFeatureAPI`. From there, you can generate a `Client` which is usable by your code. While you'll likely want a provider for your specific backend, we've provided a `NoOpProvider`, which simply returns the default passed in. +### Software Bill of Materials (SBOM) + +We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts. + +## 🌟 Features: + +- support for various backend [providers](https://docs.openfeature.dev/docs/reference/concepts/provider) +- easy integration and extension via [hooks](https://docs.openfeature.dev/docs/reference/concepts/hooks) +- bool, string, numeric and object flag types +- [context-aware](https://docs.openfeature.dev/docs/reference/concepts/evaluation-context) evaluation + +## 🚀 Usage: + +### Basics: + ```java -class MyApp { - public void example(){ - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new NoOpProvider()); - Client client = api.getClient(); - // Now use your `client` instance to evaluate some feature flags! - } +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); } ``` -## Contacting us -We hold regular meetings which you can see [here](https://github.com/open-feature/community/#meetings-and-events). -We are also present on the `#openfeature` channel in the [CNCF slack](https://slack.cncf.io/). +### Context-aware evaluation: -## Developing +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`](https://docs.openfeature.dev/specification/glossary#targeting). +If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. -### Integration tests +```java +// global context for static data +OpenFeatureAPI api = OpenFeatureAPI.getInstance(); +Map attributes = new HashMap<>(); +attributes.put("appVersion", new Value(System.getEnv("APP_VERSION"))); +EvaluationContext apiCtx = new ImmutableContext(attributes); +api.setEvaluationContext(apiCtx); + +// request context +Map 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); +``` -The continuous integration runs a set of [gherkin integration tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with +### Providers: +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](https://github.com/open-feature/java-sdk-contrib) 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. + +```java +public class MyProvider implements FeatureProvider { +@Override + public Metadata getMetadata() { + return () -> "My Provider"; + } + + @Override + public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { + // resolve a boolean flag value + } + + @Override + public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) { + // resolve a string flag value + } + + @Override + public ProviderEvaluation getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) { + // resolve an int flag value + } + + @Override + public ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) { + // resolve a double flag value + } + + @Override + public ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) { + // resolve an object flag value + } +} ``` -docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest -``` -and then run -``` -mvn test -P integration-test + +See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available providers. + +### Hooks: + +Hooks are a mechanism that allow for the addition of arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validation of the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. + +```java +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!"); + } +} ``` -## Releasing +See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available hooks. -See [releasing](./docs/release.md). +### Logging: -### Software Bill of Materials (SBOM) +The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation. -We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts. +### Complete API documentation: -## Contributors +See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for the complete API documentation. -Thanks so much to our contributors. +## ⭐️ Support the project + +- Give this repo a ⭐️! +- Follow us social media: + - Twitter: [@openfeature](https://twitter.com/openfeature) + - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) +- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) +- For more check out our [community page](https://docs.openfeature.dev/community/) + +## 🤝 Contributing + +Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide. + +### Thanks to everyone that has already contributed - Pictures of the folks who have contributed to the project + Pictures of the folks who have contributed to the project Made with [contrib.rocks](https://contrib.rocks). + +## 📜 License + +[Apache License 2.0](LICENSE) + +[openfeature-website]: https://openfeature.dev