diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml
index d82baeb3..153fd0a5 100644
--- a/.github/workflows/merge.yml
+++ b/.github/workflows/merge.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5
- name: Set up JDK 8
- uses: actions/setup-java@b943a4ed876ec91f6d0cde2181d88d24e8e348de
+ uses: actions/setup-java@5b86b67f5bb794ee4de9464f70b700b9445b03a8
with:
java-version: '8'
distribution: 'temurin'
diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml
index 4e705114..dd5d05b2 100644
--- a/.github/workflows/pullrequest.yml
+++ b/.github/workflows/pullrequest.yml
@@ -8,26 +8,19 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
- # TODO: this can be removed with https://github.com/open-feature/java-sdk/issues/523
- services:
- flagd:
- image: ghcr.io/open-feature/flagd-testbed:latest
- ports:
- - 8013:8013
-
steps:
- name: Check out the code
uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5
- name: Set up JDK 8
- uses: actions/setup-java@b943a4ed876ec91f6d0cde2181d88d24e8e348de
+ uses: actions/setup-java@5b86b67f5bb794ee4de9464f70b700b9445b03a8
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Initialize CodeQL
- uses: github/codeql-action/init@2160dd3b55fb3a72bfc85e989cad8aa785d2e8d5
+ uses: github/codeql-action/init@e683046da183a09174d531cc43713853e27debb3
with:
languages: java
@@ -40,7 +33,7 @@ jobs:
${{ runner.os }}-maven-
- name: Verify with Maven
- run: mvn --batch-mode --update-snapshots --activate-profiles e2e-test verify
+ run: mvn --batch-mode --update-snapshots --activate-profiles e2e verify
- name: Upload coverage to Codecov
uses: codecov/codecov-action@e1dd05cde2ed37d100f658b34ea423728ba1812e
@@ -52,4 +45,4 @@ jobs:
verbose: true # optional (default = false)
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@2160dd3b55fb3a72bfc85e989cad8aa785d2e8d5
+ uses: github/codeql-action/analyze@e683046da183a09174d531cc43713853e27debb3
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a8b9d79d..6a77578c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -32,7 +32,7 @@ jobs:
uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5
- name: Set up JDK 8
if: ${{ steps.release.outputs.releases_created }}
- uses: actions/setup-java@b943a4ed876ec91f6d0cde2181d88d24e8e348de
+ uses: actions/setup-java@5b86b67f5bb794ee4de9464f70b700b9445b03a8
with:
java-version: '8'
distribution: 'temurin'
diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml
index 00f33d2b..e4a66ac5 100644
--- a/.github/workflows/static-code-scanning.yaml
+++ b/.github/workflows/static-code-scanning.yaml
@@ -33,12 +33,12 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@2160dd3b55fb3a72bfc85e989cad8aa785d2e8d5
+ uses: github/codeql-action/init@e683046da183a09174d531cc43713853e27debb3
with:
languages: java
- name: Autobuild
- uses: github/codeql-action/autobuild@2160dd3b55fb3a72bfc85e989cad8aa785d2e8d5
+ uses: github/codeql-action/autobuild@e683046da183a09174d531cc43713853e27debb3
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@2160dd3b55fb3a72bfc85e989cad8aa785d2e8d5
+ uses: github/codeql-action/analyze@e683046da183a09174d531cc43713853e27debb3
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 54824065..287b4c71 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1 +1 @@
-{".":"1.4.3"}
\ No newline at end of file
+{".":"1.5.0"}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ed96d88..51917159 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
# Changelog
+## [1.5.0](https://github.com/open-feature/java-sdk/compare/v1.4.3...v1.5.0) (2023-08-16)
+
+
+### โจ New Features
+
+* In-memory provider for e2e testing and minimal usage ([#546](https://github.com/open-feature/java-sdk/issues/546)) ([a741568](https://github.com/open-feature/java-sdk/commit/a741568762b96091bb0e50a32a8e00e863268429))
+
+
+### ๐งน Chore
+
+* **deps:** update actions/setup-java digest to 5b86b67 ([#562](https://github.com/open-feature/java-sdk/issues/562)) ([4a4d813](https://github.com/open-feature/java-sdk/commit/4a4d81367b50ab957d99371ffe368c0977768329))
+* **deps:** update github/codeql-action digest to 3ecf990 ([#557](https://github.com/open-feature/java-sdk/issues/557)) ([350196c](https://github.com/open-feature/java-sdk/commit/350196c6882aadba1c037132ff61296c8212d871))
+* **deps:** update github/codeql-action digest to e683046 ([#559](https://github.com/open-feature/java-sdk/issues/559)) ([6c52ee4](https://github.com/open-feature/java-sdk/commit/6c52ee464fdb5d5733cb5a31e9cfea1644840177))
+* fix codecov, throw in memory provider ([1f28921](https://github.com/open-feature/java-sdk/commit/1f28921fec2cece6d492fb77160bb97dd05c3e08))
+* fix e2e profile ([94a5a86](https://github.com/open-feature/java-sdk/commit/94a5a869d8f2d41adf632f60db1eb0f7e9b530ec))
+* fix jacoco coverage minimum, throw in memory provider ([#561](https://github.com/open-feature/java-sdk/issues/561)) ([1f28921](https://github.com/open-feature/java-sdk/commit/1f28921fec2cece6d492fb77160bb97dd05c3e08))
+
+
+### ๐ Documentation
+
+* update README to be auto-included in openfeature.dev ([#560](https://github.com/open-feature/java-sdk/issues/560)) ([3496366](https://github.com/open-feature/java-sdk/commit/3496366ae880e85c08e0b5925e9220b55a67c8eb))
+
## [1.4.3](https://github.com/open-feature/java-sdk/compare/v1.4.2...v1.4.3) (2023-08-11)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 63c9d533..8acd316a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,16 +18,11 @@ If you're adding tests to cover something in the spec, use the `@Specification`
## End-to-End Tests
-
+The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using `InMemoryProvider`.
-The continuous integration runs a set of [gherkin e2e 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
+to run alone:
```
-mvn test -P e2e-test
+mvn test -P e2e
```
## Releasing
diff --git a/README.md b/README.md
index b453b426..34f5ee44 100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,65 @@
+
-
-
+
+
OpenFeature Java SDK
-[](https://github.com/open-feature/spec/tree/v0.6.0)
-[](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk)
-[](https://javadoc.io/doc/dev.openfeature/sdk)
-[](https://www.repostatus.org/#active)
-[](https://snyk.io/test/github/open-feature/java-sdk)
-[](https://github.com/open-feature/java-sdk/actions/workflows/merge.yml)
-[](https://codecov.io/gh/open-feature/java-sdk)
-[](https://bestpractices.coreinfrastructure.org/projects/6241)
-
-## ๐ Hey there! Thanks for checking out the OpenFeature Java SDK
-
-### What is OpenFeature?
-
-[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.
+
+
+
+
-### Why standardize feature flags?
+[OpenFeature](https://openfeature.dev) 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.
+
+## ๐ Quick start
-## ๐ Requirements
+### Requirements
- 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.
-## ๐ฆ Installation
+### Install
-### Maven
+#### Maven
```xml
dev.openfeaturesdk
- 1.4.3
+ 1.5.0
```
@@ -63,77 +79,163 @@ If you would like snapshot builds, this is the relevant repository information:
```
-### Gradle
+#### Gradle
+
```groovy
dependencies {
- implementation 'dev.openfeature:sdk:1.4.3'
+ implementation 'dev.openfeature:sdk:1.5.0'
}
```
-### 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://openfeature.dev/docs/reference/concepts/provider)
-- easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks)
-- bool, string, numeric, and object flag types
-- [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation
-
-## ๐ Usage
+### Usage
```java
public void example(){
+ // flags defined in memory
+ Map> myFlags = new HashMap<>();
+ flags.put("v2_enabled", Flag.builder()
+ .variant("on", true)
+ .variant("off", false)
+ .defaultVariant("on")
+ .build());
+
// configure a provider
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
- api.setProvider(new MyProviderOfChoice());
+ api.setProvider(new InMemoryProvider(myFlags));
// create a client
Client client = api.getClient();
// get a bool flag value
- boolean flagValue = client.getBooleanValue("boolFlag", false);
+ boolean flagValue = client.getBooleanValue("v2_enabled", false);
}
```
-### Context-aware evaluation
+### API Reference
+
+See [here](https://javadoc.io/doc/dev.openfeature/sdk/latest/) for the Javadocs.
+
+## ๐ Features
+
+| Status | Features | Description |
+| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| โ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
+| โ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
+| โ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
+| โ | [Logging](#logging) | Integrate with popular logging packages. |
+| โ | [Named clients](#named-clients) | Utilize multiple providers in a single application. |
+| โ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
+| โ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
+| โ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
+
+Implemented: โ | In-progress: โ ๏ธ | Not implemented yet: โ
-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://openfeature.dev/specification/glossary#targeting).
-If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`.
+### Providers
+
+[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK.
+Look [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a complete list of available providers.
+If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself.
+
+Once you've added a provider as a dependency, it can be registered with OpenFeature like this:
+
+```java
+ OpenFeatureAPI.getInstance().setProvider(new MyProvider());
+```
+
+In some situations, it may be beneficial to register multiple providers in the same application.
+This is possible using [named clients](#named-clients), which is covered in more details below.
+
+### Targeting
+
+Sometimes, the value of a flag must consider some dynamic criteria about the application or user, such as the user's location, IP, email address, or the server's location.
+In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting).
+If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context).
```java
-// global context for static data
+// set a value to the global context
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
-Map attributes = new HashMap<>();
-attributes.put("appVersion", new Value(System.getEnv("APP_VERSION")));
-EvaluationContext apiCtx = new ImmutableContext(attributes);
+Map apiAttrs = new HashMap<>();
+apiAttrs.put("region", new Value(System.getEnv("us-east-1")));
+EvaluationContext apiCtx = new ImmutableContext(apiAttrs);
api.setEvaluationContext(apiCtx);
-// request context
-Map attributes = new HashMap<>();
-attributes.put("email", new Value(session.getAttribute("email")));
-attributes.put("product", new Value(productId));
+// set a value to the client context
+Map clientAttrs = new HashMap<>();
+clientAttrs.put("region", new Value(System.getEnv("us-east-1")));
+EvaluationContext clientCtx = new ImmutableContext(clientAttrs);
+Client client = api.getInstance().getClient();
+client.setEvaluationContext(clientCtx);
+
+// set a value to the invocation context
+Map requestAttrs = new HashMap<>();
+requestAttrs.put("email", new Value(session.getAttribute("email")));
+requestAttrs.put("product", new Value("productId"));
String targetingKey = session.getId();
-EvaluationContext reqCtx = new ImmutableContext(targetingKey, attributes);
+EvaluationContext reqCtx = new ImmutableContext(targetingKey, requestAttrs);
-// use merged contextual data to determine a flag value
boolean flagValue = client.getBooleanValue("some-flag", false, reqCtx);
```
-### Events
+### Hooks
+
+[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle
+Look [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a complete list of available hooks.
+If the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself.
+
+Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level.
+
+```java
+ // add a hook globally, to run on all evaluations
+ OpenFeatureAPI api = OpenFeatureAPI.getInstance();
+ api.addHooks(new ExampleHook());
+
+ // add a hook on this client, to run on all evaluations made by this client
+ Client client = api.getClient();
+ client.addHooks(new ExampleHook());
+
+ // add a hook for this evaluation only
+ Boolean retval = client.getBooleanValue(flagKey, false, null,
+ FlagEvaluationOptions.builder().hook(new ExampleHook()).build());
+```
+
+### Logging
+
+The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation.
+
+### Named clients
+
+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, the global provider is used.
+
+```java
+FeatureProvider scopedProvider = new MyProvider();
+
+// registering the default provider
+OpenFeatureAPI.getInstance().setProvider(LocalProvider());
+// registering a named provider
+OpenFeatureAPI.getInstance().setProvider("clientForCache", new CachedProvider());
+
+// a client backed by default provider
+Client clientDefault = OpenFeatureAPI.getInstance().getClient();
+// a client backed by CachedProvider
+Client clientNamed = OpenFeatureAPI.getInstance().getClient("clientForCache");
+```
+
+### Eventing
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.
```java
// add an event handler to a client
+Client client = OpenFeatureAPI.getInstance().getClient();
client.onProviderConfigurationChanged((EventDetails eventDetails) -> {
// do something when the provider's flag settings change
});
@@ -144,62 +246,46 @@ OpenFeatureAPI.getInstance().onProviderStale((EventDetails eventDetails) -> {
});
```
-### Hooks
+### Shutdown
-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.
+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.
```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!");
- }
-}
+// shut down all providers
+OpenFeatureAPI.getInstance().shutdown();
```
-See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available hooks.
+## Extending
-### Logging:
-
-The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation.
-
-### Named clients
-
-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.
-
-```java
-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");
-```
-
-### Providers:
+### Develop a provider
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.
+Youโll then need to write the provider by implementing the `FeatureProvider` interface exported by the OpenFeature SDK.
```java
public class MyProvider implements FeatureProvider {
-@Override
+ @Override
public Metadata getMetadata() {
return () -> "My Provider";
}
+ @Override
+ public ProviderState getState() {
+ // optionally indicate your provider's state (assumed to be READY if not implemented)
+ }
+
+ @Override
+ public void initialize(EvaluationContext evaluationContext) throws Exception {
+ // start up your provider
+ }
+
+ @Override
+ public void shutdown() {
+ // shut down your provider
+ }
+
@Override
public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
// resolve a boolean flag value
@@ -227,22 +313,76 @@ public class MyProvider implements FeatureProvider {
}
```
-See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available providers.
+If you'd like your provider to support firing events, such as events for when flags are changed in the flag management system, extend `EventProvider`.
-### Shutdown
+```java
+class MyEventProvider extends EventProvider {
+ @Override
+ public Metadata getMetadata() {
+ return () -> "My Event Provider";
+ }
-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.
+ @Override
+ public ProviderState getState() {
+ // indicate your provider's state (required for EventProviders)
+ }
-```java
-// shut down all providers
-OpenFeatureAPI.getInstance().shutdown();
+ @Override
+ public void initialize(EvaluationContext evaluationContext) throws Exception {
+ // emit events when flags are changed in a hypothetical REST API
+ this.restApiClient.onFlagsChanged(() -> {
+ ProviderEventDetails details = ProviderEventDetails.builder().message("flags changed in API!").build();
+ this.emitProviderConfigurationChanged(details);
+ });
+ }
+
+ @Override
+ public void shutdown() {
+ // shut down your provider
+ }
+
+ // remaining provider methods...
+}
```
-### Complete API documentation:
+> Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=provider&projects=&template=document-provider.yaml&title=%5BProvider%5D%3A+) so we can add it to the docs!
+
+### Develop a hook
+
+To develop a hook, 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.
+Implement your own hook by conforming to the `Hook interface`.
+To satisfy the interface, all methods (`Before`/`After`/`Finally`/`Error`) need to be defined.
+To avoid defining empty functions make use of the `UnimplementedHook` struct (which already implements all the empty functions).
+
+```java
+class MyHook implements Hook {
+
+ @Override
+ public Optional before(HookContext ctx, Map hints) {
+ // code that runs before the flag evaluation
+ }
+
+ @Override
+ public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) {
+ // code that runs after the flag evaluation succeeds
+ }
-See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for the complete API documentation.
+ @Override
+ public void error(HookContext ctx, Exception error, Map hints) {
+ // code that runs when there's an error during a flag evaluation
+ }
+ @Override
+ public void finallyAfter(HookContext ctx, Map hints) {
+ // code that runs regardless of success or error
+ }
+};
+```
+
+> Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs!
+
+
## โญ๏ธ Support the project
- Give this repo a โญ๏ธ!
@@ -263,9 +403,4 @@ Interested in contributing? Great, we'd love your help! To get started, take a l
Made with [contrib.rocks](https://contrib.rocks).
-
-## ๐ License
-
-[Apache License 2.0](LICENSE)
-
-[openfeature-website]: https://openfeature.dev
+
diff --git a/pom.xml b/pom.xml
index 098d6eb0..f0133467 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,14 +4,14 @@
dev.openfeaturesdk
- 1.4.3
+ 1.5.0UTF-81.8${maven.compiler.source}5.10.0
-
+
**/e2e/*.java${groupId}.${artifactId}
@@ -21,10 +21,10 @@
https://openfeature.dev
- abrahms
- Justin Abrahms
- eBay
- https://justin.abrah.ms/
+ abrahms
+ Justin Abrahms
+ eBay
+ https://justin.abrah.ms/
@@ -120,9 +120,9 @@
- io.cucumber
- cucumber-junit-platform-engine
- test
+ io.cucumber
+ cucumber-junit-platform-engine
+ test
@@ -139,39 +139,33 @@
test
-
- dev.openfeature.contrib.providers
- flagd
- 0.5.10
- test
-
-
org.awaitilityawaitility4.2.0test
+
-
- io.cucumber
- cucumber-bom
- 7.13.0
- pom
- import
-
-
-
- org.junit
- junit-bom
- 5.10.0
- pom
- import
-
+
+ io.cucumber
+ cucumber-bom
+ 7.13.0
+ pom
+ import
+
+
+
+ org.junit
+ junit-bom
+ 5.10.0
+ pom
+ import
+
@@ -203,7 +197,7 @@
-
+
maven-dependency-plugin3.6.0
@@ -249,7 +243,7 @@
${testExclusions}
-
+
@@ -271,7 +265,7 @@
- prepare-agent
+ prepare-agentprepare-agent
@@ -319,7 +313,7 @@
-
+
@@ -496,14 +490,11 @@
-
-
-
- e2e-test
+ e2e
-
+
diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
index 78e04c71..b324c07c 100644
--- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
+++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
@@ -40,6 +40,7 @@ public static FlagEvaluationDetails from(ProviderEvaluation providerEv
.value(providerEval.getValue())
.variant(providerEval.getVariant())
.reason(providerEval.getReason())
+ .errorMessage(providerEval.getErrorMessage())
.errorCode(providerEval.getErrorCode())
.flagMetadata(providerEval.getFlagMetadata())
.build();
diff --git a/src/main/java/dev/openfeature/sdk/Structure.java b/src/main/java/dev/openfeature/sdk/Structure.java
index f8b55212..46274e70 100644
--- a/src/main/java/dev/openfeature/sdk/Structure.java
+++ b/src/main/java/dev/openfeature/sdk/Structure.java
@@ -9,6 +9,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;
+import static dev.openfeature.sdk.Value.objectToValue;
+
/**
* {@link Structure} represents a potentially nested object type which is used to represent
* structured data.
@@ -123,4 +125,16 @@ default Map merge(Function