diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml
index 8f885bd8..df591de7 100644
--- a/.github/workflows/lint-pr.yml
+++ b/.github/workflows/lint-pr.yml
@@ -18,6 +18,6 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- - uses: amannn/action-semantic-pull-request@00282d63cda40a6eaf3e9d0cbb1ac4384de896e8
+ - uses: amannn/action-semantic-pull-request@47b15d52c5c30e94a17ec87eb8dd51ff5221fed9
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml
index 84bceb8b..3b7477a5 100644
--- a/.github/workflows/merge.yml
+++ b/.github/workflows/merge.yml
@@ -20,9 +20,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up JDK 8
- uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758
+ uses: actions/setup-java@78078da0cd035d0d177cc2cb696e05d96fba7d11
with:
java-version: '8'
distribution: 'temurin'
@@ -49,7 +49,7 @@ jobs:
run: mvn --batch-mode --update-snapshots verify
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@398b9de041a7e69750d45077b10c5912201a3466
+ uses: codecov/codecov-action@v3.1.4
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
flags: unittests # optional
diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml
index 8b018bdb..1693197f 100644
--- a/.github/workflows/pullrequest.yml
+++ b/.github/workflows/pullrequest.yml
@@ -10,17 +10,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the code
- uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up JDK 8
- uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758
+ uses: actions/setup-java@78078da0cd035d0d177cc2cb696e05d96fba7d11
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Initialize CodeQL
- uses: github/codeql-action/init@43750fe4fc4f068f04f2215206e6f6a29c78c763
+ uses: github/codeql-action/init@9734ecd5b5d89514b0ce942a73586adcbe42b6ee
with:
languages: java
@@ -36,7 +36,7 @@ jobs:
run: mvn --batch-mode --update-snapshots --activate-profiles e2e verify
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@398b9de041a7e69750d45077b10c5912201a3466
+ uses: codecov/codecov-action@v3.1.4
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
flags: unittests # optional
@@ -45,4 +45,4 @@ jobs:
verbose: true # optional (default = false)
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@43750fe4fc4f068f04f2215206e6f6a29c78c763
+ uses: github/codeql-action/analyze@9734ecd5b5d89514b0ce942a73586adcbe42b6ee
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 90f5d59c..b15ee568 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -19,7 +19,7 @@ jobs:
# Release-please creates a PR that tracks all changes
steps:
- - uses: google-github-actions/release-please-action@01b3219546e6e7c4cfdaece8cd06efa464f49e2a
+ - uses: google-github-actions/release-please-action@2921787898ea2925c9eec03a32aa7404a75399e5
id: release
with:
command: manifest
@@ -29,10 +29,10 @@ jobs:
# These steps are only run if this was a merged release-please PR
- name: checkout
if: ${{ steps.release.outputs.releases_created }}
- uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up JDK 8
if: ${{ steps.release.outputs.releases_created }}
- uses: actions/setup-java@4075bfc1b51bf22876335ae1cd589602d60d8758
+ uses: actions/setup-java@78078da0cd035d0d177cc2cb696e05d96fba7d11
with:
java-version: '8'
distribution: 'temurin'
diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml
index 1190722f..5e9f9d8f 100644
--- a/.github/workflows/static-code-scanning.yaml
+++ b/.github/workflows/static-code-scanning.yaml
@@ -29,16 +29,16 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@72f2cec99f417b1a1c5e2e88945068983b7965f9
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@43750fe4fc4f068f04f2215206e6f6a29c78c763
+ uses: github/codeql-action/init@9734ecd5b5d89514b0ce942a73586adcbe42b6ee
with:
languages: java
- name: Autobuild
- uses: github/codeql-action/autobuild@43750fe4fc4f068f04f2215206e6f6a29c78c763
+ uses: github/codeql-action/autobuild@9734ecd5b5d89514b0ce942a73586adcbe42b6ee
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@43750fe4fc4f068f04f2215206e6f6a29c78c763
+ uses: github/codeql-action/analyze@9734ecd5b5d89514b0ce942a73586adcbe42b6ee
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f1ef058b..0e757992 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1 +1 @@
-{".":"1.6.1"}
\ No newline at end of file
+{".":"1.7.0"}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1571c6a..903cf395 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,87 @@
# Changelog
+## [1.7.0](https://github.com/open-feature/java-sdk/compare/v1.6.1...v1.7.0) (2023-10-24)
+
+
+### ๐ Bug Fixes
+
+* **deps:** update dependency org.projectlombok:lombok to v1.18.30 ([#625](https://github.com/open-feature/java-sdk/issues/625)) ([23bb497](https://github.com/open-feature/java-sdk/commit/23bb4974aa7245972a31a0146701a37d3fd7e1b4))
+* null handling with Structure, Value ([#663](https://github.com/open-feature/java-sdk/issues/663)) ([3ab330a](https://github.com/open-feature/java-sdk/commit/3ab330a7595aab120007fba5c719ea6e6afac937))
+* RejectedExecutionException on shutdown ([#652](https://github.com/open-feature/java-sdk/issues/652)) ([8c595b0](https://github.com/open-feature/java-sdk/commit/8c595b0227f6e186d31f8104cbbb125c8b06e2a4))
+
+
+### โจ New Features
+
+* implement spec 0.7.0 changes ([#655](https://github.com/open-feature/java-sdk/issues/655)) ([fe5a20f](https://github.com/open-feature/java-sdk/commit/fe5a20f2c39c776a68f5533ee950b96adf548231))
+ * run any event handler immediately if the provider is in the associated state, not just ready
+ * add providerName to event details
+ * add STALE provider state
+
+
+### ๐งน Chore
+
+* **deps:** update actions/checkout digest to 7cdaf2f ([#646](https://github.com/open-feature/java-sdk/issues/646)) ([8eff8d9](https://github.com/open-feature/java-sdk/commit/8eff8d9effe9471e7a98affdca23f78681f0fdcc))
+* **deps:** update actions/checkout digest to 8530928 ([#653](https://github.com/open-feature/java-sdk/issues/653)) ([b9312cf](https://github.com/open-feature/java-sdk/commit/b9312cfd43cfbbfce0e47ea9e41c471421f1f107))
+* **deps:** update actions/checkout digest to 8ade135 ([#628](https://github.com/open-feature/java-sdk/issues/628)) ([f819ead](https://github.com/open-feature/java-sdk/commit/f819ead57704e77643ea9861b8fdea002e1e4e55))
+* **deps:** update actions/checkout digest to b4ffde6 ([#658](https://github.com/open-feature/java-sdk/issues/658)) ([a0190b4](https://github.com/open-feature/java-sdk/commit/a0190b4311527dcd525925e6b69b112d384c65f0))
+* **deps:** update actions/setup-java digest to 0ab4596 ([#626](https://github.com/open-feature/java-sdk/issues/626)) ([059572a](https://github.com/open-feature/java-sdk/commit/059572a3d86291ff5c16aef7e841c4f60049ea19))
+* **deps:** update actions/setup-java digest to 78078da ([#657](https://github.com/open-feature/java-sdk/issues/657)) ([ed9ffb3](https://github.com/open-feature/java-sdk/commit/ed9ffb307b09f9da276c098a9064aea5f7dc38fd))
+* **deps:** update amannn/action-semantic-pull-request digest to 47b15d5 ([#631](https://github.com/open-feature/java-sdk/issues/631)) ([f86899b](https://github.com/open-feature/java-sdk/commit/f86899b10886765d9844bbda69da63ea6e91ccf8))
+* **deps:** update codecov/codecov-action digest to b65fbdc ([#614](https://github.com/open-feature/java-sdk/issues/614)) ([f0734f7](https://github.com/open-feature/java-sdk/commit/f0734f7c91371567bc3c2db059e7beab7cb50641))
+* **deps:** update codecov/codecov-action digest to c4cf8a4 ([#611](https://github.com/open-feature/java-sdk/issues/611)) ([c05609a](https://github.com/open-feature/java-sdk/commit/c05609ae4c6554d0795869990bb8414cabfcd7e8))
+* **deps:** update codecov/codecov-action digest to c9e0f0b ([#608](https://github.com/open-feature/java-sdk/issues/608)) ([29efc6c](https://github.com/open-feature/java-sdk/commit/29efc6c62f43fabc0b3f90aa190eaff6475fd6aa))
+* **deps:** update codecov/codecov-action digest to c9e4b73 ([#609](https://github.com/open-feature/java-sdk/issues/609)) ([af55f21](https://github.com/open-feature/java-sdk/commit/af55f216876191b95ddbd7b268ec92b0625d7c93))
+* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.7.3.6 ([#630](https://github.com/open-feature/java-sdk/issues/630)) ([d5a9867](https://github.com/open-feature/java-sdk/commit/d5a9867365d62bda51b87ff1d13e4f4daaee87cd))
+* **deps:** update dependency com.google.guava:guava to v32.1.3-jre ([#648](https://github.com/open-feature/java-sdk/issues/648)) ([8b5d8a5](https://github.com/open-feature/java-sdk/commit/8b5d8a5f319f26734465d25e2c9b4689b4390eb3))
+* **deps:** update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.3.1 ([#668](https://github.com/open-feature/java-sdk/issues/668)) ([75ff31e](https://github.com/open-feature/java-sdk/commit/75ff31e354824d9f3e2c9f808ae56333a62bdf23))
+* **deps:** update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.6.1 ([#665](https://github.com/open-feature/java-sdk/issues/665)) ([2554026](https://github.com/open-feature/java-sdk/commit/2554026e5816f4a10183fed3b59b9a83bc9a8f25))
+* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.2.1 ([#666](https://github.com/open-feature/java-sdk/issues/666)) ([72f168b](https://github.com/open-feature/java-sdk/commit/72f168b97c47f8662c7ffb40c24f1f6def8cba2c))
+* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.0 ([#620](https://github.com/open-feature/java-sdk/issues/620)) ([59c1c27](https://github.com/open-feature/java-sdk/commit/59c1c277aa81d879ebeb00d061bf2f65bd774f8c))
+* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.2.1 ([#667](https://github.com/open-feature/java-sdk/issues/667)) ([9dc2cb4](https://github.com/open-feature/java-sdk/commit/9dc2cb4e05163d8658b29526c7ee38ec87df439e))
+* **deps:** update github/codeql-action digest to 01b8760 ([#623](https://github.com/open-feature/java-sdk/issues/623)) ([210a9dc](https://github.com/open-feature/java-sdk/commit/210a9dcc06b62af77925678f6f2357fbc96d6c36))
+* **deps:** update github/codeql-action digest to 0d5c2e0 ([#643](https://github.com/open-feature/java-sdk/issues/643)) ([5737439](https://github.com/open-feature/java-sdk/commit/5737439269421671c5ef60efe5e01b56f2db71a3))
+* **deps:** update github/codeql-action digest to 27cb1e1 ([#633](https://github.com/open-feature/java-sdk/issues/633)) ([ab18516](https://github.com/open-feature/java-sdk/commit/ab185168bb36f07c545c671735e1bf416d49c040))
+* **deps:** update github/codeql-action digest to 2cc1651 ([#634](https://github.com/open-feature/java-sdk/issues/634)) ([a671984](https://github.com/open-feature/java-sdk/commit/a671984dbd5933e01e0db56f8661ae0bcd50f899))
+* **deps:** update github/codeql-action digest to 3078f51 ([#629](https://github.com/open-feature/java-sdk/issues/629)) ([ead77c1](https://github.com/open-feature/java-sdk/commit/ead77c113c64d5cb6f6d7f61d4e459cc0e8e3d5f))
+* **deps:** update github/codeql-action digest to 3dd4ad8 ([#641](https://github.com/open-feature/java-sdk/issues/641)) ([15dae81](https://github.com/open-feature/java-sdk/commit/15dae81665a564ea72d1bce492e9e61112b5101f))
+* **deps:** update github/codeql-action digest to 3f7850a ([#642](https://github.com/open-feature/java-sdk/issues/642)) ([c1dec9e](https://github.com/open-feature/java-sdk/commit/c1dec9e6c55262d60cc2303e8790e7ed4d56aee7))
+* **deps:** update github/codeql-action digest to 4254f3a ([#621](https://github.com/open-feature/java-sdk/issues/621)) ([7e100de](https://github.com/open-feature/java-sdk/commit/7e100de6d67b64a4b39246d02f2826ba824072b0))
+* **deps:** update github/codeql-action digest to 49aaa9a ([#627](https://github.com/open-feature/java-sdk/issues/627)) ([59a792f](https://github.com/open-feature/java-sdk/commit/59a792f836a01ac5ca7dd9792307c7a44366ed0a))
+* **deps:** update github/codeql-action digest to 4a368f6 ([#660](https://github.com/open-feature/java-sdk/issues/660)) ([c625721](https://github.com/open-feature/java-sdk/commit/c625721132da03e2b79836d47861eb40da3f6b71))
+* **deps:** update github/codeql-action digest to 4ab9237 ([#644](https://github.com/open-feature/java-sdk/issues/644)) ([ed415a7](https://github.com/open-feature/java-sdk/commit/ed415a7fcf9d2f97986488af4f7e4f7bf79ce53b))
+* **deps:** update github/codeql-action digest to 5f18c9a ([#617](https://github.com/open-feature/java-sdk/issues/617)) ([f887fe8](https://github.com/open-feature/java-sdk/commit/f887fe8656a20b4fcf1931cca79887234e3b00f9))
+* **deps:** update github/codeql-action digest to 6347027 ([#661](https://github.com/open-feature/java-sdk/issues/661)) ([799a5ba](https://github.com/open-feature/java-sdk/commit/799a5bae5bb250e46febcb32abd20eecfa7c9124))
+* **deps:** update github/codeql-action digest to 650a85e ([#632](https://github.com/open-feature/java-sdk/issues/632)) ([ac78477](https://github.com/open-feature/java-sdk/commit/ac784779ceb8cba8f4fc9be212b3d5eb6328ccce))
+* **deps:** update github/codeql-action digest to 6a6a824 ([#607](https://github.com/open-feature/java-sdk/issues/607)) ([fd774e3](https://github.com/open-feature/java-sdk/commit/fd774e35476f696318d630ca101756bc8a0e3dfd))
+* **deps:** update github/codeql-action digest to 77bbb99 ([#659](https://github.com/open-feature/java-sdk/issues/659)) ([7bd35c1](https://github.com/open-feature/java-sdk/commit/7bd35c10694d9aaffe7c70a8ae72490097ee0e1b))
+* **deps:** update github/codeql-action digest to 82ba90b ([#651](https://github.com/open-feature/java-sdk/issues/651)) ([39a2c18](https://github.com/open-feature/java-sdk/commit/39a2c18b2ed9ae2f05ecdc0d5ad312cd4689621e))
+* **deps:** update github/codeql-action digest to 8a2cbab ([#649](https://github.com/open-feature/java-sdk/issues/649)) ([b77e44e](https://github.com/open-feature/java-sdk/commit/b77e44e98377e725c2bbc9e75896de77531a3573))
+* **deps:** update github/codeql-action digest to 8e0b1c7 ([#624](https://github.com/open-feature/java-sdk/issues/624)) ([9684687](https://github.com/open-feature/java-sdk/commit/9684687c2d3268659db987c0a1f86710436df3f7))
+* **deps:** update github/codeql-action digest to 8efd40b ([#612](https://github.com/open-feature/java-sdk/issues/612)) ([27fbe45](https://github.com/open-feature/java-sdk/commit/27fbe4521c1c2bd7055aa273aa18b8c416f129e9))
+* **deps:** update github/codeql-action digest to 90f8ed1 ([#638](https://github.com/open-feature/java-sdk/issues/638)) ([5d35c9d](https://github.com/open-feature/java-sdk/commit/5d35c9dcf278874856e66dae160050b1d53082ed))
+* **deps:** update github/codeql-action digest to 9734ecd ([#664](https://github.com/open-feature/java-sdk/issues/664)) ([f838369](https://github.com/open-feature/java-sdk/commit/f838369217137f6132d02fa9b11f52630876197a))
+* **deps:** update github/codeql-action digest to a291b7c ([#662](https://github.com/open-feature/java-sdk/issues/662)) ([fb4d369](https://github.com/open-feature/java-sdk/commit/fb4d369615d89cb04b9a20c15048d09439356b89))
+* **deps:** update github/codeql-action digest to a370ce3 ([#637](https://github.com/open-feature/java-sdk/issues/637)) ([899191a](https://github.com/open-feature/java-sdk/commit/899191a1712b6f07e02fc9882208419d798a071f))
+* **deps:** update github/codeql-action digest to a67b110 ([#645](https://github.com/open-feature/java-sdk/issues/645)) ([3a1d138](https://github.com/open-feature/java-sdk/commit/3a1d13842e7ee5e8ae67967b418da063a78d9852))
+* **deps:** update github/codeql-action digest to b686e07 ([#640](https://github.com/open-feature/java-sdk/issues/640)) ([e99f7c4](https://github.com/open-feature/java-sdk/commit/e99f7c44f7413ecc7faab94730539cb670d565ef))
+* **deps:** update github/codeql-action digest to c459726 ([#619](https://github.com/open-feature/java-sdk/issues/619)) ([ee8a411](https://github.com/open-feature/java-sdk/commit/ee8a411026324fb9e0f88520ef6e61164f73052a))
+* **deps:** update github/codeql-action digest to c6c77c8 ([#613](https://github.com/open-feature/java-sdk/issues/613)) ([7a7c7e8](https://github.com/open-feature/java-sdk/commit/7a7c7e868f16f453548bf35dbd6fbc40fb316a3c))
+* **deps:** update github/codeql-action digest to d859d17 ([#654](https://github.com/open-feature/java-sdk/issues/654)) ([1a7f7de](https://github.com/open-feature/java-sdk/commit/1a7f7de6e4ab0971acd574c91ac196960df37391))
+* **deps:** update github/codeql-action digest to dd1128f ([#622](https://github.com/open-feature/java-sdk/issues/622)) ([a0342b7](https://github.com/open-feature/java-sdk/commit/a0342b7e203d62fa3e66d3ac25a40a148181fd36))
+* **deps:** update github/codeql-action digest to e7a6fa9 ([#635](https://github.com/open-feature/java-sdk/issues/635)) ([b6d4e7e](https://github.com/open-feature/java-sdk/commit/b6d4e7eec03511119fd0fd81b588ce00bcad4a8f))
+* **deps:** update github/codeql-action digest to e982de4 ([#615](https://github.com/open-feature/java-sdk/issues/615)) ([41e9ebb](https://github.com/open-feature/java-sdk/commit/41e9ebb8181f7022fac078f9557233a7c55086f8))
+* **deps:** update github/codeql-action digest to f3051ed ([#618](https://github.com/open-feature/java-sdk/issues/618)) ([514d463](https://github.com/open-feature/java-sdk/commit/514d4632457ef705f3adf451b11d4799e4ed15df))
+* **deps:** update google-github-actions/release-please-action digest to 2921787 ([#639](https://github.com/open-feature/java-sdk/issues/639)) ([c2da0b1](https://github.com/open-feature/java-sdk/commit/c2da0b16310b1135bbb443af694a112ce51718c3))
+* **deps:** update google-github-actions/release-please-action digest to 48f9873 ([#605](https://github.com/open-feature/java-sdk/issues/605)) ([692c368](https://github.com/open-feature/java-sdk/commit/692c368d74f51933a1af051d88216f62d7bf93ff))
+* **deps:** update google-github-actions/release-please-action digest to 4c5670f ([#636](https://github.com/open-feature/java-sdk/issues/636)) ([1fb173d](https://github.com/open-feature/java-sdk/commit/1fb173db669f587a7960a4fc2b9a3fada94d1dc4))
+* disable action pinning, revert codecov ([#616](https://github.com/open-feature/java-sdk/issues/616)) ([bdddeb1](https://github.com/open-feature/java-sdk/commit/bdddeb19b23e82b366d113fed4c24b7f8559600b))
+
+
+### ๐ Documentation
+
+* document setProviderAndWait in README ([#610](https://github.com/open-feature/java-sdk/issues/610)) ([818131b](https://github.com/open-feature/java-sdk/commit/818131b77e48f985bc9e115085f49f228891393b))
+* Update README.md ([#604](https://github.com/open-feature/java-sdk/issues/604)) ([6fd752d](https://github.com/open-feature/java-sdk/commit/6fd752d59d303bac06953bdf3b82e59054166e71))
+
## [1.6.1](https://github.com/open-feature/java-sdk/compare/v1.6.0...v1.6.1) (2023-09-09)
diff --git a/README.md b/README.md
index ca9626f6..8d05c903 100644
--- a/README.md
+++ b/README.md
@@ -13,13 +13,13 @@
-
-
+
+
-
-
+
+
@@ -39,7 +39,7 @@
-[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.
+[OpenFeature](https://openfeature.dev) is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.
## ๐ Quick start
@@ -59,7 +59,7 @@ Note that this library is intended to be used in server-side contexts and has no
dev.openfeature
sdk
- 1.6.1
+ 1.7.0
```
@@ -84,7 +84,7 @@ If you would like snapshot builds, this is the relevant repository information:
```groovy
dependencies {
- implementation 'dev.openfeature:sdk:1.6.1'
+ implementation 'dev.openfeature:sdk:1.7.0'
}
```
@@ -104,7 +104,7 @@ public void example(){
// configure a provider
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
- api.setProvider(new InMemoryProvider(myFlags));
+ api.setProviderAndWait(new InMemoryProvider(myFlags));
// create a client
Client client = api.getClient();
@@ -140,10 +140,23 @@ Look [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D
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:
+
+#### Synchronous
+
+To register a provider in a blocking manner to ensure it is ready before further actions are taken, you can use the `setProviderAndWait` method as shown below:
+
+```java
+ OpenFeatureAPI api = OpenFeatureAPI.getInstance();
+ api.setProviderAndWait(new MyProvider());
+```
+
+#### Asynchronous
+
+To register a provider in a non-blocking manner, you can use the `setProvider` method as shown below:
```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.
@@ -209,7 +222,7 @@ The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) f
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.
+If a name has no associated provider, the global provider is used.
```java
FeatureProvider scopedProvider = new MyProvider();
@@ -225,6 +238,9 @@ Client clientDefault = OpenFeatureAPI.getInstance().getClient();
Client clientNamed = OpenFeatureAPI.getInstance().getClient("clientForCache");
```
+Named providers can be set in a blocking or non-blocking way.
+For more details, please refer to the [providers](#providers) section.
+
### 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.
diff --git a/pom.xml b/pom.xml
index 5d9800dd..cd0a4942 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
dev.openfeature
sdk
- 1.6.1
+ 1.7.0
UTF-8
@@ -45,7 +45,7 @@
org.projectlombok
lombok
- 1.18.28
+ 1.18.30
provided
@@ -53,7 +53,7 @@
com.github.spotbugs
spotbugs
- 4.7.3
+ 4.8.0
provided
@@ -135,7 +135,7 @@
com.google.guava
guava
- 32.1.2-jre
+ 32.1.3-jre
test
@@ -200,7 +200,7 @@
maven-dependency-plugin
- 3.6.0
+ 3.6.1
verify
@@ -235,7 +235,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.1.2
+ 3.2.1
${surefireArgLine}
@@ -250,7 +250,7 @@
org.apache.maven.plugins
maven-failsafe-plugin
- 3.1.2
+ 3.2.1
${surefireArgLine}
@@ -349,7 +349,7 @@
com.github.spotbugs
spotbugs-maven-plugin
- 4.7.3.5
+ 4.7.3.6
spotbugs-exclusions.xml
@@ -365,7 +365,7 @@
com.github.spotbugs
spotbugs
- 4.7.3
+ 4.8.0
@@ -382,7 +382,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.3.0
+ 3.3.1
checkstyle.xml
UTF-8
@@ -452,7 +452,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.5.0
+ 3.6.0
true
all,-missing
diff --git a/renovate.json b/renovate.json
index 62574107..d3b4a0c6 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,8 +1,7 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
- "config:base",
- "helpers:pinGitHubActionDigests"
+ "config:base"
],
"packageRules": [
{
diff --git a/spotbugs-exclusions.xml b/spotbugs-exclusions.xml
index 8105db97..66032ad0 100644
--- a/spotbugs-exclusions.xml
+++ b/spotbugs-exclusions.xml
@@ -26,6 +26,26 @@
+
+ Added in spotbugs 4.8.0 - EventProvider shares a name with something from the standard lib (confusing), but change would be breaking
+
+
+
+
+ Added in spotbugs 4.8.0 - Metadata shares a name with something from the standard lib (confusing), but change would be breaking
+
+
+
+
+ Added in spotbugs 4.8.0 - Reason shares a name with something from the standard lib (confusing), but change would be breaking
+
+
+
+
+ Added in spotbugs 4.8.0 - FlagValueType.STRING shares a name with something from the standard lib (confusing), but change would be breaking
+
+
+
diff --git a/src/main/java/dev/openfeature/sdk/AbstractStructure.java b/src/main/java/dev/openfeature/sdk/AbstractStructure.java
new file mode 100644
index 00000000..a7d7c2ea
--- /dev/null
+++ b/src/main/java/dev/openfeature/sdk/AbstractStructure.java
@@ -0,0 +1,35 @@
+package dev.openfeature.sdk;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings({ "PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType" })
+abstract class AbstractStructure implements Structure {
+
+ protected final Map attributes;
+
+ AbstractStructure() {
+ this.attributes = new HashMap<>();
+ }
+
+ AbstractStructure(Map attributes) {
+ this.attributes = attributes;
+ }
+
+ /**
+ * Get all values as their underlying primitives types.
+ *
+ * @return all attributes on the structure into a Map
+ */
+ @Override
+ public Map asObjectMap() {
+ return attributes
+ .entrySet()
+ .stream()
+ // custom collector, workaround for Collectors.toMap in JDK8
+ // https://bugs.openjdk.org/browse/JDK-8148463
+ .collect(HashMap::new,
+ (accumulated, entry) -> accumulated.put(entry.getKey(), convertValue(entry.getValue())),
+ HashMap::putAll);
+ }
+}
diff --git a/src/main/java/dev/openfeature/sdk/EventDetails.java b/src/main/java/dev/openfeature/sdk/EventDetails.java
index 3f6db159..d4ecac93 100644
--- a/src/main/java/dev/openfeature/sdk/EventDetails.java
+++ b/src/main/java/dev/openfeature/sdk/EventDetails.java
@@ -7,19 +7,23 @@
/**
* The details of a particular event.
*/
-@Data @SuperBuilder(toBuilder = true)
+@Data
+@SuperBuilder(toBuilder = true)
public class EventDetails extends ProviderEventDetails {
private String clientName;
+ private String providerName;
- static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails) {
- return EventDetails.fromProviderEventDetails(providerEventDetails, null);
+ static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails, String providerName) {
+ return EventDetails.fromProviderEventDetails(providerEventDetails, providerName, null);
}
static EventDetails fromProviderEventDetails(
ProviderEventDetails providerEventDetails,
+ @Nullable String providerName,
@Nullable String clientName) {
return EventDetails.builder()
.clientName(clientName)
+ .providerName(providerName)
.flagsChanged(providerEventDetails.getFlagsChanged())
.eventMetadata(providerEventDetails.getEventMetadata())
.message(providerEventDetails.getMessage())
diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
index b324c07c..af48d877 100644
--- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
+++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
@@ -1,5 +1,7 @@
package dev.openfeature.sdk;
+import java.util.Optional;
+
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
@@ -8,7 +10,8 @@
import lombok.NoArgsConstructor;
/**
- * Contains information about how the provider resolved a flag, including the resolved value.
+ * Contains information about how the provider resolved a flag, including the
+ * resolved value.
*
* @param the type of the flag being evaluated.
*/
@@ -20,11 +23,15 @@ public class FlagEvaluationDetails implements BaseEvaluation {
private String flagKey;
private T value;
- @Nullable private String variant;
- @Nullable private String reason;
+ @Nullable
+ private String variant;
+ @Nullable
+ private String reason;
private ErrorCode errorCode;
- @Nullable private String errorMessage;
- @Builder.Default private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build();
+ @Nullable
+ private String errorMessage;
+ @Builder.Default
+ private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build();
/**
* Generate detail payload from the provider response.
@@ -42,7 +49,8 @@ public static FlagEvaluationDetails from(ProviderEvaluation providerEv
.reason(providerEval.getReason())
.errorMessage(providerEval.getErrorMessage())
.errorCode(providerEval.getErrorCode())
- .flagMetadata(providerEval.getFlagMetadata())
+ .flagMetadata(
+ Optional.ofNullable(providerEval.getFlagMetadata()).orElse(ImmutableMetadata.builder().build()))
.build();
}
}
diff --git a/src/main/java/dev/openfeature/sdk/ImmutableStructure.java b/src/main/java/dev/openfeature/sdk/ImmutableStructure.java
index 731a55b1..7ea1ef65 100644
--- a/src/main/java/dev/openfeature/sdk/ImmutableStructure.java
+++ b/src/main/java/dev/openfeature/sdk/ImmutableStructure.java
@@ -1,32 +1,32 @@
package dev.openfeature.sdk;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
-import java.util.stream.Collectors;
+
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
/**
- * {@link ImmutableStructure} represents a potentially nested object type which is used to represent
+ * {@link ImmutableStructure} represents a potentially nested object type which
+ * is used to represent
* structured data.
- * The ImmutableStructure is a Structure implementation which is threadsafe, and whose attributes can
- * not be modified after instantiation.
+ * The ImmutableStructure is a Structure implementation which is threadsafe, and
+ * whose attributes can
+ * not be modified after instantiation. All references are clones.
*/
@ToString
@EqualsAndHashCode
-@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"})
-public final class ImmutableStructure implements Structure {
-
- private final Map attributes;
+@SuppressWarnings({ "PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType" })
+public final class ImmutableStructure extends AbstractStructure {
/**
* create an immutable structure with the empty attributes.
*/
public ImmutableStructure() {
- this(new HashMap<>());
+ super();
}
/**
@@ -35,10 +35,14 @@ public ImmutableStructure() {
* @param attributes attributes.
*/
public ImmutableStructure(Map attributes) {
- Map copy = attributes.entrySet()
+ super(new HashMap<>(attributes.entrySet()
.stream()
- .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().clone()));
- this.attributes = new HashMap<>(copy);
+ .collect(HashMap::new,
+ (accumulated, entry) -> accumulated.put(entry.getKey(),
+ Optional.ofNullable(entry.getValue())
+ .map(e -> e.clone())
+ .orElse(null)),
+ HashMap::putAll)));
}
@Override
@@ -63,25 +67,11 @@ public Map asMap() {
return attributes
.entrySet()
.stream()
- .collect(Collectors.toMap(
- Map.Entry::getKey,
- e -> getValue(e.getKey())
- ));
- }
-
- /**
- * Get all values, with primitives types.
- *
- * @return all attributes on the structure into a Map
- */
- @Override
- public Map asObjectMap() {
- return attributes
- .entrySet()
- .stream()
- .collect(Collectors.toMap(
- Map.Entry::getKey,
- e -> convertValue(getValue(e.getKey()))
- ));
+ .collect(HashMap::new,
+ (accumulated, entry) -> accumulated.put(entry.getKey(),
+ Optional.ofNullable(entry.getValue())
+ .map(e -> e.clone())
+ .orElse(null)),
+ HashMap::putAll);
}
}
diff --git a/src/main/java/dev/openfeature/sdk/MutableStructure.java b/src/main/java/dev/openfeature/sdk/MutableStructure.java
index 343fe2c9..3c4f34dd 100644
--- a/src/main/java/dev/openfeature/sdk/MutableStructure.java
+++ b/src/main/java/dev/openfeature/sdk/MutableStructure.java
@@ -1,14 +1,13 @@
package dev.openfeature.sdk;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
+
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
/**
* {@link MutableStructure} represents a potentially nested object type which is used to represent
@@ -19,16 +18,14 @@
@ToString
@EqualsAndHashCode
@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"})
-public class MutableStructure implements Structure {
-
- protected final Map attributes;
+public class MutableStructure extends AbstractStructure {
public MutableStructure() {
- this.attributes = new HashMap<>();
+ super();
}
public MutableStructure(Map attributes) {
- this.attributes = new HashMap<>(attributes);
+ super(attributes);
}
@Override
@@ -92,20 +89,4 @@ public MutableStructure add(String key, List value) {
public Map asMap() {
return new HashMap<>(this.attributes);
}
-
- /**
- * Get all values, with primitives types.
- *
- * @return all attributes on the structure into a Map
- */
- @Override
- public Map asObjectMap() {
- return attributes
- .entrySet()
- .stream()
- .collect(Collectors.toMap(
- Map.Entry::getKey,
- e -> convertValue(getValue(e.getKey()))
- ));
- }
}
diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java
index 47c09388..7448ad78 100644
--- a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java
+++ b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java
@@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
@@ -100,12 +101,12 @@ public EvaluationContext getEvaluationContext() {
public void setProvider(FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
- provider,
+ provider,
this::attachEventProvider,
this::emitReady,
this::detachEventProvider,
this::emitError,
- false);
+ false);
}
}
@@ -118,12 +119,12 @@ public void setProvider(FeatureProvider provider) {
public void setProvider(String clientName, FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(clientName,
- provider,
- this::attachEventProvider,
- this::emitReady,
- this::detachEventProvider,
- this::emitError,
- false);
+ provider,
+ this::attachEventProvider,
+ this::emitReady,
+ this::detachEventProvider,
+ this::emitError,
+ false);
}
}
@@ -133,12 +134,12 @@ public void setProvider(String clientName, FeatureProvider provider) {
public void setProviderAndWait(FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
- provider,
- this::attachEventProvider,
- this::emitReady,
- this::detachEventProvider,
- this::emitError,
- true);
+ provider,
+ this::attachEventProvider,
+ this::emitReady,
+ this::detachEventProvider,
+ this::emitError,
+ true);
}
}
@@ -151,18 +152,18 @@ public void setProviderAndWait(FeatureProvider provider) {
public void setProviderAndWait(String clientName, FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(clientName,
- provider,
- this::attachEventProvider,
- this::emitReady,
- this::detachEventProvider,
- this::emitError,
- true);
+ provider,
+ this::attachEventProvider,
+ this::emitReady,
+ this::detachEventProvider,
+ this::emitError,
+ true);
}
}
private void attachEventProvider(FeatureProvider provider) {
if (provider instanceof EventProvider) {
- ((EventProvider)provider).attach((p, event, details) -> {
+ ((EventProvider) provider).attach((p, event, details) -> {
runHandlersForProvider(p, event, details);
});
}
@@ -174,7 +175,7 @@ private void emitReady(FeatureProvider provider) {
private void detachEventProvider(FeatureProvider provider) {
if (provider instanceof EventProvider) {
- ((EventProvider)provider).detach();
+ ((EventProvider) provider).detach();
}
}
@@ -229,9 +230,10 @@ public void clearHooks() {
/**
* Shut down and reset the current status of OpenFeature API.
- * This call cleans up all active providers and attempts to shut down internal event handling mechanisms.
+ * This call cleans up all active providers and attempts to shut down internal
+ * event handling mechanisms.
* Once shut down is complete, API is reset and ready to use again.
- * */
+ */
public void shutdown() {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.shutdown();
@@ -302,9 +304,9 @@ void removeHandler(String clientName, ProviderEvent event, Consumer handler) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
- // if the provider is READY, run immediately
- if (ProviderEvent.PROVIDER_READY.equals(event)
- && ProviderState.READY.equals(this.providerRepository.getProvider(clientName).getState())) {
+ // if the provider is in the state associated with event, run immediately
+ if (Optional.ofNullable(this.providerRepository.getProvider(clientName).getState())
+ .orElse(ProviderState.READY).matchesEvent(event)) {
eventSupport.runHandler(handler, EventDetails.builder().clientName(clientName).build());
}
eventSupport.addClientHandler(clientName, event, handler);
@@ -315,30 +317,36 @@ void addHandler(String clientName, ProviderEvent event, Consumer h
* Runs the handlers associated with a particular provider.
*
* @param provider the provider from where this event originated
- * @param event the event type
- * @param details the event details
+ * @param event the event type
+ * @param details the event details
*/
private void runHandlersForProvider(FeatureProvider provider, ProviderEvent event, ProviderEventDetails details) {
try (AutoCloseableLock __ = lock.readLockAutoCloseable()) {
-
+
List clientNamesForProvider = providerRepository
- .getClientNamesForProvider(provider);
-
+ .getClientNamesForProvider(provider);
+
+ final String providerName = Optional.ofNullable(provider.getMetadata())
+ .map(metadata -> metadata.getName())
+ .orElse(null);
+
// run the global handlers
- eventSupport.runGlobalHandlers(event, EventDetails.fromProviderEventDetails(details));
+ eventSupport.runGlobalHandlers(event, EventDetails.fromProviderEventDetails(details, providerName));
// run the handlers associated with named clients for this provider
- clientNamesForProvider.forEach(name -> {
- eventSupport.runClientHandlers(name, event, EventDetails.fromProviderEventDetails(details, name));
+ clientNamesForProvider.forEach(name -> {
+ eventSupport.runClientHandlers(name, event,
+ EventDetails.fromProviderEventDetails(details, providerName, name));
});
-
+
if (providerRepository.isDefaultProvider(provider)) {
// run handlers for clients that have no bound providers (since this is the default)
Set allClientNames = eventSupport.getAllClientNames();
Set boundClientNames = providerRepository.getAllBoundClientNames();
allClientNames.removeAll(boundClientNames);
allClientNames.forEach(name -> {
- eventSupport.runClientHandlers(name, event, EventDetails.fromProviderEventDetails(details, name));
+ eventSupport.runClientHandlers(name, event,
+ EventDetails.fromProviderEventDetails(details, providerName, name));
});
}
}
diff --git a/src/main/java/dev/openfeature/sdk/ProviderRepository.java b/src/main/java/dev/openfeature/sdk/ProviderRepository.java
index f3967e26..2ca3b21f 100644
--- a/src/main/java/dev/openfeature/sdk/ProviderRepository.java
+++ b/src/main/java/dev/openfeature/sdk/ProviderRepository.java
@@ -171,16 +171,6 @@ public void shutdown() {
.concat(Stream.of(this.defaultProvider.get()), this.providers.values().stream())
.distinct()
.forEach(this::shutdownProvider);
- setProvider(new NoOpProvider(),
- (FeatureProvider fp) -> {
- },
- (FeatureProvider fp) -> {
- },
- (FeatureProvider fp) -> {
- },
- (FeatureProvider fp,
- String message) -> {
- }, false);
this.providers.clear();
taskExecutor.shutdown();
}
diff --git a/src/main/java/dev/openfeature/sdk/ProviderState.java b/src/main/java/dev/openfeature/sdk/ProviderState.java
index 6685f8fe..a66d4e94 100644
--- a/src/main/java/dev/openfeature/sdk/ProviderState.java
+++ b/src/main/java/dev/openfeature/sdk/ProviderState.java
@@ -4,5 +4,17 @@
* Indicates the state of the provider.
*/
public enum ProviderState {
- READY, NOT_READY, ERROR;
+ READY, NOT_READY, ERROR, STALE;
+
+ /**
+ * Returns true if the passed ProviderEvent maps to this ProviderState.
+ *
+ * @param event event to compare
+ * @return boolean if matches.
+ */
+ boolean matchesEvent(ProviderEvent event) {
+ return this == READY && event == ProviderEvent.PROVIDER_READY
+ || this == STALE && event == ProviderEvent.PROVIDER_STALE
+ || this == ERROR && event == ProviderEvent.PROVIDER_ERROR;
+ }
}
diff --git a/src/main/java/dev/openfeature/sdk/Structure.java b/src/main/java/dev/openfeature/sdk/Structure.java
index 46274e70..6ceaf592 100644
--- a/src/main/java/dev/openfeature/sdk/Structure.java
+++ b/src/main/java/dev/openfeature/sdk/Structure.java
@@ -48,12 +48,17 @@ public interface Structure {
Map asObjectMap();
/**
- * convertValue is converting the object type Value in a primitive type.
+ * Converts the Value into its equivalent primitive type.
*
* @param value - Value object to convert
- * @return an Object containing the primitive type.
+ * @return an Object containing the primitive type, or null.
*/
default Object convertValue(Value value) {
+
+ if (value == null || value.isNull()) {
+ return null;
+ }
+
if (value.isBoolean()) {
return value.asBoolean();
}
@@ -85,15 +90,14 @@ default Object convertValue(Value value) {
if (value.isStructure()) {
Structure s = value.asStructure();
return s.asMap()
- .keySet()
+ .entrySet()
.stream()
- .collect(
- Collectors.toMap(
- key -> key,
- key -> convertValue(s.getValue(key))
- )
- );
+ .collect(HashMap::new,
+ (accumulated, entry) -> accumulated.put(entry.getKey(),
+ convertValue(entry.getValue())),
+ HashMap::putAll);
}
+
throw new ValueNotConvertableError();
}
@@ -134,7 +138,9 @@ default Map merge(Function