Compare commits

..

494 Commits
v1.9.0 ... main

Author SHA1 Message Date
renovate[bot] ac3344c7f6
chore(deps): update github/codeql-action digest to 7710ed1 (#1521)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-17 21:51:17 +00:00
renovate[bot] ecc8f7e3ad
chore(deps): update github/codeql-action digest to 03a2a17 (#1520)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-17 16:35:35 +02:00
renovate[bot] cbf7a58622
chore(deps): update dependency maven to v3.9.11 (#1519)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-16 06:57:06 +00:00
renovate[bot] 1382b367d9
chore(deps): update actions/setup-java digest to ae2b61d (#1518)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-16 03:54:58 +00:00
renovate[bot] 5b3e3656f6
chore(deps): update github/codeql-action digest to 0d17ea4 (#1517)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-15 23:46:35 +00:00
renovate[bot] 1d3fab6184
fix(deps): update dependency io.cucumber:cucumber-bom to v7.26.0 (#1516)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 16:00:25 +02:00
renovate[bot] 006ae75e2b
chore(deps): update github/codeql-action digest to 6f936b5 (#1515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 15:49:08 +02:00
renovate[bot] aa0569379b
chore(deps): update github/codeql-action digest to f53ec7c (#1512)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 01:45:44 +00:00
renovate[bot] bf68cbdedf
fix(deps): update dependency io.cucumber:cucumber-bom to v7.25.0 (#1514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-10 20:57:58 +00:00
renovate[bot] 62738f7f16
chore(deps): update dependency com.diffplug.spotless:spotless-maven-plugin to v2.45.0 (#1509)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 10:17:05 +02:00
renovate[bot] 1e8f5c880c
chore(deps): update dependency com.google.guava:guava to v33.4.8-jre (#1382)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 06:34:38 +00:00
renovate[bot] 488196656a
fix(deps): update dependency io.cucumber:cucumber-bom to v7.24.0 (#1510)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 08:28:26 +02:00
renovate[bot] 26716a51cf
chore(deps): update github/codeql-action digest to 624d0bc (#1507)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 03:14:51 +00:00
renovate[bot] 908755c2c2
chore(deps): update actions/setup-java digest to c190c18 (#1508)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 23:04:40 +00:00
OpenFeature Bot d2b1dc3a41
chore(main): release 1.16.0 (#1452)
Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-07-07 14:54:59 -04:00
Todd Baert 85d89ee79a chore: update publish env vars
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-07-07 14:42:51 -04:00
Todd Baert 6194186b3e chore: skip tests on publish
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-07-07 14:39:17 -04:00
Todd Baert 5425a34a12 chore: migrate to new publish
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-07-07 14:30:18 -04:00
renovate[bot] 957c0d1ba3
fix(deps): update dependency org.junit:junit-bom to v5.13.3 (#1505)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 19:37:31 +00:00
chrfwow ebea0fdf1c
fix: Reduce locking and concurrency issues (#1478)
* Reduce locking and concurrency issues

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* Reduce locking and concurrency issues

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* formatting

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* use concurrent data structure for hooks

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* use concurrent data structure for hooks

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

---------

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-07-04 09:17:56 -04:00
renovate[bot] 08f549afd1
chore(deps): update actions/setup-java digest to 67aec00 (#1504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 23:29:05 +00:00
renovate[bot] a5d1cbced4
chore(deps): update github/codeql-action digest to b694213 (#1503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 19:13:17 +00:00
renovate[bot] 0fd9d3dcfb
chore(deps): update github/codeql-action digest to 33f8489 (#1502)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 00:11:36 +00:00
renovate[bot] 0515ad54c4
chore(deps): update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.8 (#1501)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-02 13:05:20 +02:00
renovate[bot] 69519b1ef7
chore(deps): update github/codeql-action digest to dcc1a66 (#1499)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 20:37:12 +00:00
renovate[bot] 2e3b479cb1
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.26.1 (#1498)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 01:58:05 +00:00
renovate[bot] 49214b7282
chore(deps): update github/codeql-action digest to 4c57370 (#1497)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 23:59:31 +00:00
renovate[bot] fc430c3e1d
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.2 (#1496)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 07:35:50 +02:00
renovate[bot] 86a5916f0d
chore(deps): update github/codeql-action digest to 8ef1782 (#1495)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-26 14:54:48 +02:00
renovate[bot] 34b22e8d93
fix(deps): update dependency org.junit:junit-bom to v5.13.2 (#1492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-25 06:40:04 +00:00
renovate[bot] 300a705e0a
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.26.0 (#1494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-25 08:32:52 +02:00
renovate[bot] b64efe82d9
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.1 (#1493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-25 02:49:37 +00:00
renovate[bot] 6f67b06f71
chore(deps): update github/codeql-action digest to 9b02dc2 (#1491)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 20:50:48 +00:00
renovate[bot] e67f598357
chore(deps): update actions/setup-java digest to ebb356c (#1490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 22:42:58 +00:00
renovate[bot] 312b6df5d2
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.25.1 (#1489)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-21 21:10:50 +00:00
renovate[bot] 8fad544b17
chore(deps): update github/codeql-action digest to ac30a39 (#1488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-20 19:08:37 +00:00
renovate[bot] c3eaecdb8b
chore(deps): update github/codeql-action digest to 66d7255 (#1487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-20 01:25:24 +00:00
renovate[bot] 7c2af57a36
chore(deps): update actions/cache digest to 640a1c2 (#1485)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-17 20:05:59 +00:00
renovate[bot] 8bf777a7e9
chore(deps): update github/codeql-action digest to ef36b69 (#1484)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-17 04:48:36 +00:00
renovate[bot] 936ff60fac
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.6 (#1483)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 16:50:34 +00:00
renovate[bot] 99a3006de8
chore(deps): update github/codeql-action digest to 3de706a (#1481)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 16:44:00 +00:00
renovate[bot] 8e51e6fe10
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.6 (#1482)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 18:37:11 +02:00
renovate[bot] 844d5e244b
chore(deps): update github/codeql-action digest to be30325 (#1479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 18:52:24 +00:00
renovate[bot] 0b57bcafc1
chore(deps): update github/codeql-action digest to 466d6ce (#1477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-11 21:43:28 +00:00
chrfwow 3dd7d5d426
feat: add means of awaiting event emission, fix flaky build (#1463)
## This PR

- adds the ability to await event emissions by returning a new construct
- uses this construct in tests

⚠️ in rare cases, this could be a breaking change, but the events API is currently experimental, so we will not do a major version ubmp

### Related Issues

Fixes #1449
2025-06-10 11:27:15 -04:00
renovate[bot] 6cca721be5
chore(deps): update github/codeql-action digest to 7cb9b16 (#1476)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 01:27:44 +00:00
renovate[bot] 4481537ceb
chore(deps): update dependency maven to v3.9.10 (#1474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 21:59:01 +00:00
renovate[bot] b5d873e44d
chore(deps): update actions/checkout digest to 09d2aca (#1473)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 17:39:13 +00:00
renovate[bot] 545d6aac09
fix(deps): update dependency org.junit:junit-bom to v5.13.1 (#1475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 13:08:10 +00:00
renovate[bot] 2dcd6a1dd0
chore(deps): update github/codeql-action digest to b1e4dc3 (#1471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 06:27:45 +00:00
Simon Schrottner 3ed65cfb0c
chore: remove unneeded version information (#1428)
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-06-04 14:44:38 +00:00
renovate[bot] 6597de7a98
chore(deps): update github/codeql-action digest to 075e08a (#1470)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 18:05:22 +00:00
renovate[bot] 376f81f5c3
chore(deps): update github/codeql-action digest to 4a00331 (#1469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 19:28:18 +00:00
renovate[bot] 1558a86249
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.25.0 (#1468)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-31 21:27:57 +00:00
renovate[bot] f8260a1c3a
fix(deps): update junit5 monorepo (#1467)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 21:02:38 +00:00
renovate[bot] 50a6b168a7
fix(deps): update dependency io.cucumber:cucumber-bom to v7.23.0 (#1466)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 05:38:25 +00:00
renovate[bot] b6ceff2ecb
chore(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.1 (#1461)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 02:01:25 +00:00
renovate[bot] 2de7616676
chore(deps): update io.cucumber.version to v7.23.0 (#1465)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-29 23:00:03 +00:00
renovate[bot] f10aaaa357
chore(deps): update github/codeql-action digest to 7fd6215 (#1464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 22:25:40 +00:00
renovate[bot] 40b319c5de
chore(deps): update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.5 (#1462)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 04:12:52 +00:00
renovate[bot] 5e922cf3ef
chore(deps): update github/codeql-action digest to bc02a25 (#1460)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-27 22:26:25 +00:00
renovate[bot] 6a95c008e9
chore(deps): update github/codeql-action digest to 7b0fb5a (#1459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 22:59:22 +00:00
renovate[bot] dcbfd265a3
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.24.0 (#1458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 06:29:34 +00:00
renovate[bot] e17b0b2975
chore(deps): update dependency org.mockito:mockito-core to v5.18.0 (#1457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 04:08:45 +00:00
renovate[bot] b45a937017
chore(deps): update github/codeql-action digest to 396fd27 (#1456)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 23:54:03 +00:00
renovate[bot] 36eed065e7
chore(deps): update github/codeql-action digest to 57eebf6 (#1455)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 15:06:06 +00:00
renovate[bot] e3379395e6
chore(deps): update codecov/codecov-action action to v5.4.3 (#1454)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 01:40:23 +00:00
renovate[bot] b667aa3251
chore(deps): update github/codeql-action digest to b86edfc (#1453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 20:01:17 +00:00
Todd Baert 1714efe81a
chore: improvements to release workflow (#1451)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: chrfwow <christian.lutnik@dynatrace.com>
2025-05-15 11:22:10 -04:00
renovate[bot] d9a72d2aaf
chore(deps): update github/codeql-action digest to 510dfa3 (#1450)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-14 22:43:05 +00:00
OpenFeature Bot cfd9512728
chore(main): release 1.15.1 (#1448)
* chore(main): release 1.15.1

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>

* fixup: change version

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-05-14 14:12:11 +02:00
Todd Baert f6bd30db93
chore: update boostrap sha for release please
Creating a new build

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-05-14 07:57:13 -04:00
chrfwow e2813b2e5d
feat: add logging on provider state transitions (#1444)
* NOISSUE add logging on provider state transitions

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix npe

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix failing test

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix failing test

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* format

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

---------

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-05-14 11:11:36 +02:00
renovate[bot] bc10bacb5a
chore(deps): update github/codeql-action digest to 15bce5b (#1443)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-13 22:40:47 +00:00
OpenFeature Bot 7182a7fc41
chore(main): release 1.15.0 (#1431)
Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-05-13 12:38:55 -04:00
Liran M d0ae548277
feat: add telemetry helper utils (#1346)
* feat: add telemetry helper utils

Signed-off-by: liran2000 <liran2000@gmail.com>

* updates

Signed-off-by: liran2000 <liran2000@gmail.com>

* fixup: apply changes according to the semconv

The semconv has changed, and some attributes have been
renamed. Furthermore, the body usage is deprecated
and should be part of the attributes.

see: https://github.com/open-telemetry/semantic-conventions/pull/1990/
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

* fixup: fix tests

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

* fixup: fix spotless

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: liran2000 <liran2000@gmail.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-05-13 09:45:16 +02:00
renovate[bot] e568f3a4f5
fix(deps): update dependency io.cucumber:cucumber-bom to v7.22.2 (#1442)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 07:07:53 +00:00
renovate[bot] 58454b4eaa
chore(deps): update io.cucumber.version to v7.22.2 (#1441)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 09:01:29 +02:00
renovate[bot] 78657ee79e
chore(deps): update dependency com.tngtech.archunit:archunit-junit5 to v1.4.1 (#1440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-08 03:06:04 +00:00
renovate[bot] 3403510515
chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10 (#103)
* chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10

* Fix javadoc format

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

---------

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-05-06 06:19:41 +00:00
jarebudev 4dc988b637
feat!: Raise required Java version to 11 (#1393)
* bumped to java 11, altered CI to target java 11

Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com>

* changed profile and toolchain

Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com>

* corrected toolchain version

Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com>

---------

Signed-off-by: jarebudev <23311805+jarebudev@users.noreply.github.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-05-05 09:30:23 +00:00
renovate[bot] f2348ea370
chore(deps): update github/codeql-action digest to 5eb3ed6 (#1439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 18:13:36 +00:00
renovate[bot] 85b200a08b
chore(deps): update github/codeql-action digest to 97a2bfd (#1438)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 18:38:45 +00:00
renovate[bot] f965cbcb37
chore(deps): update github/codeql-action digest to 40e16ed (#1437)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 23:46:35 +00:00
renovate[bot] b09e88798f
chore(deps): update github/codeql-action digest to ed51cb5 (#1436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 19:28:15 +00:00
renovate[bot] 7e74f2aa3a
chore(deps): update github/codeql-action digest to 83605b3 (#1435)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 02:56:28 +00:00
renovate[bot] 62ba6db457
chore(deps): update amannn/action-semantic-pull-request digest to 3352882 (#1434)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 20:32:23 +00:00
Abhay Porwal 96cf9c7f54
docs: add try-catch example for setProviderAndWait usage (#1433)
* added the detailed instructions for the setProviderAndWait

Signed-off-by: Abhay <abhayakg123@gmail.com.com>

* fixup: checkstyle issues

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: Abhay <abhayakg123@gmail.com.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Abhay <abhayakg123@gmail.com.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-04-28 14:34:19 +02:00
renovate[bot] 99faaf88aa
chore(deps): update github/codeql-action digest to f843d94 (#1432)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 22:07:09 +00:00
Todd Baert 1cc851b293
chore: update release please action (#1430)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-24 21:41:37 -04:00
Todd Baert 32137bfa82
chore: add DCO to release please (#1429)
* chore: add DCO to release please

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update release-please-config.json

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-24 21:14:07 -04:00
Todd Baert 45ec4b1b77
chore: add DCO to release please
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-24 20:58:47 -04:00
Todd Baert 014f8a59da
chore: use PAT for release please
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-24 19:32:45 -04:00
renovate[bot] 1c4d2efafd
fix(deps): update dependency io.cucumber:cucumber-bom to v7.22.1 (#1427)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 18:19:32 +00:00
renovate[bot] 844374a42b
chore(deps): update io.cucumber.version to v7.22.1 (#1426)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 15:19:34 +00:00
renovate[bot] a7828e73a8
chore(deps): update github/codeql-action digest to 4ffa236 (#1425)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 22:47:18 +00:00
renovate[bot] 6b6849f3a3
chore(deps): update github/codeql-action digest to 2a8cbad (#1423)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 19:25:23 +00:00
renovate[bot] 495da271be
chore(deps): update dependency com.h3xstream.findsecbugs:findsecbugs-plugin to v1.14.0 (#1422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 10:02:26 +00:00
renovate[bot] e19ccaa35d
chore(deps): update dependency org.jacoco:jacoco-maven-plugin to v0.8.13 (#1407)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-18 08:15:55 +02:00
Simon Schrottner 498fd38265
chore: update codeowners to give global maintainers code ownership (#1412)
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-04-17 11:33:57 -04:00
renovate[bot] a3e2a59aeb
chore(deps): update actions/setup-java digest to f4f1212 (#1421)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-16 21:41:52 +00:00
Todd Baert 665dd51eb2
chore: add publish env (#1420)
* chore: add publish env

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update release.yml

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update merge.yml

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-16 12:45:16 -04:00
renovate[bot] a6389e89f6
chore(deps): update codecov/codecov-action action to v5.4.2 (#1419)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 03:44:53 +00:00
renovate[bot] 97b442ed6e
fix(deps): update junit5 monorepo (#1418)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 21:45:27 +00:00
renovate[bot] 0c77c84460
chore(deps): update github/codeql-action digest to 4c3e536 (#1417)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 02:21:54 +00:00
renovate[bot] 4607c62f15
chore(deps): update github/codeql-action digest to 56dd02f (#1416)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 22:09:23 +00:00
renovate[bot] a5789038ac
chore(deps): update actions/setup-java digest to c5195ef (#1415)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 23:02:50 +00:00
renovate[bot] e066d3f749
chore(deps): update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.4 (#1414)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 06:34:39 +00:00
renovate[bot] 5b327eeb77
chore(deps): update github/codeql-action digest to d26c46a (#1413)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 01:31:00 +00:00
renovate[bot] e25181982a
fix(deps): update dependency io.cucumber:cucumber-bom to v7.22.0 (#1411)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 10:23:07 +00:00
renovate[bot] 3c69f2f36c
chore(deps): update io.cucumber.version to v7.22.0 (#1410)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 06:25:16 +00:00
renovate[bot] 345cdcfa10
chore(deps): update dependency org.mockito:mockito-core to v5.17.0 (#1409)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 18:42:05 +00:00
renovate[bot] ca160cab7c
chore(deps): update github/codeql-action digest to 362ef4c (#1408)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 18:12:31 +00:00
renovate[bot] e211397d51
chore(deps): update github/codeql-action digest to e13fe0d (#1406)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 02:18:17 +00:00
renovate[bot] 5b2f1513ab
chore(deps): update github/codeql-action digest to dab8a02 (#1405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 17:47:53 +00:00
renovate[bot] f834e11acc
chore(deps): update actions/setup-java digest to 148017a (#1404)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 22:21:36 +00:00
renovate[bot] ef32f11571
fix(deps): update dependency org.projectlombok:lombok to v1.18.38 (#1403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 03:02:58 +00:00
renovate[bot] 07301bda3f
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.5 (#1401)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 23:11:43 +00:00
renovate[bot] 384953d30e
chore(deps): update github/codeql-action digest to efffb48 (#1402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 18:29:21 +00:00
renovate[bot] 1f2d071508
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.5 (#1400)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 15:00:52 +00:00
renovate[bot] d6ebc161a9
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.3 (#1399)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 10:47:07 +00:00
renovate[bot] 1fcf0e77d9
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.3 (#1398)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 05:38:29 +00:00
renovate[bot] 37d76be697
chore(deps): update github/codeql-action digest to 9f45e74 (#1396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-28 23:26:09 +00:00
renovate[bot] d7b591c9f9
chore(deps): update github/codeql-action digest to 9bd18b4 (#1394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-27 23:40:23 +00:00
github-actions[bot] 7f54c334da
chore(main): release 1.14.2 (#1334)
* chore(main): release 1.15.0

* Update CHANGELOG.md

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update .release-please-manifest.json

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update CHANGELOG.md

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update version.txt

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update README.md

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update README.md

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update pom.xml

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-03-27 15:48:06 -04:00
Todd Baert 24ef9dd290
fix: hooks not run in NOT_READY/FATAL (#1392)
* fix: hooks not run in NOT_READY/FATAL

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-03-27 09:22:19 -04:00
renovate[bot] 753667925a
chore(deps): update actions/setup-java digest to 3b6c050 (#1391)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-26 07:41:23 +00:00
renovate[bot] 87c06d9edd
chore(deps): update amannn/action-semantic-pull-request digest to 04501d4 (#1390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 16:35:34 +00:00
renovate[bot] 85fd5e0997
chore(deps): update github/codeql-action digest to 486ab5a (#1389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 02:02:27 +00:00
renovate[bot] d8f6514598
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.4 (#1388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 13:00:33 +00:00
renovate[bot] cb574d93b6
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.4 (#1387)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 07:03:02 +00:00
renovate[bot] 4125ae8380
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.3 (#1385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 10:02:36 +00:00
renovate[bot] 387e5f2e3b
chore(deps): update github/codeql-action digest to e0ea141 (#1386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 05:11:28 +00:00
renovate[bot] b6becac2c4
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.3 (#1384)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 03:00:07 +00:00
renovate[bot] 922e17e677
chore(deps): update github/codeql-action digest to bd1d9ab (#1383)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-21 22:54:41 +00:00
renovate[bot] d61c33e466
chore(deps): update github/codeql-action digest to c50c157 (#1379)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 07:07:31 +00:00
renovate[bot] 2239f054b9
chore(deps): update actions/setup-java digest to b8ebb8b (#1381)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 01:33:47 +00:00
renovate[bot] 8359ef13bb
chore(deps): update actions/cache digest to 5a3ec84 (#1380)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 21:41:15 +00:00
renovate[bot] dbf92df33b
chore(deps): update github/codeql-action digest to 6349095 (#1378)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 18:41:01 +00:00
renovate[bot] 706565581d
chore(deps): update github/codeql-action digest to 6a151cd (#1377)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 02:01:21 +00:00
renovate[bot] 9750f75d04
chore(deps): update dependency org.mockito:mockito-core to v5.16.1 (#1376)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-16 05:21:02 +00:00
renovate[bot] de3e213ac8
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.0 (#1375)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-16 02:24:15 +00:00
renovate[bot] 6b65e26c74
fix(deps): update junit5 monorepo (#1373)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 06:28:22 +00:00
renovate[bot] d233480912
chore(deps): update github/codeql-action digest to 70df9de (#1372)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 01:29:33 +00:00
chrfwow 69b571eda7
fix: equals and hashcode of several classes (#1364)
fix: equals and hashcode of several classes
2025-03-13 08:33:21 +01:00
renovate[bot] f8df5fb84a
chore(deps): update github/codeql-action digest to dc49dca (#1369)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 03:22:53 +00:00
renovate[bot] d54c68a8e9
chore(deps): update github/codeql-action digest to 7254660 (#1368)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-11 23:00:23 +00:00
renovate[bot] c550d59722
chore(deps): update github/codeql-action digest to b46b37a (#1367)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 22:21:34 +00:00
renovate[bot] d00e4b5b24
chore(deps): update github/codeql-action digest to b2e6519 (#1366)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 22:43:13 +00:00
chrfwow c37d249776
feat: implement gherkin tests for context merging (#1363)
feat: implement gherkin tests for context merging (#1363)
2025-03-07 11:04:46 +01:00
renovate[bot] 959e675e4c
chore(deps): update github/codeql-action digest to 56b25d5 (#1365)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 19:34:13 +00:00
renovate[bot] 67b34f84a3
chore(deps): update github/codeql-action digest to 608ccd6 (#1361)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 19:07:16 +00:00
renovate[bot] 30b6d004aa
chore(deps): update dependency org.mockito:mockito-core to v5.16.0 (#1358)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 15:10:03 +00:00
renovate[bot] ecea9df932
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.2.0 (#1360)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 10:30:29 +00:00
renovate[bot] 6c03e5d84a
chore(deps): update github/codeql-action digest to 80f9930 (#1357)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 06:25:17 +00:00
renovate[bot] 31444d6c8f
chore(deps): update actions/setup-java digest to 799ee7c (#1359)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 02:12:10 +00:00
renovate[bot] dd83114c4d
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.2 (#1356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 23:33:51 +00:00
renovate[bot] 2a1adca8c2
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.2 (#1355)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 17:40:45 +00:00
renovate[bot] 59017977a4
chore(deps): update actions/cache digest to d4323d4 (#1353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 18:39:13 +00:00
renovate[bot] 989f4ae542
chore(deps): update github/codeql-action digest to 8392354 (#1352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 16:13:25 +00:00
renovate[bot] b133c2fa52
chore(deps): update codecov/codecov-action action to v5.4.0 (#1351)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 06:59:17 +00:00
renovate[bot] 7df9565691
chore(deps): update github/codeql-action digest to 97aac9b (#1350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-26 23:30:46 +00:00
renovate[bot] 2ec7c6c7ff
fix(deps): update dependency org.slf4j:slf4j-api to v2.0.17 (#1348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-26 02:09:26 +00:00
renovate[bot] 698756856b
chore(deps): update github/codeql-action digest to 8c69433 (#1347)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 21:49:59 +00:00
renovate[bot] 5de33c02a6
chore(deps): update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.3 (#1341)
* chore(deps): update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.3

* fixup: fix spotless violation

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-02-25 08:15:15 +01:00
renovate[bot] de64eddfb3
chore(deps): update github/codeql-action digest to a8849fb (#1345)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 06:00:41 +00:00
renovate[bot] d95e270653
fix(deps): update junit5 monorepo (#1344)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 09:50:37 +00:00
renovate[bot] 1504d0f798
chore(deps): update dependency org.awaitility:awaitility to v4.3.0 (#1343)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 07:00:59 +00:00
renovate[bot] 88a778cc03
chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 (#1342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 01:27:57 +00:00
renovate[bot] 50b45b2be4
chore(deps): update github/codeql-action digest to ff79de6 (#1340)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 21:38:42 +00:00
chrfwow dd9227a924
feat: update test harness with metadata assertions #1467 (#1319)
* feat: implement gherkin tests

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fixup! feat: implement gherkin tests

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fixup! feat: implement gherkin tests

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fixup! feat: implement gherkin tests

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fixup: add version for dependency

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-02-19 16:27:46 +01:00
renovate[bot] cdcdc143ea
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.1.0 (#1332)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-19 10:06:15 +00:00
renovate[bot] 3920c638a4
chore(deps): update actions/cache digest to 7921ae2 (#1337)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-19 06:22:52 +00:00
renovate[bot] 4e535fd10f
chore(deps): update github/codeql-action digest to d99c7e8 (#1338)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-19 02:13:36 +00:00
renovate[bot] 4817864fd7
chore(deps): update dependency org.mockito:mockito-core to v5.15.2 (#1339)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 22:10:34 +01:00
Simon Schrottner 90217b2083
chore: update build and tooling to utilize new java version (#1321)
* chore: update build and tooling to utilize new java version

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

* Fix failing test

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* chore: update build and tooling to utilize new java version

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: christian.lutnik <christian.lutnik@dynatrace.com>
2025-02-18 21:58:17 +01:00
Simon Schrottner 88baa65dd0
test: Reduce usage of singelton within our tests and implementations (#1331)
Our tests are great, but often we rely on our own Singelton for testing purposes.
This can create concurrency issues or make testing really hard.
By instantiating a own API object for each test we ensure that we are not messing
with each other.
Furthermore we should not use `.getInstance()` within our own implementation.

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-18 19:19:18 +01:00
renovate[bot] e163ce1c06
chore(deps): update github/codeql-action digest to 1bb15d0 (#1336)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:48:26 +00:00
renovate[bot] 5436eb0d5d
chore(deps): update github/codeql-action digest to acadfed (#1335)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 02:28:02 +00:00
renovate[bot] 859a36cbfa
chore(deps): update github/codeql-action digest to 8c1551c (#1333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 18:05:19 +00:00
github-actions[bot] 9e782308d3
chore(main): release 1.14.1 (#1278)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-17 11:18:26 +01:00
renovate[bot] 4ba5695eee
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.1 (#1330)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-14 18:13:42 +00:00
renovate[bot] 9ab26182ea
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.1 (#1329)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-14 14:13:05 +00:00
Philipp Fehre c33ac2d9b2
fix: possible event-related deadlocks with some providers (#1314)
* Move event emitting off the main thread to avoid deadlocks

When stacking event emitting inside an EventProvider, when using sychronization
the EventProvider can deadlock, to avoid this move the event emitting of the
main thread.

Signed-off-by: Philipp Fehre <philipp@fehre.co.uk>

* Test fixes

Test provider should respect the init-delay during all test

Signed-off-by: Philipp Fehre <philipp@fehre.co.uk>

* Add timeout to EventProviderTest

With the events being executed on a different thread, we need to wait to make
sure the thread is scheduled to have the events emitted.

Signed-off-by: Philipp Fehre <philipp@fehre.co.uk>

* Don't reuse the JVM Process

Signed-off-by: Philipp Fehre <philipp@fehre.co.uk>

---------

Signed-off-by: Philipp Fehre <philipp@fehre.co.uk>
Co-authored-by: Philipp Fehre <philipp.fehre@mollie.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-13 14:01:58 -05:00
Jonathan Norris 08c38fb553
fix: TrackingEventDetails interface to include numeric getValue() call (#1328)
Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
2025-02-13 13:50:19 -05:00
renovate[bot] 3baf0df966
chore(deps): update github/codeql-action digest to 1c15a48 (#1325)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-13 02:02:06 +00:00
renovate[bot] 69cdc772a6
chore(deps): update actions/cache digest to 9fa7e61 (#1324)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 22:35:36 +00:00
renovate[bot] 8f3ced5907
chore(deps): update github/codeql-action digest to affec20 (#1323)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-12 11:46:13 +00:00
renovate[bot] 538140dfe7
chore(deps): update github/codeql-action digest to 6063925 (#1320)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-11 09:32:43 +00:00
renovate[bot] b7978832b7
fix(deps): update dependency io.cucumber:cucumber-bom to v7.21.1 (#1317)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 20:56:17 +00:00
renovate[bot] 26e1d7fff3
chore(deps): update github/codeql-action digest to 0a35e8f (#1316)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 17:53:29 +00:00
renovate[bot] 46903c6f27
chore(deps): update github/codeql-action digest to 24e1c2d (#1315)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 18:53:02 +00:00
renovate[bot] 37ed6a424c
chore(deps): update github/codeql-action digest to 08bc0cf (#1313)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 02:27:14 +00:00
renovate[bot] 208411e723
fix(deps): update dependency io.cucumber:cucumber-bom to v7.21.0 (#1312)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 09:58:39 +01:00
renovate[bot] 9a1e9abd64
chore(deps): update github/codeql-action digest to 0701025 (#1311)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 21:39:36 +00:00
renovate[bot] 40fa173338
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.17.0 (#1310)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 12:26:19 +00:00
renovate[bot] cda34053f7
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.17.0 (#1309)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 09:03:12 +00:00
renovate[bot] 99d818572a
chore(deps): update github/codeql-action digest to e9987ad (#1308)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 04:28:35 +00:00
renovate[bot] 6f36434c52
chore(deps): update github/codeql-action digest to 54b1c84 (#1307)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 01:46:15 +00:00
renovate[bot] ba9cc4b85a
chore(deps): update actions/setup-java digest to 3a4f6e1 (#1306)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 22:03:11 +00:00
renovate[bot] 7916d76635
chore(deps): update github/codeql-action digest to 5f4f998 (#1305)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 13:26:01 +00:00
renovate[bot] 6874de64ce
chore(deps): update github/codeql-action digest to 43cffee (#1304)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 01:53:26 +00:00
renovate[bot] f9fa54be49
chore(deps): update codecov/codecov-action action to v5.3.1 (#1303)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-25 04:32:24 +00:00
renovate[bot] 78adc77c23
chore(deps): update github/codeql-action digest to e7c0c9d (#1302)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-25 01:31:55 +00:00
renovate[bot] f7f6586d72
chore(deps): update codecov/codecov-action action to v5.3.0 (#1301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 05:39:08 +00:00
renovate[bot] 34919561b7
chore(deps): update github/codeql-action digest to 7e3036b (#1300)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 02:00:19 +00:00
renovate[bot] 531fc385b6
chore(deps): update codecov/codecov-action action to v5.2.0 (#1298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-23 04:46:04 +00:00
renovate[bot] 305e0329e7
chore(deps): update github/codeql-action digest to b44b19f (#1297)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-23 00:49:44 +00:00
renovate[bot] 874e86df5c
chore(deps): update actions/setup-java digest to 28b532b (#1296)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 04:49:00 +00:00
renovate[bot] 122e82f843
chore(deps): update github/codeql-action digest to f89b8a7 (#1295)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 22:08:52 +00:00
renovate[bot] 5671184e7f
chore(deps): update github/codeql-action digest to d90e07f (#1294)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 01:24:58 +00:00
renovate[bot] 6071932cb4
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.16.1 (#1293)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-19 16:48:47 +00:00
renovate[bot] 0af9f2901f
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.16.1 (#1292)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-19 12:47:02 +00:00
renovate[bot] a5eb21d1a2
chore(deps): update dependency org.assertj:assertj-core to v3.27.3 (#1291)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 17:02:55 +00:00
renovate[bot] 6c4205a008
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.16.0 (#1290)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 08:26:00 +00:00
renovate[bot] 0b5b423bdd
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.16.0 (#1289)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 04:42:09 +00:00
renovate[bot] 882d2dd5bd
chore(deps): update github/codeql-action digest to 0f1559a (#1286)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-17 09:37:40 +00:00
renovate[bot] c69d3a4bd1
chore(deps): update actions/setup-java digest to 51ab6d2 (#1288)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-17 05:22:11 +00:00
renovate[bot] 640e35e853
chore(deps): update actions/checkout digest to 85e6279 (#1287)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-17 01:30:43 +00:00
renovate[bot] 32a39335de
chore(deps): update actions/setup-java digest to 99d3141 (#1285)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 21:00:50 +00:00
renovate[bot] 45b3995bda
chore(deps): update github/codeql-action digest to 93da9f2 (#1283)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-16 01:12:12 +00:00
renovate[bot] b390d5f0b0
chore(deps): update github/codeql-action digest to 3b4f4d9 (#1282)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-15 16:46:16 +00:00
renovate[bot] 8a1ab7ea18
chore(deps): update github/codeql-action digest to 1efc6bb (#1281)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 23:40:55 +00:00
renovate[bot] a3854d6ab1
chore(deps): update github/codeql-action digest to 10a3f07 (#1280)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 01:08:23 +00:00
renovate[bot] b997946db1
chore(deps): update github/codeql-action digest to db7177a (#1279)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-11 06:42:17 +00:00
renovate[bot] c2a82dbdba
chore(deps): update github/codeql-action digest to 87fc816 (#1277)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 21:58:22 +00:00
github-actions[bot] 9274c117ab
chore(main): release 1.14.0 (#1242)
* chore(main): release 1.14.0

* Update CHANGELOG.md

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-10 15:10:55 -05:00
renovate[bot] 9c92ebb1bd
chore(deps): update github/codeql-action digest to e83e0a4 (#1275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 10:17:41 +00:00
renovate[bot] d825ff8363
chore(deps): update actions/cache digest to 36f1e14 (#1274)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 06:08:41 +00:00
chrfwow ae85278c30
feat: Add evaluation details to finally hook stage #1246 (#1262)
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-09 16:12:14 -05:00
renovate[bot] 3c97b7baaf
chore(deps): update github/codeql-action digest to fb65b6c (#1273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 23:21:18 +00:00
renovate[bot] 4086dea703
chore(deps): update github/codeql-action digest to 3407610 (#1269)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 00:40:07 +00:00
renovate[bot] a1c558f4ff
chore(deps): update actions/cache digest to 53aa38c (#1270)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 21:06:18 +00:00
renovate[bot] 2e10d34920
chore(deps): update dependency org.assertj:assertj-core to v3.27.2 (#1268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-04 15:14:06 +00:00
renovate[bot] 20bbb2337c
chore(deps): update dependency org.assertj:assertj-core to v3.27.1 (#1266)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 18:24:06 +00:00
Simon Schrottner 64ec68bcf5
build: change checkstyle to google code format, plus adding spotless (#1264)
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-01-03 19:06:22 +01:00
renovate[bot] f1817d8fef
chore(deps): update github/codeql-action digest to 5b6e617 (#1263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 23:06:59 +00:00
renovate[bot] fc6f35e581
chore(deps): update github/codeql-action digest to 7876007 (#1260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-21 00:46:09 +00:00
renovate[bot] c62ade3878
chore(deps): update dependency org.assertj:assertj-core to v3.27.0 (#1258)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 01:39:52 +00:00
renovate[bot] 6d60c962fb
chore(deps): update github/codeql-action digest to d01b25e (#1257)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 22:28:15 +00:00
renovate[bot] 992c00396c
chore(deps): update github/codeql-action digest to 64cc90b (#1256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 04:03:19 +00:00
renovate[bot] d274cdac37
chore(deps): update codecov/codecov-action action to v5.1.2 (#1255)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 02:15:10 +00:00
renovate[bot] 6a7987455e
chore(deps): update github/codeql-action digest to 562042d (#1254)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 03:34:59 +00:00
renovate[bot] f39c4b5af5
chore(deps): update dependency com.google.guava:guava to v33.4.0-jre (#1253)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-17 06:20:23 +00:00
renovate[bot] 482a5aef10
chore(deps): update github/codeql-action digest to 9d59969 (#1252)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 22:56:34 +00:00
renovate[bot] 834f720718
fix(deps): update junit5 monorepo (#1251)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 18:39:04 +00:00
renovate[bot] 6772d3f394
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.11 (#1250)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 18:15:18 +00:00
renovate[bot] 6d169f55e2
chore(deps): update github/codeql-action digest to dd75594 (#1247)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 15:06:36 +00:00
renovate[bot] 4440cda6a5
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.11 (#1249)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 12:48:35 +00:00
renovate[bot] 86e18c5d28
chore(deps): update actions/setup-java digest to 7a6d8a8 (#1248)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-13 01:31:22 +00:00
renovate[bot] 9acc8612a5
chore(deps): update actions/setup-java digest to 7136edc (#1244)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-12 00:54:52 +00:00
renovate[bot] fd1c1702c6
chore(deps): update github/codeql-action digest to 78d0136 (#1245)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 22:04:18 +00:00
renovate[bot] 884f8fbf77
chore(deps): update github/codeql-action digest to 4d64ab6 (#1243)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 01:28:12 +00:00
renovate[bot] b0abfd02cf
chore(deps): update github/codeql-action digest to 8975792 (#1241)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 01:20:08 +00:00
github-actions[bot] cacacc2615
chore(main): release 1.13.0 (#1185)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-09 08:48:34 -05:00
renovate[bot] c87c6e7a76
chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.11.2 (#1240)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-07 16:29:04 +00:00
renovate[bot] baaa78b7ec
chore(deps): update github/codeql-action digest to 6f9e628 (#1239)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 21:55:48 +00:00
warber 64ad644bdb
feat: add tracking as per spec (#1228)
feat: add tracking as per spec

---------

Signed-off-by: Bernd Warmuth <bernd.warmuth@dynatrace.com>
2024-12-06 10:19:36 -05:00
renovate[bot] c5ad1b4d4f
chore(deps): update codecov/codecov-action action to v5.1.1 (#1238)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 01:03:17 +00:00
renovate[bot] da725d89e0
chore(deps): update actions/cache digest to 1bd1e32 (#1237)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 23:08:11 +00:00
warber 473be8659c
test: Update gherkin test sub module (#1236)
Signed-off-by: Bernd Warmuth <bernd.warmuth@dynatrace.com>
2024-12-05 16:10:49 +00:00
renovate[bot] 409fd042f3
chore(deps): update github/codeql-action digest to 3096afe (#1235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-04 17:02:17 +00:00
renovate[bot] bb3272d364
chore(deps): update github/codeql-action digest to 978ed82 (#1234)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-04 03:31:19 +00:00
renovate[bot] 5b460ead7e
chore(deps): update github/codeql-action digest to f1c289a (#1233)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 22:13:25 +00:00
renovate[bot] b3549a1b4a
chore(deps): update github/codeql-action digest to ef2fd42 (#1232)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:31:38 +00:00
renovate[bot] 4bbaf51753
chore(deps): update github/codeql-action digest to af49565 (#1231)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-02 20:25:33 +00:00
renovate[bot] 764d6650e6
chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.9.1 (#1230)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-30 01:23:12 +00:00
renovate[bot] a0723ec2f8
chore(deps): update github/codeql-action digest to 3d3d628 (#1229)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-22 16:44:33 +00:00
renovate[bot] 234062cf33
chore(deps): update codecov/codecov-action action to v5.0.7 (#1227)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 08:03:20 +00:00
renovate[bot] 13811dcf25
chore(deps): update codecov/codecov-action action to v5.0.6 (#1226)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 22:34:42 +00:00
renovate[bot] 3227623425
chore(deps): update github/codeql-action digest to f8e782a (#1225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 20:34:21 +00:00
renovate[bot] 19ed5c7c97
chore(deps): update codecov/codecov-action action to v5.0.4 (#1224)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 09:22:54 +00:00
renovate[bot] e91194ae16
chore(deps): update codecov/codecov-action action to v5.0.3 (#1223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 01:33:05 +00:00
renovate[bot] bbc934c6d9
chore(deps): update github/codeql-action digest to a6c8729 (#1222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-19 21:43:05 +00:00
renovate[bot] 37f0f06467
chore(deps): update github/codeql-action digest to cba5fb5 (#1221)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-19 06:19:31 +00:00
renovate[bot] 45d0656520
chore(deps): update github/codeql-action digest to e782c3a (#1220)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-19 01:32:36 +00:00
renovate[bot] 9cadc71d9d
fix(deps): update dependency org.projectlombok:lombok to v1.18.36 (#1219)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-16 00:02:00 +00:00
renovate[bot] 1b4947f108
chore(deps): update codecov/codecov-action action to v5.0.2 (#1218)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-15 18:10:46 +00:00
renovate[bot] 7aa77b8614
chore(deps): update codecov/codecov-action action to v5 (#1217)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-15 01:13:12 +00:00
renovate[bot] 6d3bb69420
chore(deps): update github/codeql-action digest to a1695c5 (#1215)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 21:40:29 +00:00
renovate[bot] 273efc62a7
chore(deps): update actions/checkout digest to cbb7224 (#1216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 18:24:10 +00:00
renovate[bot] 9f37927eaa
chore(deps): update github/codeql-action digest to 6e3a010 (#1214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 00:23:20 +00:00
renovate[bot] 92c87913ac
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.6 (#1213)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-13 13:34:11 +00:00
renovate[bot] d5228f5ccf
chore(deps): update amannn/action-semantic-pull-request digest to 40166f0 (#1212)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-13 10:56:56 +00:00
renovate[bot] 1df54411b7
chore(deps): update github/codeql-action digest to 024283f (#1211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-13 02:52:28 +00:00
renovate[bot] a94bd37cff
chore(deps): update github/codeql-action digest to 5cb4249 (#1210)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-12 15:51:48 +00:00
renovate[bot] 1c21d2444b
chore(deps): update github/codeql-action digest to 4dc1519 (#1209)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 21:47:01 +00:00
renovate[bot] a3ced47e5d
chore(deps): update dependency org.simplify4u:slf4j2-mock to v2.4.0 (#1208)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-09 03:31:56 +00:00
renovate[bot] 21dbd3fc4c
chore(deps): update github/codeql-action digest to acb9cb1 (#1207)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-09 00:41:31 +00:00
renovate[bot] 446e2987e9
chore(deps): update actions/checkout digest to 3b9b8c8 (#1206)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-08 22:08:50 +00:00
renovate[bot] eb4f625561
chore(deps): update github/codeql-action digest to 3ef4c08 (#1205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-07 21:14:36 +00:00
renovate[bot] 3a9fd60fd4
chore(deps): update github/codeql-action digest to 5ac2ddd (#1204)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-07 04:42:35 +00:00
renovate[bot] 2bb2ed3992
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.10 (#1203)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 08:19:14 +00:00
renovate[bot] d959059177
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.10 (#1202)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-04 04:58:15 +00:00
renovate[bot] d2cb092b09
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.2 (#1200)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 09:11:03 +00:00
renovate[bot] a2a57ab8f1
chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.11.1 (#1201)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 07:13:45 +00:00
renovate[bot] 08da9a3439
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.2 (#1199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 05:20:51 +00:00
renovate[bot] e32a712615
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.9 (#1198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 02:15:10 +00:00
renovate[bot] 54a234519f
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.9 (#1197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-02 21:30:23 +00:00
renovate[bot] 30eb2ce082
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.8 (#1196)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-02 03:05:33 +00:00
renovate[bot] 309f28b520
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.8 (#1195)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-02 00:57:59 +00:00
renovate[bot] 2dba3a737d
chore(deps): update github/codeql-action digest to cbe1897 (#1194)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-01 23:08:42 +00:00
renovate[bot] 8621944633
chore(deps): update github/codeql-action digest to 48c3e26 (#1193)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-31 20:31:28 +00:00
renovate[bot] f99de6fa55
chore(deps): update github/codeql-action digest to 9f93f47 (#1191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-30 01:45:47 +00:00
renovate[bot] f3163dfbd4
chore(deps): update github/codeql-action digest to 6a38de6 (#1190)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-29 02:15:51 +00:00
renovate[bot] d5082cd5f6
chore(deps): update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.26.0 (#1189)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 22:40:51 +00:00
renovate[bot] 89c7f85da4
chore(deps): update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.6.0 (#1188)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-26 03:41:50 +00:00
renovate[bot] 5c7c28706e
chore(deps): update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.8.1 (#1187)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-26 01:56:27 +00:00
renovate[bot] 4e3a329c40
chore(deps): update github/codeql-action digest to 3aa7135 (#1186)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-25 22:18:48 +00:00
renovate[bot] d0309eaa66
chore(deps): update github/codeql-action digest to b91f43b (#1184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-25 15:15:09 +00:00
github-actions[bot] f1cee1ca4c
chore(main): release 1.12.2 (#1162)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-24 08:48:06 -04:00
Todd Baert fd7659a46f
perf: reduce hashmap allocations (#1178)
* chore: reduce hashmap allocations

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-24 08:41:55 -04:00
renovate[bot] 7a1eb9b9e9
chore(deps): update github/codeql-action digest to 467d7e6 (#1181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 23:25:51 +00:00
renovate[bot] 74958fd261
chore(deps): update actions/checkout digest to 11bd719 (#1183)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 19:08:29 +00:00
Todd Baert 0009e23c7b
chore: improve benchmark realism; add more context (#1182)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-23 12:33:02 -04:00
renovate[bot] 36620f8408
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.7 (#1180)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 16:29:05 +00:00
renovate[bot] 0db0a50cf4
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.7 (#1179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 12:39:25 +00:00
renovate[bot] a08589664c
chore(deps): update github/codeql-action digest to b7cdb7f (#1177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 22:12:34 +00:00
renovate[bot] cedad9c2c6
chore(deps): update actions/cache digest to 6849a64 (#1174)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 18:14:14 +00:00
renovate[bot] 9fb469f8e8
chore(deps): update github/codeql-action digest to b35b023 (#1176)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 15:33:38 +00:00
renovate[bot] c8c70e23e8
chore(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.0 (#1175)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 12:21:42 +00:00
renovate[bot] b08e8d5537
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.5 (#1173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 05:26:51 +00:00
renovate[bot] 59139a2186
chore(deps): update github/codeql-action digest to 0a30541 (#1170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 00:26:41 +00:00
renovate[bot] a432760fc9
chore(deps): update actions/setup-java digest to 8df1039 (#1172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-21 23:01:08 +00:00
renovate[bot] 02eed7a32c
fix(deps): update junit5 monorepo (#1171)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-21 18:53:27 +00:00
Todd Baert d6d284b6a3
chore: flaky test (#1169)
chore: blocking set-provider in test

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-18 10:10:28 -04:00
renovate[bot] 3f1cfed913
chore(deps): update actions/checkout digest to 163217d (#1168)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-18 10:27:50 +00:00
renovate[bot] 51a3410d8e
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.5 (#1166)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-17 22:48:33 +00:00
renovate[bot] 432ec438ef
chore(deps): update github/codeql-action digest to af56b04 (#1167)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-17 19:14:53 +00:00
renovate[bot] 2d3be2617b
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.5 (#1165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-17 15:02:37 +00:00
renovate[bot] 4e39b55bda
chore(deps): update github/codeql-action digest to c470063 (#1163)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-16 18:23:02 +00:00
Todd Baert 473a05784c chore: fix another flaky test
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-15 13:47:12 -04:00
Todd Baert 457da96e7b chore: fix flaky test
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-15 12:36:36 -04:00
github-actions[bot] 8037e343bd
chore(main): release 1.12.1 (#1117)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 12:18:46 -04:00
Todd Baert 90088188c9
perf: add heap benchmark and reduce allocations (#1156)
* chore: add heap benchmark and reduce allocations

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-15 09:47:51 -04:00
renovate[bot] b144763299
chore(deps): update github/codeql-action digest to 5636274 (#1161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 01:06:35 +00:00
renovate[bot] f28cefe3b1
chore(deps): update github/codeql-action digest to ea2cd92 (#1160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-12 00:09:51 +00:00
renovate[bot] a8813760d6
chore(deps): update github/codeql-action digest to 0c3e006 (#1159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-11 19:01:23 +00:00
renovate[bot] 98a7ed0727
chore(deps): update actions/setup-java digest to 83a06ff (#1158)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-11 00:32:37 +00:00
renovate[bot] 20e3a5d3fe
chore(deps): update github/codeql-action digest to 38469af (#1157)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 22:11:03 +00:00
renovate[bot] 82a5eb5687
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.4 (#1155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 03:34:24 +00:00
renovate[bot] 4f32abaf84
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.4 (#1154)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 00:34:59 +00:00
renovate[bot] 7ccc896665
fix(deps): update dependency io.cucumber:cucumber-bom to v7.20.1 (#1153)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 21:32:16 +00:00
renovate[bot] e982216f70
chore(deps): update github/codeql-action digest to 9d1e406 (#1152)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 01:36:48 +00:00
renovate[bot] fdda5e94b6
chore(deps): update actions/cache digest to 8469c94 (#1151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-08 22:26:06 +00:00
renovate[bot] 6d38b2c5a9
chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.9.0 (#1150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-08 09:20:13 +00:00
renovate[bot] 03e6604960
chore(deps): update github/codeql-action digest to 572cc52 (#1148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-08 00:08:29 +00:00
renovate[bot] 16ec4e459b
chore(deps): update actions/checkout digest to eef6144 (#1149)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 21:56:19 +00:00
renovate[bot] aaab1598a1
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.1 (#1147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 13:34:24 +00:00
renovate[bot] 2489e40c29
chore(deps): update github/codeql-action digest to 56d1975 (#1145)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 10:32:50 +00:00
renovate[bot] 0c0c5f4ad9
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.1 (#1144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-06 15:49:54 +00:00
renovate[bot] 20ea6bd99d
fix(deps): update junit5 monorepo (#1141)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 06:49:33 +00:00
renovate[bot] 9eb64a7471
chore(deps): update github/codeql-action digest to 7cf65a5 (#1140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 04:36:13 +00:00
renovate[bot] a0041c10e4
chore(deps): update actions/cache digest to 2cdf405 (#1143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 00:04:32 +00:00
renovate[bot] e6573838a0
fix(deps): update dependency io.cucumber:cucumber-bom to v7.20.0 (#1142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-04 21:02:56 +00:00
renovate[bot] 1f2c5a1b2a
chore(deps): update github/codeql-action digest to 8b33300 (#1139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-04 00:04:44 +00:00
renovate[bot] 43f076a125
chore(deps): update actions/cache digest to a11fb02 (#1138)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 22:07:35 +00:00
renovate[bot] 0c8ff472f2
chore(deps): update actions/checkout digest to 6b42224 (#1137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 13:22:17 +00:00
renovate[bot] 16e1dec928
chore(deps): update github/codeql-action digest to 8aba5f2 (#1136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 07:36:07 +00:00
renovate[bot] 26659a3eed
chore(deps): update github/codeql-action digest to c4d433c (#1135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 07:40:14 +00:00
renovate[bot] 626f5e17c0
chore(deps): update actions/checkout digest to de5a000 (#1134)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 03:01:48 +00:00
renovate[bot] d4dac274ee
chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.10.1 (#1131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 00:30:11 +00:00
renovate[bot] c8722a2ac6
chore(deps): update github/codeql-action digest to a196a71 (#1133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-01 21:53:02 +00:00
renovate[bot] f7d6202e13
chore(deps): update codecov/codecov-action action to v4.6.0 (#1132)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-01 19:34:00 +00:00
renovate[bot] 02f4ec1061
chore(deps): update github/codeql-action digest to cf5b0a9 (#1130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-30 19:08:45 +00:00
Guido Breitenhuber 4f83d61306
build: Add Maven wrapper (#1129)
Signed-off-by: Guido Breitenhuber <guido.breitenhuber@dynatrace.com>
2024-09-30 12:11:53 -04:00
renovate[bot] 3816151b87
chore(deps): update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.7 (#1128)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-27 21:03:14 +00:00
renovate[bot] 91fffb3560
fix(deps): update junit5 monorepo (#1121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-27 19:17:02 +00:00
renovate[bot] 93f4feb818
chore(deps): update github/codeql-action digest to 2617ff2 (#1127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-27 16:16:24 +00:00
renovate[bot] 8765cf3440
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.3 (#1126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-27 07:59:42 +00:00
renovate[bot] 58635411bd
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.3 (#1125)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-27 04:40:12 +00:00
renovate[bot] f2c37eacc2
chore(deps): update actions/setup-java digest to 292cc14 (#1124)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-26 10:38:29 +00:00
renovate[bot] db1bc75cde
chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.8.2 (#1123)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-26 03:48:16 +00:00
renovate[bot] 2393924592
chore(deps): update actions/checkout digest to d632683 (#1122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-26 00:41:23 +00:00
renovate[bot] c5bace6ff2
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.2 (#1120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-25 20:03:51 +00:00
renovate[bot] b919333823
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.2 (#1119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-25 14:23:20 +00:00
renovate[bot] 90c65666e2
chore(deps): update github/codeql-action digest to 46e0c78 (#1118)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-24 22:44:43 +00:00
renovate[bot] ce06eee9df
chore(deps): update dependency com.google.guava:guava to v33.3.1-jre (#1116)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-24 06:50:02 +00:00
renovate[bot] 5d9780333a
chore(deps): update actions/setup-java digest to b36c23c (#1114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-24 03:34:29 +00:00
renovate[bot] a2a55e8f31
chore(deps): update github/codeql-action digest to 426821d (#1115)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-24 01:33:16 +00:00
github-actions[bot] 48f0685051
chore(main): release 1.12.0 (#1112)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-23 12:51:01 -04:00
chrfwow 1b1e527e78
feat: make provider interface "stateless"; SDK maintains provider state (#1096)
* Make provider interface "stateless", SDK maintains provider state

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-09-23 12:45:34 -04:00
renovate[bot] dd8ba81f12
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.4 (#1113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-21 11:08:08 +00:00
renovate[bot] 52e6d2b0ee
chore(deps): update github/codeql-action digest to 323f5ef (#1111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-20 19:09:08 +00:00
github-actions[bot] 0f94ba890e
chore(main): release 1.11.0 (#1090)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-20 09:39:11 -04:00
renovate[bot] 2412f296b5
fix(deps): update dependency io.cucumber:cucumber-bom to v7.19.0 (#1110)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-20 00:37:30 +00:00
renovate[bot] 17a58efc7e
chore(deps): update github/codeql-action digest to 799e477 (#1108)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 21:43:56 +00:00
renovate[bot] 244f216582
chore(deps): update actions/setup-java digest to 40b9536 (#1109)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 20:21:42 +00:00
renovate[bot] 37b56ac2da
chore(deps): update actions/setup-java digest to 0a40ce6 (#1107)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 19:55:37 +00:00
renovate[bot] ce19ac91f6
chore(deps): update github/codeql-action digest to 64431c6 (#1106)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 16:14:50 +00:00
renovate[bot] 9d69ebd94a
chore(deps): update github/codeql-action digest to cb28816 (#1105)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 05:10:38 +00:00
renovate[bot] 7cb89087da
chore(deps): update github/codeql-action digest to 782de45 (#1104)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-17 16:06:06 +00:00
Simon Schrottner 6fc0b90610
feat: error resolution flow control without exceptions (#1095)
* Allowing flowcontrol with out exceptions

So far we used exception to handle our flowcontrol, but
Exceptions are costly. In the end we enriched our
evaluation Details with errorCode and errorMessage.
This can be also handled by the providers if desired,
to reduce the execution footprint in errornous cases,
which do not have to be exceptions.

Eg FlagNotFound - it might be the case, but in performance
critical environments, an exception rather than a normal
return, can cause overhead and can be already too costly.

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

* fix: adding reason, and removing stacktraces from errors

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

* Update src/main/java/dev/openfeature/sdk/exceptions/TypeMismatchError.java

Co-authored-by: Justin Abrahms <justin@abrah.ms>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>

---------

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
Co-authored-by: Justin Abrahms <justin@abrah.ms>
2024-09-17 09:15:43 -04:00
renovate[bot] 29901b87ea
chore(deps): update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.6 (#1103)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:23:56 +00:00
renovate[bot] d1478c001a
chore(deps): update github/codeql-action digest to 5618c9f (#1102)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-13 21:47:30 +00:00
renovate[bot] b80fd6d307
chore(deps): update github/codeql-action digest to 4a01ec7 (#1101)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 21:49:04 +00:00
renovate[bot] c68f78e17b
chore(deps): update actions/setup-java digest to bcfbca5 (#1100)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-11 12:07:01 +00:00
renovate[bot] caec6e35e9
chore(deps): update github/codeql-action digest to e817992 (#1099)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-11 03:43:06 +00:00
renovate[bot] 64082617fa
chore(deps): update github/codeql-action digest to 8fd294e (#1097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-10 01:02:53 +00:00
renovate[bot] 082f5746c8
chore(deps): update actions/setup-java digest to 2dfa201 (#1094)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 00:59:37 +00:00
renovate[bot] d60593fa11
chore(deps): update github/codeql-action digest to d8b1697 (#1093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-06 16:16:30 +00:00
renovate[bot] 870fc27ed7
chore(deps): update github/codeql-action digest to 9b41ced (#1089)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-06 08:22:57 +00:00
renovate[bot] 58ead7fa91
chore(deps): update actions/setup-java digest to 7467385 (#1092)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-06 03:29:26 +00:00
renovate[bot] 9f6a40ec9b
chore(deps): update actions/checkout digest to 6d193bf (#1091)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-06 02:08:56 +00:00
renovate[bot] 7e0c70f7c5
chore(deps): update actions/checkout digest to b684943 (#1088)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-05 18:34:47 +00:00
github-actions[bot] 1f8d577a16
chore(main): release 1.10.0 (#1065)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-05 13:05:46 -04:00
Todd Baert 037826fe1b
feat: add logging hook, rm logging from evaluation (#1084)
* feat: add logging hook, rm logging from evaluation

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: remove public

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: debug, not info

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: move comment

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: underscoes

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: add to readme

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-09-05 12:33:51 -04:00
renovate[bot] 78e3371c05
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.3 (#1087)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-05 07:01:18 +00:00
renovate[bot] dd7696f473
chore(deps): update github/codeql-action digest to 889597e (#1086)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-04 22:46:26 +00:00
renovate[bot] 90648d1c9d
chore(deps): update github/codeql-action digest to b4a8631 (#1083)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-03 14:44:42 +00:00
renovate[bot] 9196599f30
chore(deps): update actions/checkout digest to 2d7d9f7 (#1082)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-02 18:39:34 +00:00
renovate[bot] a4d428c83c
chore(deps): update github/codeql-action digest to 821ab42 (#1081)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 12:10:55 +00:00
renovate[bot] a3285df729
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.1 (#1079)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 03:25:51 +00:00
renovate[bot] 0cc5ca1397
chore(deps): update actions/setup-java digest to 8e04ddf (#1080)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 01:05:10 +00:00
renovate[bot] 98360061a8
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.1 (#1078)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-29 21:13:06 +00:00
renovate[bot] 3f5294c734
chore(deps): update github/codeql-action digest to b43ac1c (#1077)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-29 16:56:18 +00:00
renovate[bot] eb5526d75f
chore(deps): update github/codeql-action digest to 7233ec5 (#1076)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 19:11:07 +00:00
renovate[bot] b772119977
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.0 (#1075)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 03:55:03 +00:00
renovate[bot] 5ee38510a8
chore(deps): update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.25.0 (#1074)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 00:41:42 +00:00
renovate[bot] 3eed950d3c
chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.10.0 (#1072)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-27 21:42:54 +00:00
renovate[bot] c8450358c0
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.0 (#1073)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-27 18:07:36 +00:00
renovate[bot] 5668987274
chore(deps): update github/codeql-action digest to b8efe4d (#1071)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-27 15:41:48 +00:00
renovate[bot] ee6d8b094a
chore(deps): update github/codeql-action digest to 864b979 (#1070)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-27 03:45:55 +00:00
renovate[bot] 0e048c1ff5
chore(deps): update github/codeql-action digest to d36c7aa (#1069)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-26 21:43:20 +00:00
Todd Baert 35d4cc23c8
chore: various non-functional refactors (#1066)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-08-26 09:16:10 -04:00
renovate[bot] ea59e7fa58
chore(deps): update github/codeql-action digest to a895f2e (#1068)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-24 05:37:08 +00:00
renovate[bot] a07eb67865
chore(deps): update github/codeql-action digest to 7e27807 (#1067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 20:07:49 +00:00
renovate[bot] dd53021153
chore(deps): update dependency net.bytebuddy:byte-buddy-agent to v1.15.0 (#1064)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 13:42:51 +00:00
renovate[bot] 7fea9b106c
chore(deps): update dependency net.bytebuddy:byte-buddy to v1.15.0 (#1063)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 11:12:31 +00:00
github-actions[bot] d7ed2a5de2
chore(main): release 1.9.1 (#996)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-22 16:01:38 -04:00
renovate[bot] 8370d4209d
chore(deps): update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.5.0 (#1062)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-22 15:56:50 -04:00
Ryan Prayogo 32340a3e0e
fix: Pin byte-buddy(-agent) version to 1.14.19 to workaround Mockito issue (#1060)
* fix: Add the net.bytebuddy.experimental=true system property

Workaround to make Mockito tests to pass under Java 21

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* fix: Pin byte-buddy and byte-buddy-agent to a newer version

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* chore: Fix maven warning about deprecated expression

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* chore: Add comments around the Mockito workaround

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* Update pom.xml

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-08-22 15:56:19 -04:00
Ryan Prayogo b7ed041eed
fix: Use ConcurrentHashMap for InMemoryProvider (#1057)
* fix: Use ConcurrentHashMap for InMemoryProvider

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* fix: make the flags field variable final

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* chore: Use Collections.singletonList instead of Arrays.asList

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* chore: Update javadoc and parameter name

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>

* fixup: await verify

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: remove test, key diffing

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Ryan Prayogo <57620+ryanprayogo@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-08-22 15:48:45 -04:00
renovate[bot] a81957ff56
chore(deps): update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.8.0 (#1061)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-22 14:40:10 +00:00
renovate[bot] b0f915bb09
chore(deps): update github/codeql-action digest to fd5fa13 (#1058)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-22 01:50:06 +00:00
renovate[bot] 61d821ae8a
chore(deps): update github/codeql-action digest to 202b3b9 (#1056)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-21 00:25:47 +00:00
Todd Baert dbf967a860
fix: updated context not passed to all hooks (#1049)
* fix: updated context not passed to all hooks

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: checkstyle

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-08-20 15:33:34 -04:00
renovate[bot] 7cac1984f8
chore(deps): update github/codeql-action digest to 512e306 (#1055)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-20 15:02:17 +00:00
renovate[bot] aed4ea21d6
chore(deps): update github/codeql-action digest to 339aada (#1053)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-19 21:45:43 +00:00
renovate[bot] 13dd70f847
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.4.0 (#1052)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-19 04:35:51 +00:00
renovate[bot] a36d2ab111
chore(deps): update dependency com.google.guava:guava to v33.3.0-jre (#1050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-19 01:14:23 +00:00
renovate[bot] a1ceb1fbbf
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.4.0 (#1051)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-18 23:21:46 +00:00
renovate[bot] 00bc0609eb
chore(deps): update github/codeql-action digest to 5c681ef (#1048)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-15 15:39:23 +00:00
renovate[bot] 5e77f8ad33
fix(deps): update junit5 monorepo (#1045)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-14 21:16:02 +00:00
renovate[bot] 2934195a8f
chore(deps): update github/codeql-action digest to a93f8c2 (#1046)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-14 18:49:57 +00:00
renovate[bot] d746dc0a11
chore(deps): update actions/cache digest to 81382a7 (#1044)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-14 15:58:59 +00:00
renovate[bot] f1ea4057fc
chore(deps): update github/codeql-action digest to 0d5982a (#1043)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 12:38:06 -04:00
renovate[bot] 37121e9939
chore(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.1 (#1042)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 01:13:31 +00:00
renovate[bot] 69db287007
chore(deps): update github/codeql-action digest to d620faa (#1041)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 22:12:09 +00:00
renovate[bot] b215dec8b8
chore(deps): update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.5 (#1040)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 14:11:06 +00:00
renovate[bot] beba1bd8d6
fix(deps): update dependency org.slf4j:slf4j-api to v2.0.16 (#1039)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-10 12:53:59 +00:00
renovate[bot] 75b9acd791
chore(deps): update github/codeql-action digest to 25ad3c8 (#1038)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-08 22:19:31 +00:00
renovate[bot] b4f0550a2b
chore(deps): update actions/setup-java digest to 67fbd72 (#1037)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-08 22:10:56 +00:00
renovate[bot] fed93942b8
fix(deps): update dependency org.slf4j:slf4j-api to v2.0.15 (#1036)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-08 18:09:46 +00:00
renovate[bot] 4591d3f1da
chore(deps): update dependency org.awaitility:awaitility to v4.2.2 (#1035)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 14:28:50 +00:00
renovate[bot] ccabb1856c
chore(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.0 (#1034)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 07:55:55 +00:00
renovate[bot] 4ec155d91b
fix(deps): update dependency org.slf4j:slf4j-api to v2.0.14 (#1033)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 03:12:16 +00:00
renovate[bot] 1ed7fc1577
chore(deps): update github/codeql-action digest to 5c02493 (#1032)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 01:25:18 +00:00
renovate[bot] 22435a694a
chore(deps): update github/codeql-action digest to c24926b (#1031)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-06 19:47:12 +00:00
renovate[bot] 6990e21b47
chore(deps): update actions/cache digest to 57b8e40 (#1030)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-06 17:19:45 +00:00
renovate[bot] 89cb7479f4
chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.8.1 (#1029)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-04 07:02:11 +00:00
renovate[bot] cd4c8239cd
chore(deps): update github/codeql-action digest to 9c646c2 (#1028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-02 19:31:13 +00:00
renovate[bot] 09686741ad
chore(deps): update actions/setup-java digest to 6a0805f (#1027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-01 21:50:25 +00:00
renovate[bot] 41128b86fb
chore(deps): update actions/cache digest to 40c3b67 (#1026)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-31 21:01:30 +00:00
renovate[bot] c574ec5c77
chore(deps): update github/codeql-action digest to 5cdd182 (#1025)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-31 16:39:08 +00:00
renovate[bot] d23a9115c8
chore(deps): update github/codeql-action digest to 16639b4 (#1024)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-30 13:43:51 +00:00
renovate[bot] 326a10ba01
chore(deps): update actions/checkout digest to 9a9194f (#1023)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-30 03:46:08 +00:00
renovate[bot] 865c3bb17a
chore(deps): update actions/cache digest to 4a28cbc (#1022)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-30 00:59:00 +00:00
renovate[bot] e57eafd86d
chore(deps): update github/codeql-action digest to aa96d09 (#1021)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 19:57:40 +00:00
renovate[bot] 7db6d8a3d3
chore(deps): update github/codeql-action digest to 4b1d7da (#1020)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 20:17:27 +00:00
renovate[bot] cf760e4cc4
chore(deps): update github/codeql-action digest to f8e94f9 (#1019)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 14:52:07 +00:00
renovate[bot] aa7f8b97f0
chore(deps): update github/codeql-action digest to 1b214db (#1018)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 21:07:51 +00:00
renovate[bot] baa13313e8
chore(deps): update github/codeql-action digest to f67c9cd (#1017)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 16:09:27 +00:00
renovate[bot] 5db43ad1aa
chore(deps): update github/codeql-action digest to b400d0f (#1016)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 00:42:54 +00:00
renovate[bot] f1b0eb154d
chore(deps): update github/codeql-action digest to 0e346f2 (#1014)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 01:46:52 +00:00
renovate[bot] 3d0cd62c98
chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.8.0 (#1013)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-20 14:01:02 +00:00
renovate[bot] eca299b3ad
chore(deps): update github/codeql-action digest to 44534b7 (#1012)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-19 22:07:05 +00:00
renovate[bot] 91fa8cf7d6
fix(deps): update dependency io.cucumber:cucumber-bom to v7.18.1 (#1011)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-18 23:28:44 +00:00
renovate[bot] 1d31726e57
chore(deps): update github/codeql-action digest to 270a29d (#1010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-17 19:00:44 +00:00
renovate[bot] efbb69a998
chore(deps): update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.24.0 (#1009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-14 01:32:25 +00:00
renovate[bot] 9cc9241b01
chore(deps): update github/codeql-action digest to c2585ec (#1008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 21:40:22 +00:00
renovate[bot] aab84b80af
chore(deps): update github/codeql-action digest to 857f661 (#1007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 14:35:00 +00:00
renovate[bot] 2bb58d6e1b
chore(deps): update github/codeql-action digest to 9ab7277 (#1006)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 13:56:33 +00:00
renovate[bot] e8568a8ea2
chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.3.1 (#1005)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 04:52:40 +00:00
renovate[bot] 7ae703e1da
chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.3.1 (#1004)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 00:31:04 +00:00
renovate[bot] f3d9a55eb7
chore(deps): update github/codeql-action digest to be825d5 (#1003)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-10 14:32:44 +00:00
renovate[bot] 2f5deb1a3a
chore(deps): update dependency org.assertj:assertj-core to v3.26.3 (#1002)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-09 21:19:24 +00:00
renovate[bot] 145dfc70c2
chore(deps): update github/codeql-action digest to 6e04d51 (#1001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-08 18:39:48 +00:00
renovate[bot] 42d2d776a8
chore(deps): update github/codeql-action digest to 064a406 (#1000)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-08 14:05:49 +00:00
renovate[bot] d0b3b35981
chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.2 (#999)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-06 03:03:57 +00:00
renovate[bot] 62f95b651b
chore(deps): update github/codeql-action digest to 7adf9ac (#998)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-02 16:55:24 +00:00
renovate[bot] fc40209edc
chore(deps): update github/codeql-action digest to ee4ad8b (#997)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 22:21:04 +00:00
David Pilato 7bff3eebe6
docs: Small typo sonartype vs sonatype (#989)
Small type sonartype vs sonatype

Nothing important. Feel free to ignore ;)

Signed-off-by: David Pilato <david@pilato.fr>
2024-06-28 12:48:32 -07:00
renovate[bot] e2c70d9f0b
chore(deps): update github/codeql-action digest to 79e9a50 (#995)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-28 18:16:12 +00:00
162 changed files with 8660 additions and 2818 deletions

72
.editorconfig Normal file
View File

@ -0,0 +1,72 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
trim_trailing_whitespace = true
ij_continuation_indent_size = 8
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# Following the rules of the Google Java Style Guide.
# See https://google.github.io/styleguide/javaguide.html
[*.java]
max_line_length = 120
ij_java_do_not_wrap_after_single_annotation_in_parameter = true
ij_java_insert_inner_class_imports = false
ij_java_class_count_to_use_import_on_demand = 999
ij_java_names_count_to_use_import_on_demand = 999
ij_java_packages_to_use_import_on_demand = unset
ij_java_imports_layout = $*,|,*
ij_java_doc_align_param_comments = true
ij_java_doc_align_exception_comments = true
ij_java_doc_add_p_tag_on_empty_lines = false
ij_java_doc_do_not_wrap_if_one_line = true
ij_java_doc_keep_empty_parameter_tag = false
ij_java_doc_keep_empty_throws_tag = false
ij_java_doc_keep_empty_return_tag = false
ij_java_doc_preserve_line_breaks = true
ij_java_doc_indent_on_continuation = true
ij_java_keep_control_statement_in_one_line = false
ij_java_keep_blank_lines_in_code = 1
ij_java_align_multiline_parameters = false
ij_java_align_multiline_resources = false
ij_java_align_multiline_for = true
ij_java_space_before_array_initializer_left_brace = true
ij_java_call_parameters_wrap = normal
ij_java_method_parameters_wrap = normal
ij_java_extends_list_wrap = normal
ij_java_throws_keyword_wrap = normal
ij_java_method_call_chain_wrap = normal
ij_java_binary_operation_wrap = normal
ij_java_binary_operation_sign_on_next_line = true
ij_java_ternary_operation_wrap = normal
ij_java_ternary_operation_signs_on_next_line = true
ij_java_keep_simple_methods_in_one_line = true
ij_java_keep_simple_lambdas_in_one_line = true
ij_java_keep_simple_classes_in_one_line = true
ij_java_for_statement_wrap = normal
ij_java_array_initializer_wrap = normal
ij_java_wrap_comments = true
ij_java_if_brace_force = always
ij_java_do_while_brace_force = always
ij_java_while_brace_force = always
ij_java_for_brace_force = always
ij_java_space_after_closing_angle_bracket_in_type_argument = false
[{*.json,*.json5}]
indent_size = 2
tab_width = 2
ij_smart_tabs = false
[*.yaml]
indent_size = 2
tab_width = 2

1
.gitattributes vendored
View File

@ -3,4 +3,3 @@
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

View File

@ -18,6 +18,6 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@80c0371c57c5142ed6c844270bba1864bac8a4c6
- uses: amannn/action-semantic-pull-request@335288255954904a41ddda8947c8f2c844b8bfeb
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -9,35 +9,36 @@ name: on-merge
on:
push:
branches: [ master, main ]
branches:
- main
permissions:
contents: read
jobs:
build:
environment: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Set up JDK 8
uses: actions/setup-java@fd08b9c8dc6f530393a204a04e1f05101a5d00fd
- uses: actions/checkout@09d2acae674a48949e3602304ab46fd20ae0c42f
- name: Set up JDK 17
uses: actions/setup-java@ae2b61dbc685e60e4427b2e8ed4f0135c6ea8597
with:
java-version: '8'
java-version: '17'
distribution: 'temurin'
cache: maven
server-id: ossrh
server-username: ${{ secrets.OSSRH_USERNAME }}
server-password: ${{ secrets.OSSRH_PASSWORD }}
server-id: central
server-username: ${{ secrets.CENTRAL_USERNAME }}
server-password: ${{ secrets.CENTRAL_PASSWORD }}
- name: Cache local Maven repository
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
uses: actions/cache@640a1c2554105b57832a23eea0b4672fc7a790d5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
key: ${{ runner.os }}-17-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
${{ runner.os }}-17-maven-
- name: Configure GPG Key
run: |
@ -49,7 +50,7 @@ jobs:
run: mvn --batch-mode --update-snapshots verify
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.5.0
uses: codecov/codecov-action@v5.4.3
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
flags: unittests # optional
@ -60,11 +61,11 @@ jobs:
# Add -SNAPSHOT before deploy
- name: Add SNAPSHOT
run: mvn versions:set -DnewVersion='${project.version}-SNAPSHOT'
- name: Deploy
run: |
mvn --batch-mode \
--settings release/m2-settings.xml clean deploy
--settings release/m2-settings.xml -DskipTests clean deploy
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}

View File

@ -7,36 +7,46 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest]
build:
- java: 17
profile: codequality
- java: 11
profile: java11
name: with Java ${{ matrix.build.java }}
runs-on: ${{ matrix.os}}
steps:
- name: Check out the code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
uses: actions/checkout@09d2acae674a48949e3602304ab46fd20ae0c42f
- name: Set up JDK 8
uses: actions/setup-java@fd08b9c8dc6f530393a204a04e1f05101a5d00fd
- name: Set up JDK 11
uses: actions/setup-java@ae2b61dbc685e60e4427b2e8ed4f0135c6ea8597
with:
java-version: '8'
distribution: 'temurin'
cache: maven
java-version: ${{ matrix.build.java }}
distribution: 'temurin'
cache: maven
- name: Initialize CodeQL
uses: github/codeql-action/init@de945755c9edd3a4e5d160a71f1482ece6a3c271
uses: github/codeql-action/init@7710ed11e398ea99c7f7004c2b2e0f580458db42
with:
languages: java
- name: Cache local Maven repository
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
uses: actions/cache@640a1c2554105b57832a23eea0b4672fc7a790d5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
path: ~/.m2/repository
key: ${{ runner.os }}${{ matrix.build.java }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}${{ matrix.build.java }}-maven-
- name: Verify with Maven
run: mvn --batch-mode --update-snapshots --activate-profiles e2e verify
run: mvn --batch-mode --update-snapshots --activate-profiles e2e,${{ matrix.build.profile }} verify
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.5.0
- if: matrix.build.java == '17'
name: Upload coverage to Codecov
uses: codecov/codecov-action@v5.4.3
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
flags: unittests # optional
@ -45,4 +55,4 @@ jobs:
verbose: true # optional (default = false)
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@de945755c9edd3a4e5d160a71f1482ece6a3c271
uses: github/codeql-action/analyze@7710ed11e398ea99c7f7004c2b2e0f580458db42

View File

@ -12,46 +12,53 @@ permissions: # added using https://github.com/step-security/secure-workflows
jobs:
release-please:
permissions:
contents: write # for google-github-actions/release-please-action to create release commit
pull-requests: write # for google-github-actions/release-please-action to create release PR
runs-on: ubuntu-latest
permissions:
contents: write # for googleapis/release-please-action to create release commit
pull-requests: write # for googleapis/release-please-action to create release PR
issues: write # for googleapis/release-please-action to create labels
# Release-please creates a PR that tracks all changes
steps:
- uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee
- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{secrets.GITHUB_TOKEN}}
default-branch: main
token: ${{secrets.RELEASE_PLEASE_ACTION_TOKEN}}
outputs:
release_created: ${{ fromJSON(steps.release.outputs.paths_released)[0] != null }} # if we have a single release path, do the release
# These steps are only run if this was a merged release-please PR
- name: checkout
if: ${{ steps.release.outputs.release_created }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: Set up JDK 8
if: ${{ steps.release.outputs.release_created }}
uses: actions/setup-java@fd08b9c8dc6f530393a204a04e1f05101a5d00fd
publish:
environment: publish
runs-on: ubuntu-latest
permissions:
contents: read
needs: release-please
if: ${{ fromJSON(needs.release-please.outputs.release_created || false) }}
steps:
- name: Checkout Repository
uses: actions/checkout@09d2acae674a48949e3602304ab46fd20ae0c42f
- name: Set up JDK 17
uses: actions/setup-java@ae2b61dbc685e60e4427b2e8ed4f0135c6ea8597
with:
java-version: '8'
java-version: '17'
distribution: 'temurin'
cache: maven
server-id: ossrh
server-username: ${{ secrets.OSSRH_USERNAME }}
server-password: ${{ secrets.OSSRH_PASSWORD }}
server-id: central
server-username: ${{ secrets.CENTRAL_USERNAME }}
server-password: ${{ secrets.CENTRAL_PASSWORD }}
- name: Configure GPG Key
if: ${{ steps.release.outputs.release_created }}
run: |
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import
env:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
- name: Deploy
if: ${{ steps.release.outputs.release_created }}
run: |
mvn --batch-mode \
--settings release/m2-settings.xml clean deploy
--settings release/m2-settings.xml -DskipTests clean deploy
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}

View File

@ -29,16 +29,16 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
uses: actions/checkout@09d2acae674a48949e3602304ab46fd20ae0c42f
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@de945755c9edd3a4e5d160a71f1482ece6a3c271
uses: github/codeql-action/init@7710ed11e398ea99c7f7004c2b2e0f580458db42
with:
languages: java
- name: Autobuild
uses: github/codeql-action/autobuild@de945755c9edd3a4e5d160a71f1482ece6a3c271
uses: github/codeql-action/autobuild@7710ed11e398ea99c7f7004c2b2e0f580458db42
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@de945755c9edd3a4e5d160a71f1482ece6a3c271
uses: github/codeql-action/analyze@7710ed11e398ea99c7f7004c2b2e0f580458db42

6
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "test-harness"]
path = test-harness
url = https://github.com/open-feature/test-harness
[submodule "spec"]
path = spec
url = https://github.com/open-feature/spec/

19
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

View File

@ -1 +1 @@
{".":"1.9.0"}
{".":"1.16.0"}

View File

@ -1,5 +1,635 @@
# Changelog
## [1.16.0](https://github.com/open-feature/java-sdk/compare/v1.15.1...v1.16.0) (2025-07-07)
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.23.0 ([#1466](https://github.com/open-feature/java-sdk/issues/1466)) ([50a6b16](https://github.com/open-feature/java-sdk/commit/50a6b168a7de40337aa51ef3d79d122030956cb9))
* **deps:** update dependency org.junit:junit-bom to v5.13.1 ([#1475](https://github.com/open-feature/java-sdk/issues/1475)) ([545d6aa](https://github.com/open-feature/java-sdk/commit/545d6aac09dbc74c00a0a4e5c26f4ef80be22379))
* **deps:** update dependency org.junit:junit-bom to v5.13.2 ([#1492](https://github.com/open-feature/java-sdk/issues/1492)) ([34b22e8](https://github.com/open-feature/java-sdk/commit/34b22e8d93a986fdb81500ab539b4d2fe038b618))
* **deps:** update dependency org.junit:junit-bom to v5.13.3 ([#1505](https://github.com/open-feature/java-sdk/issues/1505)) ([957c0d1](https://github.com/open-feature/java-sdk/commit/957c0d1ba38ecc758c1ec164e40070ac93a01d68))
* **deps:** update junit5 monorepo ([#1467](https://github.com/open-feature/java-sdk/issues/1467)) ([f8260a1](https://github.com/open-feature/java-sdk/commit/f8260a1c3a345c877eba95bfe41184ad11f6555e))
* Reduce locking and concurrency issues ([#1478](https://github.com/open-feature/java-sdk/issues/1478)) ([ebea0fd](https://github.com/open-feature/java-sdk/commit/ebea0fdf1cf3e6f4d2e8aebf2dcb7c7e1f31acc2))
### ✨ New Features
* add means of awaiting event emission, fix flaky build ([#1463](https://github.com/open-feature/java-sdk/issues/1463)) ([3dd7d5d](https://github.com/open-feature/java-sdk/commit/3dd7d5d4262f1f4461e13c13a7d64d2fa8bfd764)), closes [#1449](https://github.com/open-feature/java-sdk/issues/1449)
### 🧹 Chore
* **deps:** update actions/cache digest to 640a1c2 ([#1485](https://github.com/open-feature/java-sdk/issues/1485)) ([7c2af57](https://github.com/open-feature/java-sdk/commit/7c2af57a362ee11f757a431ee17eff3ee448bf6c))
* **deps:** update actions/checkout digest to 09d2aca ([#1473](https://github.com/open-feature/java-sdk/issues/1473)) ([b5d873e](https://github.com/open-feature/java-sdk/commit/b5d873e44d3c41b42f11569b0fafccc0a002ebdd))
* **deps:** update actions/setup-java digest to 67aec00 ([#1504](https://github.com/open-feature/java-sdk/issues/1504)) ([08f549a](https://github.com/open-feature/java-sdk/commit/08f549afd1fd26581b2a8e063832ec986c5e3267))
* **deps:** update actions/setup-java digest to ebb356c ([#1490](https://github.com/open-feature/java-sdk/issues/1490)) ([e67f598](https://github.com/open-feature/java-sdk/commit/e67f5983573afff805a56ef18584d1a7291ccafc))
* **deps:** update codecov/codecov-action action to v5.4.3 ([#1454](https://github.com/open-feature/java-sdk/issues/1454)) ([e337939](https://github.com/open-feature/java-sdk/commit/e3379395e6bfb0ce811d8372761a3cb015ad2cde))
* **deps:** update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.5 ([#1462](https://github.com/open-feature/java-sdk/issues/1462)) ([40b319c](https://github.com/open-feature/java-sdk/commit/40b319c5de0461bec13f76978ae09edc958310cd))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.1 ([#1493](https://github.com/open-feature/java-sdk/issues/1493)) ([b64efe8](https://github.com/open-feature/java-sdk/commit/b64efe82d993defe070dfeb9aa60e740ccf757cd))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.2 ([#1496](https://github.com/open-feature/java-sdk/issues/1496)) ([fc430c3](https://github.com/open-feature/java-sdk/commit/fc430c3e1d57a532d8c0c879c3e7e25c46d4ad84))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10.24.0 ([#1458](https://github.com/open-feature/java-sdk/issues/1458)) ([dcbfd26](https://github.com/open-feature/java-sdk/commit/dcbfd265a3875271695af760fce9870e53c69f13))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10.25.0 ([#1468](https://github.com/open-feature/java-sdk/issues/1468)) ([1558a86](https://github.com/open-feature/java-sdk/commit/1558a862497c0e133d11d53ff6d7f28437653d43))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10.25.1 ([#1489](https://github.com/open-feature/java-sdk/issues/1489)) ([312b6df](https://github.com/open-feature/java-sdk/commit/312b6df5d2c891ac758bf398f8399ecd25b7597e))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10.26.0 ([#1494](https://github.com/open-feature/java-sdk/issues/1494)) ([300a705](https://github.com/open-feature/java-sdk/commit/300a705e0af959da7ed0e88e9975379ff6fc4138))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10.26.1 ([#1498](https://github.com/open-feature/java-sdk/issues/1498)) ([2e3b479](https://github.com/open-feature/java-sdk/commit/2e3b479cb1e8b0b65652ee813eaa2e1940d53c8e))
* **deps:** update dependency maven to v3.9.10 ([#1474](https://github.com/open-feature/java-sdk/issues/1474)) ([4481537](https://github.com/open-feature/java-sdk/commit/4481537cebc213dcfe19bb8cd9b70a4c91a682b2))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.6 ([#1482](https://github.com/open-feature/java-sdk/issues/1482)) ([8e51e6f](https://github.com/open-feature/java-sdk/commit/8e51e6fe101882184a5d09be31fa65563d82c673))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.6 ([#1483](https://github.com/open-feature/java-sdk/issues/1483)) ([936ff60](https://github.com/open-feature/java-sdk/commit/936ff60fac471a83a7c14412d2e825b2a7f9704c))
* **deps:** update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.8 ([#1501](https://github.com/open-feature/java-sdk/issues/1501)) ([0515ad5](https://github.com/open-feature/java-sdk/commit/0515ad54c4f71863373eb1b7f429393923b27d90))
* **deps:** update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.1 ([#1461](https://github.com/open-feature/java-sdk/issues/1461)) ([b6ceff2](https://github.com/open-feature/java-sdk/commit/b6ceff2ecb0e34be2ccdb83f7f37c1177de6f27e))
* **deps:** update dependency org.mockito:mockito-core to v5.18.0 ([#1457](https://github.com/open-feature/java-sdk/issues/1457)) ([e17b0b2](https://github.com/open-feature/java-sdk/commit/e17b0b29758ae7cdbdac9ddb2178382c55eb1277))
* **deps:** update github/codeql-action digest to 075e08a ([#1470](https://github.com/open-feature/java-sdk/issues/1470)) ([6597de7](https://github.com/open-feature/java-sdk/commit/6597de7a98e0fae10a541a8a9b60837623c133a8))
* **deps:** update github/codeql-action digest to 33f8489 ([#1502](https://github.com/open-feature/java-sdk/issues/1502)) ([0fd9d3d](https://github.com/open-feature/java-sdk/commit/0fd9d3dcfb1fd65197a42885b12d40a1cc152d3b))
* **deps:** update github/codeql-action digest to 396fd27 ([#1456](https://github.com/open-feature/java-sdk/issues/1456)) ([b45a937](https://github.com/open-feature/java-sdk/commit/b45a9370173e3d3b97c78449dfc99225fb572228))
* **deps:** update github/codeql-action digest to 3de706a ([#1481](https://github.com/open-feature/java-sdk/issues/1481)) ([99a3006](https://github.com/open-feature/java-sdk/commit/99a3006de878ab0ba1f0e61a4cb5432914425795))
* **deps:** update github/codeql-action digest to 466d6ce ([#1477](https://github.com/open-feature/java-sdk/issues/1477)) ([0b57bca](https://github.com/open-feature/java-sdk/commit/0b57bcafc14b946000feb4a3421d73b9616e83cb))
* **deps:** update github/codeql-action digest to 4a00331 ([#1469](https://github.com/open-feature/java-sdk/issues/1469)) ([376f81f](https://github.com/open-feature/java-sdk/commit/376f81f5c3b66d7e3e298aac30ac7544b84e7362))
* **deps:** update github/codeql-action digest to 4c57370 ([#1497](https://github.com/open-feature/java-sdk/issues/1497)) ([49214b7](https://github.com/open-feature/java-sdk/commit/49214b7282ddde1ee16cf80f92c11cc90ef7612a))
* **deps:** update github/codeql-action digest to 510dfa3 ([#1450](https://github.com/open-feature/java-sdk/issues/1450)) ([d9a72d2](https://github.com/open-feature/java-sdk/commit/d9a72d2aafd787a1814132f000897ad1c94181e4))
* **deps:** update github/codeql-action digest to 57eebf6 ([#1455](https://github.com/open-feature/java-sdk/issues/1455)) ([36eed06](https://github.com/open-feature/java-sdk/commit/36eed065e763bbfa0f8f97d704202bbd219332ca))
* **deps:** update github/codeql-action digest to 66d7255 ([#1487](https://github.com/open-feature/java-sdk/issues/1487)) ([c3eaecd](https://github.com/open-feature/java-sdk/commit/c3eaecdb8b34d3b33946bd205ee92d49584602bd))
* **deps:** update github/codeql-action digest to 7b0fb5a ([#1459](https://github.com/open-feature/java-sdk/issues/1459)) ([6a95c00](https://github.com/open-feature/java-sdk/commit/6a95c008e975dd3c7328c32f1d7cf626bbaecfa6))
* **deps:** update github/codeql-action digest to 7cb9b16 ([#1476](https://github.com/open-feature/java-sdk/issues/1476)) ([6cca721](https://github.com/open-feature/java-sdk/commit/6cca721be5bc6f5926fe64668a7c03728cab3cb0))
* **deps:** update github/codeql-action digest to 7fd6215 ([#1464](https://github.com/open-feature/java-sdk/issues/1464)) ([f10aaaa](https://github.com/open-feature/java-sdk/commit/f10aaaa357581b573895f4d6e2329abb705582aa))
* **deps:** update github/codeql-action digest to 8ef1782 ([#1495](https://github.com/open-feature/java-sdk/issues/1495)) ([86a5916](https://github.com/open-feature/java-sdk/commit/86a5916f0dc6116b5b9e5dc897ff4b8705ac01e3))
* **deps:** update github/codeql-action digest to 9b02dc2 ([#1491](https://github.com/open-feature/java-sdk/issues/1491)) ([6f67b06](https://github.com/open-feature/java-sdk/commit/6f67b06f712c461f331681a76f5cb2c3ddb0d36b))
* **deps:** update github/codeql-action digest to ac30a39 ([#1488](https://github.com/open-feature/java-sdk/issues/1488)) ([8fad544](https://github.com/open-feature/java-sdk/commit/8fad544b17ee08b4280d7975073d00a874c374db))
* **deps:** update github/codeql-action digest to b1e4dc3 ([#1471](https://github.com/open-feature/java-sdk/issues/1471)) ([2dcd6a1](https://github.com/open-feature/java-sdk/commit/2dcd6a1dd0c80ee676b9860afd6a6002d0ea4aea))
* **deps:** update github/codeql-action digest to b694213 ([#1503](https://github.com/open-feature/java-sdk/issues/1503)) ([a5d1cbc](https://github.com/open-feature/java-sdk/commit/a5d1cbced4658fadb63f362b4512bdbd68ae7d6a))
* **deps:** update github/codeql-action digest to b86edfc ([#1453](https://github.com/open-feature/java-sdk/issues/1453)) ([b667aa3](https://github.com/open-feature/java-sdk/commit/b667aa325136b78c01867d40342f81eeb7e16f46))
* **deps:** update github/codeql-action digest to bc02a25 ([#1460](https://github.com/open-feature/java-sdk/issues/1460)) ([5e922cf](https://github.com/open-feature/java-sdk/commit/5e922cf3efc156135563707de92e508b0a4d19f3))
* **deps:** update github/codeql-action digest to be30325 ([#1479](https://github.com/open-feature/java-sdk/issues/1479)) ([844d5e2](https://github.com/open-feature/java-sdk/commit/844d5e244b02703b624cf75e5bf8448c07e62d3d))
* **deps:** update github/codeql-action digest to dcc1a66 ([#1499](https://github.com/open-feature/java-sdk/issues/1499)) ([69519b1](https://github.com/open-feature/java-sdk/commit/69519b1ef7274ceae39d6746c5a5a98dc69f562f))
* **deps:** update github/codeql-action digest to ef36b69 ([#1484](https://github.com/open-feature/java-sdk/issues/1484)) ([8bf777a](https://github.com/open-feature/java-sdk/commit/8bf777a7e99be4dfac8917b8e61cb6c23385b8ce))
* **deps:** update io.cucumber.version to v7.23.0 ([#1465](https://github.com/open-feature/java-sdk/issues/1465)) ([2de7616](https://github.com/open-feature/java-sdk/commit/2de76166764bacd34883b13220dd0bad824c8b1a))
* improvements to release workflow ([#1451](https://github.com/open-feature/java-sdk/issues/1451)) ([1714efe](https://github.com/open-feature/java-sdk/commit/1714efe81aa6ae025f4f8b12c9c042561498d25e))
* migrate to new publish ([5425a34](https://github.com/open-feature/java-sdk/commit/5425a34a12baa04f9583b83fd1bfdd7e2a6ab5e8))
* remove unneeded version information ([#1428](https://github.com/open-feature/java-sdk/issues/1428)) ([3ed65cf](https://github.com/open-feature/java-sdk/commit/3ed65cfb0cb5ee5b70793cd68a27909c81cd4fab))
* skip tests on publish ([6194186](https://github.com/open-feature/java-sdk/commit/6194186b3e791f3cb28da24f5acb3ff96788d65e))
* update publish env vars ([85d89ee](https://github.com/open-feature/java-sdk/commit/85d89ee79a52d960322731fb786c0f60245f0d75))
## [1.15.1](https://github.com/open-feature/java-sdk/compare/v1.14.2...v1.15.1) (2025-05-14)
### NOTABLE CHANGES
* Raise required Java version to 11 ([#1393](https://github.com/open-feature/java-sdk/issues/1393))
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.22.0 ([#1411](https://github.com/open-feature/java-sdk/issues/1411)) ([e251819](https://github.com/open-feature/java-sdk/commit/e25181982af8e5d37be4876b71b337ca86e8454b))
* **deps:** update dependency io.cucumber:cucumber-bom to v7.22.1 ([#1427](https://github.com/open-feature/java-sdk/issues/1427)) ([1c4d2ef](https://github.com/open-feature/java-sdk/commit/1c4d2efafdebb562f099ba1ec3a6a29eabc8ff91))
* **deps:** update dependency io.cucumber:cucumber-bom to v7.22.2 ([#1442](https://github.com/open-feature/java-sdk/issues/1442)) ([e568f3a](https://github.com/open-feature/java-sdk/commit/e568f3a4f560187586d5473aa7bc12a673340e24))
* **deps:** update dependency org.projectlombok:lombok to v1.18.38 ([#1403](https://github.com/open-feature/java-sdk/issues/1403)) ([ef32f11](https://github.com/open-feature/java-sdk/commit/ef32f11571de4d3a981efec4f61113eb8b0d7d9d))
* **deps:** update junit5 monorepo ([#1418](https://github.com/open-feature/java-sdk/issues/1418)) ([97b442e](https://github.com/open-feature/java-sdk/commit/97b442ed6e8f2b99ca949ffd63e5cbf57718c796))
### ✨ New Features
* add logging on provider state transitions ([#1444](https://github.com/open-feature/java-sdk/issues/1444)) ([e2813b2](https://github.com/open-feature/java-sdk/commit/e2813b2e5df8e548caf16e3e425b35962045ca6c))
* add telemetry helper utils ([#1346](https://github.com/open-feature/java-sdk/issues/1346)) ([d0ae548](https://github.com/open-feature/java-sdk/commit/d0ae5482771f4d1701bce25381cdf4e92e2d4882))
* Raise required Java version to 11 ([#1393](https://github.com/open-feature/java-sdk/issues/1393)) ([4dc988b](https://github.com/open-feature/java-sdk/commit/4dc988b637a9e9c377edf7df7b29bf6407319f16))
### 🧹 Chore
* add DCO to release please ([45ec4b1](https://github.com/open-feature/java-sdk/commit/45ec4b1b7734c9117f43abf8fe5105c2903c3986))
* add DCO to release please ([#1429](https://github.com/open-feature/java-sdk/issues/1429)) ([32137bf](https://github.com/open-feature/java-sdk/commit/32137bfa82e9c0391c999bf0be2a36f201620931))
* add publish env ([#1420](https://github.com/open-feature/java-sdk/issues/1420)) ([665dd51](https://github.com/open-feature/java-sdk/commit/665dd51eb2b3b79d3ffccb6cef64d544aa5e7206))
* **deps:** update actions/setup-java digest to 148017a ([#1404](https://github.com/open-feature/java-sdk/issues/1404)) ([f834e11](https://github.com/open-feature/java-sdk/commit/f834e11acc7ecf903e972d80e9dab324be97847e))
* **deps:** update actions/setup-java digest to c5195ef ([#1415](https://github.com/open-feature/java-sdk/issues/1415)) ([a578903](https://github.com/open-feature/java-sdk/commit/a5789038acc36cb2b0ddf12e534a1317e1c9b8e8))
* **deps:** update actions/setup-java digest to f4f1212 ([#1421](https://github.com/open-feature/java-sdk/issues/1421)) ([a3e2a59](https://github.com/open-feature/java-sdk/commit/a3e2a59aebee051ae8c7eb1c5769a04dc9da8de3))
* **deps:** update amannn/action-semantic-pull-request digest to 3352882 ([#1434](https://github.com/open-feature/java-sdk/issues/1434)) ([62ba6db](https://github.com/open-feature/java-sdk/commit/62ba6db457358d759fe83f23318b1cf4200756ac))
* **deps:** update codecov/codecov-action action to v5.4.2 ([#1419](https://github.com/open-feature/java-sdk/issues/1419)) ([a6389e8](https://github.com/open-feature/java-sdk/commit/a6389e89f60aa7f4871f47d78fedd27a7f9991b4))
* **deps:** update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.4 ([#1414](https://github.com/open-feature/java-sdk/issues/1414)) ([e066d3f](https://github.com/open-feature/java-sdk/commit/e066d3f749c09bb1ef79e3bcace1d205a39787df))
* **deps:** update dependency com.h3xstream.findsecbugs:findsecbugs-plugin to v1.14.0 ([#1422](https://github.com/open-feature/java-sdk/issues/1422)) ([495da27](https://github.com/open-feature/java-sdk/commit/495da271bee976a942973cd23012f60db895bf24))
* **deps:** update dependency com.puppycrawl.tools:checkstyle to v10 ([#103](https://github.com/open-feature/java-sdk/issues/103)) ([3403510](https://github.com/open-feature/java-sdk/commit/34035105154b7945c02de2a88fe83eb2414526ef))
* **deps:** update dependency com.tngtech.archunit:archunit-junit5 to v1.4.1 ([#1440](https://github.com/open-feature/java-sdk/issues/1440)) ([78657ee](https://github.com/open-feature/java-sdk/commit/78657ee79efdc94018387cdf8263a73d4abf7191))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.5 ([#1400](https://github.com/open-feature/java-sdk/issues/1400)) ([1f2d071](https://github.com/open-feature/java-sdk/commit/1f2d0715087ebd4554826d8552b250e4b8b950c8))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.5 ([#1401](https://github.com/open-feature/java-sdk/issues/1401)) ([07301bd](https://github.com/open-feature/java-sdk/commit/07301bda3f5b65550eff1e025fc9c0bec3c25275))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.3 ([#1398](https://github.com/open-feature/java-sdk/issues/1398)) ([1fcf0e7](https://github.com/open-feature/java-sdk/commit/1fcf0e77d956c88c54e10942d96d2afd4d79315c))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.3 ([#1399](https://github.com/open-feature/java-sdk/issues/1399)) ([d6ebc16](https://github.com/open-feature/java-sdk/commit/d6ebc161a93ad703e25592abdb0bf0fd9e281bbc))
* **deps:** update dependency org.jacoco:jacoco-maven-plugin to v0.8.13 ([#1407](https://github.com/open-feature/java-sdk/issues/1407)) ([e19ccaa](https://github.com/open-feature/java-sdk/commit/e19ccaa35d9ac4d89d72ea58a70d416d202078db))
* **deps:** update dependency org.mockito:mockito-core to v5.17.0 ([#1409](https://github.com/open-feature/java-sdk/issues/1409)) ([345cdcf](https://github.com/open-feature/java-sdk/commit/345cdcfa10da64c61d769746f335f38ac564e9ad))
* **deps:** update github/codeql-action digest to 15bce5b ([#1443](https://github.com/open-feature/java-sdk/issues/1443)) ([bc10bac](https://github.com/open-feature/java-sdk/commit/bc10bacb5a68d0d2e498cb41c087505490f19de8))
* **deps:** update github/codeql-action digest to 2a8cbad ([#1423](https://github.com/open-feature/java-sdk/issues/1423)) ([6b6849f](https://github.com/open-feature/java-sdk/commit/6b6849f3a3ee8a7b66d859c8e522bc101d1ccd44))
* **deps:** update github/codeql-action digest to 362ef4c ([#1408](https://github.com/open-feature/java-sdk/issues/1408)) ([ca160ca](https://github.com/open-feature/java-sdk/commit/ca160cab7ccd71527e06a0851502353ac50b8d0d))
* **deps:** update github/codeql-action digest to 40e16ed ([#1437](https://github.com/open-feature/java-sdk/issues/1437)) ([f965cbc](https://github.com/open-feature/java-sdk/commit/f965cbcb37d20724e15b76c15842a88574810b1a))
* **deps:** update github/codeql-action digest to 4c3e536 ([#1417](https://github.com/open-feature/java-sdk/issues/1417)) ([0c77c84](https://github.com/open-feature/java-sdk/commit/0c77c8446032eaac7e068d48901e1423c21db326))
* **deps:** update github/codeql-action digest to 4ffa236 ([#1425](https://github.com/open-feature/java-sdk/issues/1425)) ([a7828e7](https://github.com/open-feature/java-sdk/commit/a7828e73a8f2e30f71bd2d9d4da180b2fa436424))
* **deps:** update github/codeql-action digest to 56dd02f ([#1416](https://github.com/open-feature/java-sdk/issues/1416)) ([4607c62](https://github.com/open-feature/java-sdk/commit/4607c62f15f7ee572207b8ec012ad4b3626e0184))
* **deps:** update github/codeql-action digest to 5eb3ed6 ([#1439](https://github.com/open-feature/java-sdk/issues/1439)) ([f2348ea](https://github.com/open-feature/java-sdk/commit/f2348ea370412351389c60eef390f36edbea68b0))
* **deps:** update github/codeql-action digest to 83605b3 ([#1435](https://github.com/open-feature/java-sdk/issues/1435)) ([7e74f2a](https://github.com/open-feature/java-sdk/commit/7e74f2aa3ad2dc8f7a3e4ad398e7705b3e3db364))
* **deps:** update github/codeql-action digest to 97a2bfd ([#1438](https://github.com/open-feature/java-sdk/issues/1438)) ([85b200a](https://github.com/open-feature/java-sdk/commit/85b200a08b9f8a71de3b5a19eaa057ec04e0801e))
* **deps:** update github/codeql-action digest to 9f45e74 ([#1396](https://github.com/open-feature/java-sdk/issues/1396)) ([37d76be](https://github.com/open-feature/java-sdk/commit/37d76be697e83f524250a82b2a67cdb4a953d7bc))
* **deps:** update github/codeql-action digest to d26c46a ([#1413](https://github.com/open-feature/java-sdk/issues/1413)) ([5b327ee](https://github.com/open-feature/java-sdk/commit/5b327eeb770d0a4222f3599be79543b7bed9abc2))
* **deps:** update github/codeql-action digest to dab8a02 ([#1405](https://github.com/open-feature/java-sdk/issues/1405)) ([5b2f151](https://github.com/open-feature/java-sdk/commit/5b2f1513ab75ef6692978830e59eba87ffa494d5))
* **deps:** update github/codeql-action digest to e13fe0d ([#1406](https://github.com/open-feature/java-sdk/issues/1406)) ([e211397](https://github.com/open-feature/java-sdk/commit/e211397d517e1263e1251f9c99093bf05cecd93f))
* **deps:** update github/codeql-action digest to ed51cb5 ([#1436](https://github.com/open-feature/java-sdk/issues/1436)) ([b09e887](https://github.com/open-feature/java-sdk/commit/b09e88798fed529161c61b96c20a8f257d355d3c))
* **deps:** update github/codeql-action digest to efffb48 ([#1402](https://github.com/open-feature/java-sdk/issues/1402)) ([384953d](https://github.com/open-feature/java-sdk/commit/384953d30ecff83d60a2e5b9790e8228d1a52ac7))
* **deps:** update github/codeql-action digest to f843d94 ([#1432](https://github.com/open-feature/java-sdk/issues/1432)) ([99faaf8](https://github.com/open-feature/java-sdk/commit/99faaf88aa07bd45fc473db5bafce3b8eafaf9e0))
* **deps:** update io.cucumber.version to v7.22.0 ([#1410](https://github.com/open-feature/java-sdk/issues/1410)) ([3c69f2f](https://github.com/open-feature/java-sdk/commit/3c69f2f36c4e975d690ecc2e790df632a33001ba))
* **deps:** update io.cucumber.version to v7.22.1 ([#1426](https://github.com/open-feature/java-sdk/issues/1426)) ([844374a](https://github.com/open-feature/java-sdk/commit/844374a42b94deffab6856e978766354a6f46576))
* **deps:** update io.cucumber.version to v7.22.2 ([#1441](https://github.com/open-feature/java-sdk/issues/1441)) ([58454b4](https://github.com/open-feature/java-sdk/commit/58454b4eaabfd3327f7ceaff4bf335a5a839ed41))
* **main:** release 1.15.0 ([#1431](https://github.com/open-feature/java-sdk/issues/1431)) ([7182a7f](https://github.com/open-feature/java-sdk/commit/7182a7fc4197e70218e829971dae2cff09f948c9))
* update boostrap sha for release please ([f6bd30d](https://github.com/open-feature/java-sdk/commit/f6bd30db93e37e596d211d899315a62d9f810199))
* update codeowners to give global maintainers code ownership ([#1412](https://github.com/open-feature/java-sdk/issues/1412)) ([498fd38](https://github.com/open-feature/java-sdk/commit/498fd382659669315b0db61db5f19ce054467bc9))
* update release please action ([#1430](https://github.com/open-feature/java-sdk/issues/1430)) ([1cc851b](https://github.com/open-feature/java-sdk/commit/1cc851b293008a8dd273e904e4c77a650ad71146))
* use PAT for release please ([014f8a5](https://github.com/open-feature/java-sdk/commit/014f8a59da8f1e976e440ed1ea17e85561f98e2d))
### 📚 Documentation
* add try-catch example for setProviderAndWait usage ([#1433](https://github.com/open-feature/java-sdk/issues/1433)) ([96cf9c7](https://github.com/open-feature/java-sdk/commit/96cf9c7f5463e4e0de394117845aebdd9a69425f))
## [1.14.2](https://github.com/open-feature/java-sdk/compare/v1.14.1...v1.14.2) (2025-03-27)
### 🐛 Bug Fixes
* **deps:** update dependency org.slf4j:slf4j-api to v2.0.17 ([#1348](https://github.com/open-feature/java-sdk/issues/1348)) ([2ec7c6c](https://github.com/open-feature/java-sdk/commit/2ec7c6c7ff704380fdfd8116378adf78734e4f2b))
* **deps:** update junit5 monorepo ([#1344](https://github.com/open-feature/java-sdk/issues/1344)) ([d95e270](https://github.com/open-feature/java-sdk/commit/d95e2706532259bd5739e5b4ea4813ef9f2196a6))
* **deps:** update junit5 monorepo ([#1373](https://github.com/open-feature/java-sdk/issues/1373)) ([6b65e26](https://github.com/open-feature/java-sdk/commit/6b65e26c7439895652c3f64f2b4a7307a7ca582e))
* equals and hashcode of several classes ([69b571e](https://github.com/open-feature/java-sdk/commit/69b571eda73b6f43c99864420b8663ae54ebf0ad))
* equals and hashcode of several classes ([#1364](https://github.com/open-feature/java-sdk/issues/1364)) ([69b571e](https://github.com/open-feature/java-sdk/commit/69b571eda73b6f43c99864420b8663ae54ebf0ad))
* hooks not run in NOT_READY/FATAL ([#1392](https://github.com/open-feature/java-sdk/issues/1392)) ([24ef9dd](https://github.com/open-feature/java-sdk/commit/24ef9dd2903d01ec029b70cd1e39e71ffe327499))
### 🧹 Chore
* **deps:** update actions/cache digest to 5a3ec84 ([#1380](https://github.com/open-feature/java-sdk/issues/1380)) ([8359ef1](https://github.com/open-feature/java-sdk/commit/8359ef13bb935ac1d144787cfd7181814a0b286c))
* **deps:** update actions/cache digest to 7921ae2 ([#1337](https://github.com/open-feature/java-sdk/issues/1337)) ([3920c63](https://github.com/open-feature/java-sdk/commit/3920c638a49caddfb07041f812cc6bc0bf3101f9))
* **deps:** update actions/cache digest to d4323d4 ([#1353](https://github.com/open-feature/java-sdk/issues/1353)) ([5901797](https://github.com/open-feature/java-sdk/commit/59017977a487a36c8a39f63b83299bc657134c0d))
* **deps:** update actions/setup-java digest to 3b6c050 ([#1391](https://github.com/open-feature/java-sdk/issues/1391)) ([7536679](https://github.com/open-feature/java-sdk/commit/753667925a8803b3b227f762936ae397dde95484))
* **deps:** update actions/setup-java digest to 799ee7c ([#1359](https://github.com/open-feature/java-sdk/issues/1359)) ([31444d6](https://github.com/open-feature/java-sdk/commit/31444d6c8f30f0dd35debacc9dab8da7397e11ed))
* **deps:** update actions/setup-java digest to b8ebb8b ([#1381](https://github.com/open-feature/java-sdk/issues/1381)) ([2239f05](https://github.com/open-feature/java-sdk/commit/2239f054b90734dde6cdd4a23daec1c1daa96f07))
* **deps:** update amannn/action-semantic-pull-request digest to 04501d4 ([#1390](https://github.com/open-feature/java-sdk/issues/1390)) ([87c06d9](https://github.com/open-feature/java-sdk/commit/87c06d9edd935287daf7ebc8db1e7da4831531de))
* **deps:** update codecov/codecov-action action to v5.4.0 ([#1351](https://github.com/open-feature/java-sdk/issues/1351)) ([b133c2f](https://github.com/open-feature/java-sdk/commit/b133c2fa527a0dddb6de7f7781a00fc84feaa813))
* **deps:** update dependency com.diffplug.spotless:spotless-maven-plugin to v2.44.3 ([#1341](https://github.com/open-feature/java-sdk/issues/1341)) ([5de33c0](https://github.com/open-feature/java-sdk/commit/5de33c02a675db6ca5966bfa3f58d99c8e53e36b))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.1.0 ([#1332](https://github.com/open-feature/java-sdk/issues/1332)) ([cdcdc14](https://github.com/open-feature/java-sdk/commit/cdcdc143ea5ad2f003cb3f5450ec78314e619ea3))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.2.0 ([#1360](https://github.com/open-feature/java-sdk/issues/1360)) ([ecea9df](https://github.com/open-feature/java-sdk/commit/ecea9df932ee4874613f219b73640fe964c99593))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.9.3.0 ([#1375](https://github.com/open-feature/java-sdk/issues/1375)) ([de3e213](https://github.com/open-feature/java-sdk/commit/de3e213ac8b8931121904a3d12929405512e74dd))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.2 ([#1355](https://github.com/open-feature/java-sdk/issues/1355)) ([2a1adca](https://github.com/open-feature/java-sdk/commit/2a1adca8c2ed8d61d51530969290793a5d3d15f3))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.3 ([#1384](https://github.com/open-feature/java-sdk/issues/1384)) ([b6becac](https://github.com/open-feature/java-sdk/commit/b6becac2c4e0f98a8651cc2f77d4c0b081548991))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.4 ([#1387](https://github.com/open-feature/java-sdk/issues/1387)) ([cb574d9](https://github.com/open-feature/java-sdk/commit/cb574d93b6210c89a188aa104ef4f1db68daf1c0))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.2 ([#1356](https://github.com/open-feature/java-sdk/issues/1356)) ([dd83114](https://github.com/open-feature/java-sdk/commit/dd83114c4d9389753575392fafcd56585d7178ae))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.3 ([#1385](https://github.com/open-feature/java-sdk/issues/1385)) ([4125ae8](https://github.com/open-feature/java-sdk/commit/4125ae83801a9f485059a9edaca090ee47b7632f))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.4 ([#1388](https://github.com/open-feature/java-sdk/issues/1388)) ([d8f6514](https://github.com/open-feature/java-sdk/commit/d8f6514598d53f43cb084ee746742a59d271363b))
* **deps:** update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 ([#1342](https://github.com/open-feature/java-sdk/issues/1342)) ([88a778c](https://github.com/open-feature/java-sdk/commit/88a778cc03e112d45756428d1f0ae1ef0fe02c84))
* **deps:** update dependency org.awaitility:awaitility to v4.3.0 ([#1343](https://github.com/open-feature/java-sdk/issues/1343)) ([1504d0f](https://github.com/open-feature/java-sdk/commit/1504d0f7982757a2b413eda593ce7057b90519e5))
* **deps:** update dependency org.mockito:mockito-core to v5.15.2 ([#1339](https://github.com/open-feature/java-sdk/issues/1339)) ([4817864](https://github.com/open-feature/java-sdk/commit/4817864fd7ae70c1e19c3c09e82e1fb03dd88942))
* **deps:** update dependency org.mockito:mockito-core to v5.16.0 ([#1358](https://github.com/open-feature/java-sdk/issues/1358)) ([30b6d00](https://github.com/open-feature/java-sdk/commit/30b6d004aaf3464547805f7eda6fad0e122de4f9))
* **deps:** update dependency org.mockito:mockito-core to v5.16.1 ([#1376](https://github.com/open-feature/java-sdk/issues/1376)) ([9750f75](https://github.com/open-feature/java-sdk/commit/9750f75d04beb8339fc2e972f0ee97120eaff354))
* **deps:** update github/codeql-action digest to 1bb15d0 ([#1336](https://github.com/open-feature/java-sdk/issues/1336)) ([e163ce1](https://github.com/open-feature/java-sdk/commit/e163ce1c060d0dc8812e4a8a3b37f52b0156324d))
* **deps:** update github/codeql-action digest to 486ab5a ([#1389](https://github.com/open-feature/java-sdk/issues/1389)) ([85fd5e0](https://github.com/open-feature/java-sdk/commit/85fd5e0997ff1a5e5d7226d8bbfe2775769a6ca6))
* **deps:** update github/codeql-action digest to 56b25d5 ([#1365](https://github.com/open-feature/java-sdk/issues/1365)) ([959e675](https://github.com/open-feature/java-sdk/commit/959e675e4c2363e5fd80d1d2f1edbfab11794fc8))
* **deps:** update github/codeql-action digest to 608ccd6 ([#1361](https://github.com/open-feature/java-sdk/issues/1361)) ([67b34f8](https://github.com/open-feature/java-sdk/commit/67b34f84a373512013ab2f7649faaddfd2d61048))
* **deps:** update github/codeql-action digest to 6349095 ([#1378](https://github.com/open-feature/java-sdk/issues/1378)) ([dbf92df](https://github.com/open-feature/java-sdk/commit/dbf92df33bf5657d50dc3b2f129207b0097c1f27))
* **deps:** update github/codeql-action digest to 6a151cd ([#1377](https://github.com/open-feature/java-sdk/issues/1377)) ([7065655](https://github.com/open-feature/java-sdk/commit/706565581d78856dd73605b1a16b131f974c0731))
* **deps:** update github/codeql-action digest to 70df9de ([#1372](https://github.com/open-feature/java-sdk/issues/1372)) ([d233480](https://github.com/open-feature/java-sdk/commit/d233480912f1d5e095f5034f36a838535d1ecdff))
* **deps:** update github/codeql-action digest to 7254660 ([#1368](https://github.com/open-feature/java-sdk/issues/1368)) ([d54c68a](https://github.com/open-feature/java-sdk/commit/d54c68a8e9e4a0f67c99e7d76621a1c5724e4cd1))
* **deps:** update github/codeql-action digest to 80f9930 ([#1357](https://github.com/open-feature/java-sdk/issues/1357)) ([6c03e5d](https://github.com/open-feature/java-sdk/commit/6c03e5d84aacee11f5b8e608a6114c11fced72b8))
* **deps:** update github/codeql-action digest to 8392354 ([#1352](https://github.com/open-feature/java-sdk/issues/1352)) ([989f4ae](https://github.com/open-feature/java-sdk/commit/989f4ae54263b46ca2c81561acc70b39918c382d))
* **deps:** update github/codeql-action digest to 8c1551c ([#1333](https://github.com/open-feature/java-sdk/issues/1333)) ([859a36c](https://github.com/open-feature/java-sdk/commit/859a36cbfafc94d4601b87d304237e6ddf97c08d))
* **deps:** update github/codeql-action digest to 8c69433 ([#1347](https://github.com/open-feature/java-sdk/issues/1347)) ([6987568](https://github.com/open-feature/java-sdk/commit/698756856ba40e98d91ccf661dab409798861aa5))
* **deps:** update github/codeql-action digest to 97aac9b ([#1350](https://github.com/open-feature/java-sdk/issues/1350)) ([7df9565](https://github.com/open-feature/java-sdk/commit/7df9565691731d164b534116b8a6b933b171d103))
* **deps:** update github/codeql-action digest to a8849fb ([#1345](https://github.com/open-feature/java-sdk/issues/1345)) ([de64edd](https://github.com/open-feature/java-sdk/commit/de64eddfb3a6cc117bb108dbcf167830e9f6729d))
* **deps:** update github/codeql-action digest to acadfed ([#1335](https://github.com/open-feature/java-sdk/issues/1335)) ([5436eb0](https://github.com/open-feature/java-sdk/commit/5436eb0d5db3a0e9bd9289fbef57b9eeada0a667))
* **deps:** update github/codeql-action digest to b2e6519 ([#1366](https://github.com/open-feature/java-sdk/issues/1366)) ([d00e4b5](https://github.com/open-feature/java-sdk/commit/d00e4b5b24621aa55085827fbe6ea982491376de))
* **deps:** update github/codeql-action digest to b46b37a ([#1367](https://github.com/open-feature/java-sdk/issues/1367)) ([c550d59](https://github.com/open-feature/java-sdk/commit/c550d597227bfc1e0e17357139f1fd8a87593be0))
* **deps:** update github/codeql-action digest to bd1d9ab ([#1383](https://github.com/open-feature/java-sdk/issues/1383)) ([922e17e](https://github.com/open-feature/java-sdk/commit/922e17e677e15690e3df2fe93a961f16f21ff283))
* **deps:** update github/codeql-action digest to c50c157 ([#1379](https://github.com/open-feature/java-sdk/issues/1379)) ([d61c33e](https://github.com/open-feature/java-sdk/commit/d61c33e466336c7120b870ca5e3843eba5f7175c))
* **deps:** update github/codeql-action digest to d99c7e8 ([#1338](https://github.com/open-feature/java-sdk/issues/1338)) ([4e535fd](https://github.com/open-feature/java-sdk/commit/4e535fd10fac742ca472faa62c941fa51b282ca7))
* **deps:** update github/codeql-action digest to dc49dca ([#1369](https://github.com/open-feature/java-sdk/issues/1369)) ([f8df5fb](https://github.com/open-feature/java-sdk/commit/f8df5fb84a765af917587dd509f9cec38103f787))
* **deps:** update github/codeql-action digest to e0ea141 ([#1386](https://github.com/open-feature/java-sdk/issues/1386)) ([387e5f2](https://github.com/open-feature/java-sdk/commit/387e5f2e3bd24ccea6691b0d6dbfe542cfd05b52))
* **deps:** update github/codeql-action digest to ff79de6 ([#1340](https://github.com/open-feature/java-sdk/issues/1340)) ([50b45b2](https://github.com/open-feature/java-sdk/commit/50b45b2be442bb89a431c9bcc45d825f63bd93a6))
* update build and tooling to utilize new java version ([#1321](https://github.com/open-feature/java-sdk/issues/1321)) ([90217b2](https://github.com/open-feature/java-sdk/commit/90217b2083a2ba92c623365dc450326d49b46fab))
## [1.14.1](https://github.com/open-feature/java-sdk/compare/v1.14.0...v1.14.1) (2025-02-14)
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.21.0 ([#1312](https://github.com/open-feature/java-sdk/issues/1312)) ([208411e](https://github.com/open-feature/java-sdk/commit/208411e72338e37bf477ac0b784bbbbe0309b922))
* **deps:** update dependency io.cucumber:cucumber-bom to v7.21.1 ([#1317](https://github.com/open-feature/java-sdk/issues/1317)) ([b797883](https://github.com/open-feature/java-sdk/commit/b7978832b786fe081169ff0efeb702218300c622))
* possible event-related deadlocks with some providers ([#1314](https://github.com/open-feature/java-sdk/issues/1314)) ([c33ac2d](https://github.com/open-feature/java-sdk/commit/c33ac2d9b2e91b85fffb3c21653912fe82006351))
* TrackingEventDetails interface to include numeric getValue() call ([#1328](https://github.com/open-feature/java-sdk/issues/1328)) ([08c38fb](https://github.com/open-feature/java-sdk/commit/08c38fb553d82a42682c3eb9239329f770063898))
### 🧹 Chore
* **deps:** update actions/cache digest to 9fa7e61 ([#1324](https://github.com/open-feature/java-sdk/issues/1324)) ([69cdc77](https://github.com/open-feature/java-sdk/commit/69cdc772a639470dd223bf70ef6e9f8bc4d93dea))
* **deps:** update actions/checkout digest to 85e6279 ([#1287](https://github.com/open-feature/java-sdk/issues/1287)) ([640e35e](https://github.com/open-feature/java-sdk/commit/640e35e85375e3098f61b7397432d80a95502bdd))
* **deps:** update actions/setup-java digest to 28b532b ([#1296](https://github.com/open-feature/java-sdk/issues/1296)) ([874e86d](https://github.com/open-feature/java-sdk/commit/874e86df5c22a1e5771ca16c76aa13039b5f9b65))
* **deps:** update actions/setup-java digest to 3a4f6e1 ([#1306](https://github.com/open-feature/java-sdk/issues/1306)) ([ba9cc4b](https://github.com/open-feature/java-sdk/commit/ba9cc4b85a1082d638d49b9d2d0a4ed5a45f09ee))
* **deps:** update actions/setup-java digest to 51ab6d2 ([#1288](https://github.com/open-feature/java-sdk/issues/1288)) ([c69d3a4](https://github.com/open-feature/java-sdk/commit/c69d3a4bd137c1d6baa47c14228bfe8f96555676))
* **deps:** update actions/setup-java digest to 99d3141 ([#1285](https://github.com/open-feature/java-sdk/issues/1285)) ([32a3933](https://github.com/open-feature/java-sdk/commit/32a39335de8e61650905fc96dc1a73e65f1fe9f8))
* **deps:** update codecov/codecov-action action to v5.2.0 ([#1298](https://github.com/open-feature/java-sdk/issues/1298)) ([531fc38](https://github.com/open-feature/java-sdk/commit/531fc385b662c5b7b334fee298fc9fe1283c78fb))
* **deps:** update codecov/codecov-action action to v5.3.0 ([#1301](https://github.com/open-feature/java-sdk/issues/1301)) ([f7f6586](https://github.com/open-feature/java-sdk/commit/f7f6586d72e3f112a7dafc8f77de273ed49ccc4b))
* **deps:** update codecov/codecov-action action to v5.3.1 ([#1303](https://github.com/open-feature/java-sdk/issues/1303)) ([f9fa54b](https://github.com/open-feature/java-sdk/commit/f9fa54be493e1d0843b709008eb0f047e7580d47))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.16.0 ([#1289](https://github.com/open-feature/java-sdk/issues/1289)) ([0b5b423](https://github.com/open-feature/java-sdk/commit/0b5b423bdd378bb1db3e10fe5da7fa2c937a4610))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.16.1 ([#1292](https://github.com/open-feature/java-sdk/issues/1292)) ([0af9f29](https://github.com/open-feature/java-sdk/commit/0af9f2901f88b5ef9bed0c570d426939a55af3cf))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.0 ([#1309](https://github.com/open-feature/java-sdk/issues/1309)) ([cda3405](https://github.com/open-feature/java-sdk/commit/cda34053f7e39318205a181ef93c825bab2ed9fc))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.17.1 ([#1329](https://github.com/open-feature/java-sdk/issues/1329)) ([9ab2618](https://github.com/open-feature/java-sdk/commit/9ab26182eae4974b60d166777c51dfcb07957150))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.16.0 ([#1290](https://github.com/open-feature/java-sdk/issues/1290)) ([6c4205a](https://github.com/open-feature/java-sdk/commit/6c4205a00817af260ef9b90f54ce878cad33f75a))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.16.1 ([#1293](https://github.com/open-feature/java-sdk/issues/1293)) ([6071932](https://github.com/open-feature/java-sdk/commit/6071932cb4207dc83cdedfa67c8a69ed71d9c26a))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.0 ([#1310](https://github.com/open-feature/java-sdk/issues/1310)) ([40fa173](https://github.com/open-feature/java-sdk/commit/40fa1733382f4c476a1228c6499044ad83c8f3c4))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.17.1 ([#1330](https://github.com/open-feature/java-sdk/issues/1330)) ([4ba5695](https://github.com/open-feature/java-sdk/commit/4ba5695eeea6a7ab2fe1d2c595fa482d4b7868dc))
* **deps:** update dependency org.assertj:assertj-core to v3.27.3 ([#1291](https://github.com/open-feature/java-sdk/issues/1291)) ([a5eb21d](https://github.com/open-feature/java-sdk/commit/a5eb21d1a2e6945a4455cacde898bc913bddb96d))
* **deps:** update github/codeql-action digest to 0701025 ([#1311](https://github.com/open-feature/java-sdk/issues/1311)) ([9a1e9ab](https://github.com/open-feature/java-sdk/commit/9a1e9abd64220c8d8706f2a64e041ef3f37e1a43))
* **deps:** update github/codeql-action digest to 08bc0cf ([#1313](https://github.com/open-feature/java-sdk/issues/1313)) ([37ed6a4](https://github.com/open-feature/java-sdk/commit/37ed6a424cdc013ed74c9881826cc56c93ae8228))
* **deps:** update github/codeql-action digest to 0a35e8f ([#1316](https://github.com/open-feature/java-sdk/issues/1316)) ([26e1d7f](https://github.com/open-feature/java-sdk/commit/26e1d7fff342a32880542efa87b017aec506667e))
* **deps:** update github/codeql-action digest to 0f1559a ([#1286](https://github.com/open-feature/java-sdk/issues/1286)) ([882d2dd](https://github.com/open-feature/java-sdk/commit/882d2dd5bdac007e8a3783efc54fa45faed22054))
* **deps:** update github/codeql-action digest to 10a3f07 ([#1280](https://github.com/open-feature/java-sdk/issues/1280)) ([a3854d6](https://github.com/open-feature/java-sdk/commit/a3854d6ab1dba99f4db18f868e89fcc04418e306))
* **deps:** update github/codeql-action digest to 1c15a48 ([#1325](https://github.com/open-feature/java-sdk/issues/1325)) ([3baf0df](https://github.com/open-feature/java-sdk/commit/3baf0df966f8212864aa7e57bc3d3d09d324fe11))
* **deps:** update github/codeql-action digest to 1efc6bb ([#1281](https://github.com/open-feature/java-sdk/issues/1281)) ([8a1ab7e](https://github.com/open-feature/java-sdk/commit/8a1ab7ea18aff4ee5a6a2fdd1f805b08e51a50a3))
* **deps:** update github/codeql-action digest to 24e1c2d ([#1315](https://github.com/open-feature/java-sdk/issues/1315)) ([46903c6](https://github.com/open-feature/java-sdk/commit/46903c6f275e5f9dc8884acf3f76f76efcfc58bd))
* **deps:** update github/codeql-action digest to 3b4f4d9 ([#1282](https://github.com/open-feature/java-sdk/issues/1282)) ([b390d5f](https://github.com/open-feature/java-sdk/commit/b390d5f0b0945948cd6b87e6486725d095d5ac8a))
* **deps:** update github/codeql-action digest to 43cffee ([#1304](https://github.com/open-feature/java-sdk/issues/1304)) ([6874de6](https://github.com/open-feature/java-sdk/commit/6874de64ce589e853f5523019bfa9e1d60840baf))
* **deps:** update github/codeql-action digest to 54b1c84 ([#1307](https://github.com/open-feature/java-sdk/issues/1307)) ([6f36434](https://github.com/open-feature/java-sdk/commit/6f36434c520dcef27deb04e04941693dc15acb2f))
* **deps:** update github/codeql-action digest to 5f4f998 ([#1305](https://github.com/open-feature/java-sdk/issues/1305)) ([7916d76](https://github.com/open-feature/java-sdk/commit/7916d76635c5ab59dafe6d72058aad9cfcf05f4b))
* **deps:** update github/codeql-action digest to 6063925 ([#1320](https://github.com/open-feature/java-sdk/issues/1320)) ([538140d](https://github.com/open-feature/java-sdk/commit/538140dfe713a421623b179e69b399f82200fe61))
* **deps:** update github/codeql-action digest to 7e3036b ([#1300](https://github.com/open-feature/java-sdk/issues/1300)) ([3491956](https://github.com/open-feature/java-sdk/commit/34919561b73faa0cca489ad480e93cca9a854167))
* **deps:** update github/codeql-action digest to 87fc816 ([#1277](https://github.com/open-feature/java-sdk/issues/1277)) ([c2a82db](https://github.com/open-feature/java-sdk/commit/c2a82dbdbafa134fae4b0c9aef88cf589e09aefa))
* **deps:** update github/codeql-action digest to 93da9f2 ([#1283](https://github.com/open-feature/java-sdk/issues/1283)) ([45b3995](https://github.com/open-feature/java-sdk/commit/45b3995bdad9f1b05abb01455a9c8f57028cfde5))
* **deps:** update github/codeql-action digest to affec20 ([#1323](https://github.com/open-feature/java-sdk/issues/1323)) ([8f3ced5](https://github.com/open-feature/java-sdk/commit/8f3ced590764760244cc81ac10c939ca62504dfe))
* **deps:** update github/codeql-action digest to b44b19f ([#1297](https://github.com/open-feature/java-sdk/issues/1297)) ([305e032](https://github.com/open-feature/java-sdk/commit/305e0329e78116fe697240e420879ac85012d698))
* **deps:** update github/codeql-action digest to d90e07f ([#1294](https://github.com/open-feature/java-sdk/issues/1294)) ([5671184](https://github.com/open-feature/java-sdk/commit/5671184e7f76f979d631c18bb2ebfb15dccfb207))
* **deps:** update github/codeql-action digest to db7177a ([#1279](https://github.com/open-feature/java-sdk/issues/1279)) ([b997946](https://github.com/open-feature/java-sdk/commit/b997946db1c7663b7ebb775ad45cdb2b0aaeb291))
* **deps:** update github/codeql-action digest to e7c0c9d ([#1302](https://github.com/open-feature/java-sdk/issues/1302)) ([78adc77](https://github.com/open-feature/java-sdk/commit/78adc77c23da6116e1f58b3a45dc283c3c58837b))
* **deps:** update github/codeql-action digest to e9987ad ([#1308](https://github.com/open-feature/java-sdk/issues/1308)) ([99d8185](https://github.com/open-feature/java-sdk/commit/99d818572a3407ca6b25f6e91f69ef3e83bdc657))
* **deps:** update github/codeql-action digest to f89b8a7 ([#1295](https://github.com/open-feature/java-sdk/issues/1295)) ([122e82f](https://github.com/open-feature/java-sdk/commit/122e82f8431fb116ae3b147f7e2245d7f90b1c77))
## [1.14.0](https://github.com/open-feature/java-sdk/compare/v1.13.0...v1.14.0) (2025-01-10)
### ⚠ BREAKING CHANGES
The signature of the `finallyAfter` hook stage has been changed. The signature now includes the `evaluation details`, as per the [OpenFeature specification](https://openfeature.dev/specification/sections/hooks#requirement-438). Note that since hooks are still `experimental,` this does not constitute a change requiring a new major version. To migrate, update any hook that implements the `finallyAfter` stage to accept `evaluation details` as the second argument.
* Add evaluation details to finally hook stage [#1246](https://github.com/open-feature/java-sdk/issues/1246) ([#1262](https://github.com/open-feature/java-sdk/issues/1262)) ([ae85278](https://github.com/open-feature/java-sdk/commit/ae85278c30eb5279b80ea73ec6b92db040ad0bb7))
### 🐛 Bug Fixes
* **deps:** update junit5 monorepo ([#1251](https://github.com/open-feature/java-sdk/issues/1251)) ([834f720](https://github.com/open-feature/java-sdk/commit/834f72071806680353f42c750b04e36956736a9e))
### ✨ New Features
* Add evaluation details to finally hook stage [#1246](https://github.com/open-feature/java-sdk/issues/1246) ([#1262](https://github.com/open-feature/java-sdk/issues/1262)) ([ae85278](https://github.com/open-feature/java-sdk/commit/ae85278c30eb5279b80ea73ec6b92db040ad0bb7))
### 🧹 Chore
* **deps:** update actions/cache digest to 36f1e14 ([#1274](https://github.com/open-feature/java-sdk/issues/1274)) ([d825ff8](https://github.com/open-feature/java-sdk/commit/d825ff83639a2bd902bf0559209c2b80e17e0316))
* **deps:** update actions/cache digest to 53aa38c ([#1270](https://github.com/open-feature/java-sdk/issues/1270)) ([a1c558f](https://github.com/open-feature/java-sdk/commit/a1c558f4ffb95772bd141ab7660e2c5b065482f1))
* **deps:** update actions/setup-java digest to 7136edc ([#1244](https://github.com/open-feature/java-sdk/issues/1244)) ([9acc861](https://github.com/open-feature/java-sdk/commit/9acc8612a5fa7ea086da476195154a007cb55b7e))
* **deps:** update actions/setup-java digest to 7a6d8a8 ([#1248](https://github.com/open-feature/java-sdk/issues/1248)) ([86e18c5](https://github.com/open-feature/java-sdk/commit/86e18c5d28a9f5fdd7234274720ba7ddcb529268))
* **deps:** update codecov/codecov-action action to v5.1.2 ([#1255](https://github.com/open-feature/java-sdk/issues/1255)) ([d274cda](https://github.com/open-feature/java-sdk/commit/d274cdac3780286a0b45865864b12c3e4cff9f4b))
* **deps:** update dependency com.google.guava:guava to v33.4.0-jre ([#1253](https://github.com/open-feature/java-sdk/issues/1253)) ([f39c4b5](https://github.com/open-feature/java-sdk/commit/f39c4b5af5e341bfec230d4cecd2037fc5430400))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.11 ([#1249](https://github.com/open-feature/java-sdk/issues/1249)) ([4440cda](https://github.com/open-feature/java-sdk/commit/4440cda6a5b42a903ba11835a975bf6247de845f))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.11 ([#1250](https://github.com/open-feature/java-sdk/issues/1250)) ([6772d3f](https://github.com/open-feature/java-sdk/commit/6772d3f3943fb3b7f7522c80b732aa058fd03bb9))
* **deps:** update dependency org.assertj:assertj-core to v3.27.0 ([#1258](https://github.com/open-feature/java-sdk/issues/1258)) ([c62ade3](https://github.com/open-feature/java-sdk/commit/c62ade3878dabf9194536d551f3316ba5c0ce5e1))
* **deps:** update dependency org.assertj:assertj-core to v3.27.1 ([#1266](https://github.com/open-feature/java-sdk/issues/1266)) ([20bbb23](https://github.com/open-feature/java-sdk/commit/20bbb2337cb5afbee9b8d5143b45416673cb4154))
* **deps:** update dependency org.assertj:assertj-core to v3.27.2 ([#1268](https://github.com/open-feature/java-sdk/issues/1268)) ([2e10d34](https://github.com/open-feature/java-sdk/commit/2e10d34920f57d863c09ce1522c9ccff20413f74))
* **deps:** update github/codeql-action digest to 3407610 ([#1269](https://github.com/open-feature/java-sdk/issues/1269)) ([4086dea](https://github.com/open-feature/java-sdk/commit/4086dea703a950dcacc792be9a9346cc1fa8409d))
* **deps:** update github/codeql-action digest to 4d64ab6 ([#1243](https://github.com/open-feature/java-sdk/issues/1243)) ([884f8fb](https://github.com/open-feature/java-sdk/commit/884f8fbf77c41e070526da0f73e136d4c3e41a4d))
* **deps:** update github/codeql-action digest to 562042d ([#1254](https://github.com/open-feature/java-sdk/issues/1254)) ([6a79874](https://github.com/open-feature/java-sdk/commit/6a7987455ef7e46d40b835c7d8dbda29322e3b2d))
* **deps:** update github/codeql-action digest to 5b6e617 ([#1263](https://github.com/open-feature/java-sdk/issues/1263)) ([f1817d8](https://github.com/open-feature/java-sdk/commit/f1817d8fef585f957de1cfb9222b03cb591ed2e9))
* **deps:** update github/codeql-action digest to 64cc90b ([#1256](https://github.com/open-feature/java-sdk/issues/1256)) ([992c003](https://github.com/open-feature/java-sdk/commit/992c00396cb2fca6a6a7dc63d727b063a79386b6))
* **deps:** update github/codeql-action digest to 7876007 ([#1260](https://github.com/open-feature/java-sdk/issues/1260)) ([fc6f35e](https://github.com/open-feature/java-sdk/commit/fc6f35e581cacb0ad149c58a5943ec1429ce25ca))
* **deps:** update github/codeql-action digest to 78d0136 ([#1245](https://github.com/open-feature/java-sdk/issues/1245)) ([fd1c170](https://github.com/open-feature/java-sdk/commit/fd1c1702c6d4067c432c1522143266ddf470d18d))
* **deps:** update github/codeql-action digest to 8975792 ([#1241](https://github.com/open-feature/java-sdk/issues/1241)) ([b0abfd0](https://github.com/open-feature/java-sdk/commit/b0abfd02cf9e97f7409df3296818ac990b429058))
* **deps:** update github/codeql-action digest to 9d59969 ([#1252](https://github.com/open-feature/java-sdk/issues/1252)) ([482a5ae](https://github.com/open-feature/java-sdk/commit/482a5aef1005b2ebe2fdb9ee43243b6c2aeeadc8))
* **deps:** update github/codeql-action digest to d01b25e ([#1257](https://github.com/open-feature/java-sdk/issues/1257)) ([6d60c96](https://github.com/open-feature/java-sdk/commit/6d60c962fbac48a13d86271b361fb0cfd91a5342))
* **deps:** update github/codeql-action digest to dd75594 ([#1247](https://github.com/open-feature/java-sdk/issues/1247)) ([6d169f5](https://github.com/open-feature/java-sdk/commit/6d169f55e235a071033a9bf1138484f09a5e472d))
* **deps:** update github/codeql-action digest to e83e0a4 ([#1275](https://github.com/open-feature/java-sdk/issues/1275)) ([9c92ebb](https://github.com/open-feature/java-sdk/commit/9c92ebb1bdb23c80461f143753f2fb42956462e3))
* **deps:** update github/codeql-action digest to fb65b6c ([#1273](https://github.com/open-feature/java-sdk/issues/1273)) ([3c97b7b](https://github.com/open-feature/java-sdk/commit/3c97b7baaf9eee719479c059cb923d8d64f2c25f))
## [1.13.0](https://github.com/open-feature/java-sdk/compare/v1.12.2...v1.13.0) (2024-12-07)
### 🐛 Bug Fixes
* **deps:** update dependency org.projectlombok:lombok to v1.18.36 ([#1219](https://github.com/open-feature/java-sdk/issues/1219)) ([9cadc71](https://github.com/open-feature/java-sdk/commit/9cadc71d9d8a2a88f9c716c27eb939f423b95fa0))
### ✨ New Features
* add tracking as per spec ([#1228](https://github.com/open-feature/java-sdk/issues/1228)) ([64ad644](https://github.com/open-feature/java-sdk/commit/64ad644bdbb6a4535da8ec7628e74d5f41f7ebec))
### 🧹 Chore
* **deps:** update actions/cache digest to 1bd1e32 ([#1237](https://github.com/open-feature/java-sdk/issues/1237)) ([da725d8](https://github.com/open-feature/java-sdk/commit/da725d89e03d499a37307cca47b2c51af5ac8782))
* **deps:** update actions/checkout digest to 3b9b8c8 ([#1206](https://github.com/open-feature/java-sdk/issues/1206)) ([446e298](https://github.com/open-feature/java-sdk/commit/446e2987e9b80175dff0ea72de9f58ba8e0dd323))
* **deps:** update actions/checkout digest to cbb7224 ([#1216](https://github.com/open-feature/java-sdk/issues/1216)) ([273efc6](https://github.com/open-feature/java-sdk/commit/273efc62a7bb2e3fe962036d82818eb1da43b197))
* **deps:** update amannn/action-semantic-pull-request digest to 40166f0 ([#1212](https://github.com/open-feature/java-sdk/issues/1212)) ([d5228f5](https://github.com/open-feature/java-sdk/commit/d5228f5ccfa55753178425c55a02af1833168513))
* **deps:** update codecov/codecov-action action to v5 ([#1217](https://github.com/open-feature/java-sdk/issues/1217)) ([7aa77b8](https://github.com/open-feature/java-sdk/commit/7aa77b8614401c56e8387d55382e4be115a7d1ef))
* **deps:** update codecov/codecov-action action to v5.0.2 ([#1218](https://github.com/open-feature/java-sdk/issues/1218)) ([1b4947f](https://github.com/open-feature/java-sdk/commit/1b4947f108c15a4777bb35bafb631a40c7e20e77))
* **deps:** update codecov/codecov-action action to v5.0.3 ([#1223](https://github.com/open-feature/java-sdk/issues/1223)) ([e91194a](https://github.com/open-feature/java-sdk/commit/e91194ae16c1d68033a750050af18de68a618f61))
* **deps:** update codecov/codecov-action action to v5.0.4 ([#1224](https://github.com/open-feature/java-sdk/issues/1224)) ([19ed5c7](https://github.com/open-feature/java-sdk/commit/19ed5c7c97dc286a85faae1c4906508f97191497))
* **deps:** update codecov/codecov-action action to v5.0.6 ([#1226](https://github.com/open-feature/java-sdk/issues/1226)) ([13811dc](https://github.com/open-feature/java-sdk/commit/13811dcf254b604ec73b4df184d432f1dc404398))
* **deps:** update codecov/codecov-action action to v5.0.7 ([#1227](https://github.com/open-feature/java-sdk/issues/1227)) ([234062c](https://github.com/open-feature/java-sdk/commit/234062cf338036b3b942b83c00b31191fb626432))
* **deps:** update codecov/codecov-action action to v5.1.1 ([#1238](https://github.com/open-feature/java-sdk/issues/1238)) ([c5ad1b4](https://github.com/open-feature/java-sdk/commit/c5ad1b4d4f805a6ae070eabc6de38b37dd759c05))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.6 ([#1213](https://github.com/open-feature/java-sdk/issues/1213)) ([92c8791](https://github.com/open-feature/java-sdk/commit/92c87913ac417b8b3651290a4df828bdf5d501b9))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.10 ([#1202](https://github.com/open-feature/java-sdk/issues/1202)) ([d959059](https://github.com/open-feature/java-sdk/commit/d95905917730dcb8724fe166682ca773a536eb9b))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.8 ([#1195](https://github.com/open-feature/java-sdk/issues/1195)) ([309f28b](https://github.com/open-feature/java-sdk/commit/309f28b520a8f629a500c359b1f522ba687bcc6b))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.9 ([#1197](https://github.com/open-feature/java-sdk/issues/1197)) ([54a2345](https://github.com/open-feature/java-sdk/commit/54a234519f36ea803ec8574f27c94a9f754bf822))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.10 ([#1203](https://github.com/open-feature/java-sdk/issues/1203)) ([2bb2ed3](https://github.com/open-feature/java-sdk/commit/2bb2ed39928e0e15d369741df8b877c751e8d122))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.8 ([#1196](https://github.com/open-feature/java-sdk/issues/1196)) ([30eb2ce](https://github.com/open-feature/java-sdk/commit/30eb2ce082ae2854025be084da98fb856dbcd17c))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.9 ([#1198](https://github.com/open-feature/java-sdk/issues/1198)) ([e32a712](https://github.com/open-feature/java-sdk/commit/e32a712615f3b1be9cff61f1337d5b00c365c8f5))
* **deps:** update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.6.0 ([#1188](https://github.com/open-feature/java-sdk/issues/1188)) ([89c7f85](https://github.com/open-feature/java-sdk/commit/89c7f85da436b9f16193948183a1ca54eea6ceef))
* **deps:** update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.8.1 ([#1187](https://github.com/open-feature/java-sdk/issues/1187)) ([5c7c287](https://github.com/open-feature/java-sdk/commit/5c7c28706e4614061b042080820b9efd04afc342))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.2 ([#1199](https://github.com/open-feature/java-sdk/issues/1199)) ([08da9a3](https://github.com/open-feature/java-sdk/commit/08da9a34395a3e96dc2172f0f0533a4905cff204))
* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.11.1 ([#1201](https://github.com/open-feature/java-sdk/issues/1201)) ([a2a57ab](https://github.com/open-feature/java-sdk/commit/a2a57ab8f1161b5de3a112bbbdc421985baf304b))
* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.11.2 ([#1240](https://github.com/open-feature/java-sdk/issues/1240)) ([c87c6e7](https://github.com/open-feature/java-sdk/commit/c87c6e7a760e84a5e8d9a6d935ef35611d1de8ab))
* **deps:** update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.26.0 ([#1189](https://github.com/open-feature/java-sdk/issues/1189)) ([d5082cd](https://github.com/open-feature/java-sdk/commit/d5082cd5f6907b6e7649813dbbea99cdeab20728))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.2 ([#1200](https://github.com/open-feature/java-sdk/issues/1200)) ([d2cb092](https://github.com/open-feature/java-sdk/commit/d2cb092b09966bc2d5a7548e35b71ab2e56e0dee))
* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.9.1 ([#1230](https://github.com/open-feature/java-sdk/issues/1230)) ([764d665](https://github.com/open-feature/java-sdk/commit/764d6650e659aa93c1da66db348a2eb3641ae92f))
* **deps:** update dependency org.simplify4u:slf4j2-mock to v2.4.0 ([#1208](https://github.com/open-feature/java-sdk/issues/1208)) ([a3ced47](https://github.com/open-feature/java-sdk/commit/a3ced47e5dc23badae4f008e5cf4e97c588fdfd4))
* **deps:** update github/codeql-action digest to 024283f ([#1211](https://github.com/open-feature/java-sdk/issues/1211)) ([1df5441](https://github.com/open-feature/java-sdk/commit/1df54411b758c67afaf47f103e357cb551e0efca))
* **deps:** update github/codeql-action digest to 3096afe ([#1235](https://github.com/open-feature/java-sdk/issues/1235)) ([409fd04](https://github.com/open-feature/java-sdk/commit/409fd042f3921948ef0dabd58d0ef7a4c380b5fb))
* **deps:** update github/codeql-action digest to 3aa7135 ([#1186](https://github.com/open-feature/java-sdk/issues/1186)) ([4e3a329](https://github.com/open-feature/java-sdk/commit/4e3a329c406cc72a268f05766290633c67a9aae0))
* **deps:** update github/codeql-action digest to 3d3d628 ([#1229](https://github.com/open-feature/java-sdk/issues/1229)) ([a0723ec](https://github.com/open-feature/java-sdk/commit/a0723ec2f886aa834662f2e54bcce5f052262dac))
* **deps:** update github/codeql-action digest to 3ef4c08 ([#1205](https://github.com/open-feature/java-sdk/issues/1205)) ([eb4f625](https://github.com/open-feature/java-sdk/commit/eb4f6255615a77c65a79002f1233d1efe5eccd37))
* **deps:** update github/codeql-action digest to 48c3e26 ([#1193](https://github.com/open-feature/java-sdk/issues/1193)) ([8621944](https://github.com/open-feature/java-sdk/commit/86219446337e9c73a41b8517b1e26fa044d3bbaa))
* **deps:** update github/codeql-action digest to 4dc1519 ([#1209](https://github.com/open-feature/java-sdk/issues/1209)) ([1c21d24](https://github.com/open-feature/java-sdk/commit/1c21d2444b31f61d6d83dfd8f6982f7ad71f708b))
* **deps:** update github/codeql-action digest to 5ac2ddd ([#1204](https://github.com/open-feature/java-sdk/issues/1204)) ([3a9fd60](https://github.com/open-feature/java-sdk/commit/3a9fd60fd4a9595a729995a59a0c4ef9625444bc))
* **deps:** update github/codeql-action digest to 5cb4249 ([#1210](https://github.com/open-feature/java-sdk/issues/1210)) ([a94bd37](https://github.com/open-feature/java-sdk/commit/a94bd37cff0c6d7b9f535335709d69b79db2c91e))
* **deps:** update github/codeql-action digest to 6a38de6 ([#1190](https://github.com/open-feature/java-sdk/issues/1190)) ([f3163df](https://github.com/open-feature/java-sdk/commit/f3163dfbd4b3997a0335699a2472373a846cf710))
* **deps:** update github/codeql-action digest to 6e3a010 ([#1214](https://github.com/open-feature/java-sdk/issues/1214)) ([9f37927](https://github.com/open-feature/java-sdk/commit/9f37927eaa60e53d1c7db192ca8e6e117f7f0017))
* **deps:** update github/codeql-action digest to 6f9e628 ([#1239](https://github.com/open-feature/java-sdk/issues/1239)) ([baaa78b](https://github.com/open-feature/java-sdk/commit/baaa78b7ec34a3e508fda3ed8c3ea5382f1e18ea))
* **deps:** update github/codeql-action digest to 978ed82 ([#1234](https://github.com/open-feature/java-sdk/issues/1234)) ([bb3272d](https://github.com/open-feature/java-sdk/commit/bb3272d36479bde2594fe0bb64cea21d30299931))
* **deps:** update github/codeql-action digest to 9f93f47 ([#1191](https://github.com/open-feature/java-sdk/issues/1191)) ([f99de6f](https://github.com/open-feature/java-sdk/commit/f99de6fa55bea093418ecc85ea79e9e30ce03d6b))
* **deps:** update github/codeql-action digest to a1695c5 ([#1215](https://github.com/open-feature/java-sdk/issues/1215)) ([6d3bb69](https://github.com/open-feature/java-sdk/commit/6d3bb694204107f21552b48c5f6f056fa37e6cc0))
* **deps:** update github/codeql-action digest to a6c8729 ([#1222](https://github.com/open-feature/java-sdk/issues/1222)) ([bbc934c](https://github.com/open-feature/java-sdk/commit/bbc934c6d91af39b9ff384ebd58756d48b00415a))
* **deps:** update github/codeql-action digest to acb9cb1 ([#1207](https://github.com/open-feature/java-sdk/issues/1207)) ([21dbd3f](https://github.com/open-feature/java-sdk/commit/21dbd3fc4c29acbb6b74cdb6b82bc5bb4dd5523e))
* **deps:** update github/codeql-action digest to af49565 ([#1231](https://github.com/open-feature/java-sdk/issues/1231)) ([4bbaf51](https://github.com/open-feature/java-sdk/commit/4bbaf517536386f53bd92ceaf62eb08fe4859e80))
* **deps:** update github/codeql-action digest to b91f43b ([#1184](https://github.com/open-feature/java-sdk/issues/1184)) ([d0309ea](https://github.com/open-feature/java-sdk/commit/d0309eaa6616ef9e9caf8e605895ac82c8f4d780))
* **deps:** update github/codeql-action digest to cba5fb5 ([#1221](https://github.com/open-feature/java-sdk/issues/1221)) ([37f0f06](https://github.com/open-feature/java-sdk/commit/37f0f06467b10541755e723ff26144b716a26464))
* **deps:** update github/codeql-action digest to cbe1897 ([#1194](https://github.com/open-feature/java-sdk/issues/1194)) ([2dba3a7](https://github.com/open-feature/java-sdk/commit/2dba3a737dac6fefcbb1f56b292cacdca62735b5))
* **deps:** update github/codeql-action digest to e782c3a ([#1220](https://github.com/open-feature/java-sdk/issues/1220)) ([45d0656](https://github.com/open-feature/java-sdk/commit/45d065652004ecc0703af3b9c6fbfd2b45e69056))
* **deps:** update github/codeql-action digest to ef2fd42 ([#1232](https://github.com/open-feature/java-sdk/issues/1232)) ([b3549a1](https://github.com/open-feature/java-sdk/commit/b3549a1b4aa2bc27c38f66e3a0657b62d8ffc1b4))
* **deps:** update github/codeql-action digest to f1c289a ([#1233](https://github.com/open-feature/java-sdk/issues/1233)) ([5b460ea](https://github.com/open-feature/java-sdk/commit/5b460ead7e5f21eb7c86e9ae78740a2e26957420))
* **deps:** update github/codeql-action digest to f8e782a ([#1225](https://github.com/open-feature/java-sdk/issues/1225)) ([3227623](https://github.com/open-feature/java-sdk/commit/32276234257f82de98bcb01094c7219611e2c707))
## [1.12.2](https://github.com/open-feature/java-sdk/compare/v1.12.1...v1.12.2) (2024-10-24)
### 🐛 Bug Fixes
* **deps:** update junit5 monorepo ([#1171](https://github.com/open-feature/java-sdk/issues/1171)) ([02eed7a](https://github.com/open-feature/java-sdk/commit/02eed7a32c250483348d04925fe6840420b968cb))
### 🧹 Chore
* blocking set-provider in test ([d6d284b](https://github.com/open-feature/java-sdk/commit/d6d284b6a3e615ad90505bd183b098b084037616))
* **deps:** update actions/cache digest to 6849a64 ([#1174](https://github.com/open-feature/java-sdk/issues/1174)) ([cedad9c](https://github.com/open-feature/java-sdk/commit/cedad9c2c6b6fd5c4b56b30ee5cd471fe4410a40))
* **deps:** update actions/checkout digest to 11bd719 ([#1183](https://github.com/open-feature/java-sdk/issues/1183)) ([74958fd](https://github.com/open-feature/java-sdk/commit/74958fd261b0154d156d684e0e01360b8f3ba589))
* **deps:** update actions/checkout digest to 163217d ([#1168](https://github.com/open-feature/java-sdk/issues/1168)) ([3f1cfed](https://github.com/open-feature/java-sdk/commit/3f1cfed913537c245284ff59d058982d1ebc8ce3))
* **deps:** update actions/setup-java digest to 8df1039 ([#1172](https://github.com/open-feature/java-sdk/issues/1172)) ([a432760](https://github.com/open-feature/java-sdk/commit/a432760fc936b6a1c4ab2ed779c8ab49e6fe1eff))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.5 ([#1173](https://github.com/open-feature/java-sdk/issues/1173)) ([b08e8d5](https://github.com/open-feature/java-sdk/commit/b08e8d5537942e8ae8c822f0466f6e18459d2d8d))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.5 ([#1165](https://github.com/open-feature/java-sdk/issues/1165)) ([2d3be26](https://github.com/open-feature/java-sdk/commit/2d3be2617b78d200162ce816e829abda80e130a2))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.7 ([#1179](https://github.com/open-feature/java-sdk/issues/1179)) ([0db0a50](https://github.com/open-feature/java-sdk/commit/0db0a50cf40d62e9880ca68f577c43fe86497532))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.5 ([#1166](https://github.com/open-feature/java-sdk/issues/1166)) ([51a3410](https://github.com/open-feature/java-sdk/commit/51a3410d8e8c85bb0b142e6a64b889795742de86))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.7 ([#1180](https://github.com/open-feature/java-sdk/issues/1180)) ([36620f8](https://github.com/open-feature/java-sdk/commit/36620f84081bb38cc542330ea44e84f6f5754093))
* **deps:** update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.0 ([#1175](https://github.com/open-feature/java-sdk/issues/1175)) ([c8c70e2](https://github.com/open-feature/java-sdk/commit/c8c70e23e807681d271ddcb3dc6879dd80cb1c02))
* **deps:** update github/codeql-action digest to 0a30541 ([#1170](https://github.com/open-feature/java-sdk/issues/1170)) ([59139a2](https://github.com/open-feature/java-sdk/commit/59139a21867e99e65c9460fba35403efe0aa6f50))
* **deps:** update github/codeql-action digest to 467d7e6 ([#1181](https://github.com/open-feature/java-sdk/issues/1181)) ([7a1eb9b](https://github.com/open-feature/java-sdk/commit/7a1eb9b9e94db003e2ada37ecb32cf912eef8766))
* **deps:** update github/codeql-action digest to af56b04 ([#1167](https://github.com/open-feature/java-sdk/issues/1167)) ([432ec43](https://github.com/open-feature/java-sdk/commit/432ec438efdbe54e2300dd78db9fff1ce73fd725))
* **deps:** update github/codeql-action digest to b35b023 ([#1176](https://github.com/open-feature/java-sdk/issues/1176)) ([9fb469f](https://github.com/open-feature/java-sdk/commit/9fb469f8e8f45afcf55edadcef4d73753d80e0e0))
* **deps:** update github/codeql-action digest to b7cdb7f ([#1177](https://github.com/open-feature/java-sdk/issues/1177)) ([a085896](https://github.com/open-feature/java-sdk/commit/a08589664c6464df5443eccdb1b2e9eba84313eb))
* **deps:** update github/codeql-action digest to c470063 ([#1163](https://github.com/open-feature/java-sdk/issues/1163)) ([4e39b55](https://github.com/open-feature/java-sdk/commit/4e39b55bda516bb07ffd7452169dc77b1c0e340f))
* fix another flaky test ([473a057](https://github.com/open-feature/java-sdk/commit/473a05784cd25dfafdd8f55894b06c8503fb19af))
* fix flaky test ([457da96](https://github.com/open-feature/java-sdk/commit/457da96e7ba328f572e086c614b6700e9fd1c8c8))
* flaky test ([#1169](https://github.com/open-feature/java-sdk/issues/1169)) ([d6d284b](https://github.com/open-feature/java-sdk/commit/d6d284b6a3e615ad90505bd183b098b084037616))
* improve benchmark realism; add more context ([#1182](https://github.com/open-feature/java-sdk/issues/1182)) ([0009e23](https://github.com/open-feature/java-sdk/commit/0009e23c7b38dff78afc7addede41fed16937976))
### 🚀 Performance
* reduce hashmap allocations ([#1178](https://github.com/open-feature/java-sdk/issues/1178)) ([fd7659a](https://github.com/open-feature/java-sdk/commit/fd7659a46fa7a8c4a04a09217abe7ab228779c7e))
## [1.12.1](https://github.com/open-feature/java-sdk/compare/v1.12.0...v1.12.1) (2024-10-15)
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.20.0 ([#1142](https://github.com/open-feature/java-sdk/issues/1142)) ([e657383](https://github.com/open-feature/java-sdk/commit/e6573838a02df1e917b27a5ae2ad7cef0c4d6b3f))
* **deps:** update dependency io.cucumber:cucumber-bom to v7.20.1 ([#1153](https://github.com/open-feature/java-sdk/issues/1153)) ([7ccc896](https://github.com/open-feature/java-sdk/commit/7ccc896665b56eddb16f2fd9dd63d489de9d3197))
* **deps:** update junit5 monorepo ([#1121](https://github.com/open-feature/java-sdk/issues/1121)) ([91fffb3](https://github.com/open-feature/java-sdk/commit/91fffb35600162454b0600017bfc33b920922455))
* **deps:** update junit5 monorepo ([#1141](https://github.com/open-feature/java-sdk/issues/1141)) ([20ea6bd](https://github.com/open-feature/java-sdk/commit/20ea6bd99dba350b41f730c548ce28aa6d7680c2))
### 🧹 Chore
* **deps:** update actions/cache digest to 2cdf405 ([#1143](https://github.com/open-feature/java-sdk/issues/1143)) ([a0041c1](https://github.com/open-feature/java-sdk/commit/a0041c10e484aa2ea6bd63efcaac6c4570e1c1a4))
* **deps:** update actions/cache digest to 8469c94 ([#1151](https://github.com/open-feature/java-sdk/issues/1151)) ([fdda5e9](https://github.com/open-feature/java-sdk/commit/fdda5e94b615e073dcc103442d61b33cc444f19f))
* **deps:** update actions/cache digest to a11fb02 ([#1138](https://github.com/open-feature/java-sdk/issues/1138)) ([43f076a](https://github.com/open-feature/java-sdk/commit/43f076a1251569232b31e98120f29b62628717ac))
* **deps:** update actions/checkout digest to 6b42224 ([#1137](https://github.com/open-feature/java-sdk/issues/1137)) ([0c8ff47](https://github.com/open-feature/java-sdk/commit/0c8ff472f2011f4a32ac7fb3252b9362e7ba98e3))
* **deps:** update actions/checkout digest to d632683 ([#1122](https://github.com/open-feature/java-sdk/issues/1122)) ([2393924](https://github.com/open-feature/java-sdk/commit/2393924592b9a9cfd44ed4b4be6effeb5e7eca28))
* **deps:** update actions/checkout digest to de5a000 ([#1134](https://github.com/open-feature/java-sdk/issues/1134)) ([626f5e1](https://github.com/open-feature/java-sdk/commit/626f5e17c0be58fe5c4b0a286a51fb85ac734c2d))
* **deps:** update actions/checkout digest to eef6144 ([#1149](https://github.com/open-feature/java-sdk/issues/1149)) ([16ec4e4](https://github.com/open-feature/java-sdk/commit/16ec4e459b58710664db2d7831611695d6525ff5))
* **deps:** update actions/setup-java digest to 292cc14 ([#1124](https://github.com/open-feature/java-sdk/issues/1124)) ([f2c37ea](https://github.com/open-feature/java-sdk/commit/f2c37eacc2982c47408b95839b68f33c6f7f31a5))
* **deps:** update actions/setup-java digest to 83a06ff ([#1158](https://github.com/open-feature/java-sdk/issues/1158)) ([98a7ed0](https://github.com/open-feature/java-sdk/commit/98a7ed0727ba160642ad342f1d40e9c69980f4db))
* **deps:** update actions/setup-java digest to b36c23c ([#1114](https://github.com/open-feature/java-sdk/issues/1114)) ([5d97803](https://github.com/open-feature/java-sdk/commit/5d9780333a04e507c2eb56253750725d14142b53))
* **deps:** update codecov/codecov-action action to v4.6.0 ([#1132](https://github.com/open-feature/java-sdk/issues/1132)) ([f7d6202](https://github.com/open-feature/java-sdk/commit/f7d6202e131f7fd8370831c018787c0aa9deae39))
* **deps:** update dependency com.google.guava:guava to v33.3.1-jre ([#1116](https://github.com/open-feature/java-sdk/issues/1116)) ([ce06eee](https://github.com/open-feature/java-sdk/commit/ce06eee9dfe7769f4084baf8a44e18063cbc10fc))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.2 ([#1119](https://github.com/open-feature/java-sdk/issues/1119)) ([b919333](https://github.com/open-feature/java-sdk/commit/b9193338237b7e25d415b8d81718208f885e0a51))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.3 ([#1125](https://github.com/open-feature/java-sdk/issues/1125)) ([5863541](https://github.com/open-feature/java-sdk/commit/58635411bd0f99a9a45d3832d2fee047202befff))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.4 ([#1154](https://github.com/open-feature/java-sdk/issues/1154)) ([4f32aba](https://github.com/open-feature/java-sdk/commit/4f32abaf84059696a63b7aa0d562a0bc6ef8c9f8))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.2 ([#1120](https://github.com/open-feature/java-sdk/issues/1120)) ([c5bace6](https://github.com/open-feature/java-sdk/commit/c5bace6ff258bbe7ed5c23b6abd22892de1cdc19))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.3 ([#1126](https://github.com/open-feature/java-sdk/issues/1126)) ([8765cf3](https://github.com/open-feature/java-sdk/commit/8765cf344087b0e2c76fe8df1d8440eeb85ae209))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.4 ([#1155](https://github.com/open-feature/java-sdk/issues/1155)) ([82a5eb5](https://github.com/open-feature/java-sdk/commit/82a5eb568781c057fcbfc7684d9d6283303d9e0a))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.1 ([#1147](https://github.com/open-feature/java-sdk/issues/1147)) ([aaab159](https://github.com/open-feature/java-sdk/commit/aaab1598a177e1596b052c00e054bc77f7f73f58))
* **deps:** update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.7 ([#1128](https://github.com/open-feature/java-sdk/issues/1128)) ([3816151](https://github.com/open-feature/java-sdk/commit/3816151b876282d5a2aec80e0addc8ee572ea679))
* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.10.1 ([#1131](https://github.com/open-feature/java-sdk/issues/1131)) ([d4dac27](https://github.com/open-feature/java-sdk/commit/d4dac274eecd65f00f2e79a591ca867eedf454c5))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.1 ([#1144](https://github.com/open-feature/java-sdk/issues/1144)) ([0c0c5f4](https://github.com/open-feature/java-sdk/commit/0c0c5f4ad9c86ed47b38b70c74c6c30dc4266866))
* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.8.2 ([#1123](https://github.com/open-feature/java-sdk/issues/1123)) ([db1bc75](https://github.com/open-feature/java-sdk/commit/db1bc75cdeae1147a44e953d267583359b202ef6))
* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.9.0 ([#1150](https://github.com/open-feature/java-sdk/issues/1150)) ([6d38b2c](https://github.com/open-feature/java-sdk/commit/6d38b2c5a9d578279a2eeff8a22d39eedb6aaf23))
* **deps:** update github/codeql-action digest to 0c3e006 ([#1159](https://github.com/open-feature/java-sdk/issues/1159)) ([a881376](https://github.com/open-feature/java-sdk/commit/a8813760d6cce9124d9b90b5e9affeb87f29cb51))
* **deps:** update github/codeql-action digest to 2617ff2 ([#1127](https://github.com/open-feature/java-sdk/issues/1127)) ([93f4feb](https://github.com/open-feature/java-sdk/commit/93f4feb818367fdf1f3f8dd55ac1bdffaf34d5f6))
* **deps:** update github/codeql-action digest to 38469af ([#1157](https://github.com/open-feature/java-sdk/issues/1157)) ([20e3a5d](https://github.com/open-feature/java-sdk/commit/20e3a5d3fe6374e762e8439eb198c8968c2066b4))
* **deps:** update github/codeql-action digest to 426821d ([#1115](https://github.com/open-feature/java-sdk/issues/1115)) ([a2a55e8](https://github.com/open-feature/java-sdk/commit/a2a55e8f3170172921a132edcb23197a0a03b8a3))
* **deps:** update github/codeql-action digest to 46e0c78 ([#1118](https://github.com/open-feature/java-sdk/issues/1118)) ([90c6566](https://github.com/open-feature/java-sdk/commit/90c65666e2ec5e5dcd3cba991202fe867ebcc15d))
* **deps:** update github/codeql-action digest to 5636274 ([#1161](https://github.com/open-feature/java-sdk/issues/1161)) ([b144763](https://github.com/open-feature/java-sdk/commit/b1447632992c1c474bb7edfad632f85a7e0c21a9))
* **deps:** update github/codeql-action digest to 56d1975 ([#1145](https://github.com/open-feature/java-sdk/issues/1145)) ([2489e40](https://github.com/open-feature/java-sdk/commit/2489e40c290421040a8ae21ee1435055dbcd3e24))
* **deps:** update github/codeql-action digest to 572cc52 ([#1148](https://github.com/open-feature/java-sdk/issues/1148)) ([03e6604](https://github.com/open-feature/java-sdk/commit/03e66049601c64fec4c8b516ec5557a3f82ab828))
* **deps:** update github/codeql-action digest to 7cf65a5 ([#1140](https://github.com/open-feature/java-sdk/issues/1140)) ([9eb64a7](https://github.com/open-feature/java-sdk/commit/9eb64a747151f791d740f986c9dd358cbb813acc))
* **deps:** update github/codeql-action digest to 8aba5f2 ([#1136](https://github.com/open-feature/java-sdk/issues/1136)) ([16e1dec](https://github.com/open-feature/java-sdk/commit/16e1dec928bf9252339bcff433cd3cb7435554d9))
* **deps:** update github/codeql-action digest to 8b33300 ([#1139](https://github.com/open-feature/java-sdk/issues/1139)) ([1f2c5a1](https://github.com/open-feature/java-sdk/commit/1f2c5a1b2a669c65364e8e24e0824de791f4a4b4))
* **deps:** update github/codeql-action digest to 9d1e406 ([#1152](https://github.com/open-feature/java-sdk/issues/1152)) ([e982216](https://github.com/open-feature/java-sdk/commit/e982216f705763bf1cb2638e078e54590fb4c949))
* **deps:** update github/codeql-action digest to a196a71 ([#1133](https://github.com/open-feature/java-sdk/issues/1133)) ([c8722a2](https://github.com/open-feature/java-sdk/commit/c8722a2ac63c4aef7551ec591a1879bb60b9ad26))
* **deps:** update github/codeql-action digest to c4d433c ([#1135](https://github.com/open-feature/java-sdk/issues/1135)) ([26659a3](https://github.com/open-feature/java-sdk/commit/26659a3eed251e6e38ce892ca8f11945ca5add90))
* **deps:** update github/codeql-action digest to cf5b0a9 ([#1130](https://github.com/open-feature/java-sdk/issues/1130)) ([02f4ec1](https://github.com/open-feature/java-sdk/commit/02f4ec1061b82a51995389c5dad9c1abc0d35862))
* **deps:** update github/codeql-action digest to ea2cd92 ([#1160](https://github.com/open-feature/java-sdk/issues/1160)) ([f28cefe](https://github.com/open-feature/java-sdk/commit/f28cefe3b1ea9daffccb87ff55772a2e8f7d0e81))
### 🚀 Performance
* add heap benchmark and reduce allocations ([#1156](https://github.com/open-feature/java-sdk/issues/1156)) ([9008818](https://github.com/open-feature/java-sdk/commit/90088188c90da9fcca4e50328405e56f9ae17dde))
## [1.12.0](https://github.com/open-feature/java-sdk/compare/v1.11.0...v1.12.0) (2024-09-23)
### ✨ New Features
* make provider interface "stateless"; SDK maintains provider state ([#1096](https://github.com/open-feature/java-sdk/issues/1096)) ([1b1e527](https://github.com/open-feature/java-sdk/commit/1b1e527e780128c9aa3c0686427a8fe8856800b4))
### 🧹 Chore
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.4 ([#1113](https://github.com/open-feature/java-sdk/issues/1113)) ([dd8ba81](https://github.com/open-feature/java-sdk/commit/dd8ba81f1286a622aec2611f023d03a56a155e89))
* **deps:** update github/codeql-action digest to 323f5ef ([#1111](https://github.com/open-feature/java-sdk/issues/1111)) ([52e6d2b](https://github.com/open-feature/java-sdk/commit/52e6d2b0ee17124ef2a742fc872a939fde977a27))
## [1.11.0](https://github.com/open-feature/java-sdk/compare/v1.10.0...v1.11.0) (2024-09-20)
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.19.0 ([#1110](https://github.com/open-feature/java-sdk/issues/1110)) ([2412f29](https://github.com/open-feature/java-sdk/commit/2412f296b5db43c07dc807390070379e7781dbb3))
### ✨ New Features
* error resolution flow control without exceptions ([#1095](https://github.com/open-feature/java-sdk/issues/1095)) ([6fc0b90](https://github.com/open-feature/java-sdk/commit/6fc0b9061079e50cbab52c951149cf600a922671))
### 🧹 Chore
* **deps:** update actions/checkout digest to 6d193bf ([#1091](https://github.com/open-feature/java-sdk/issues/1091)) ([9f6a40e](https://github.com/open-feature/java-sdk/commit/9f6a40ec9ba490edf13adc5501a8cb2b93c32447))
* **deps:** update actions/checkout digest to b684943 ([#1088](https://github.com/open-feature/java-sdk/issues/1088)) ([7e0c70f](https://github.com/open-feature/java-sdk/commit/7e0c70f7c547b6eb14f30ba4e77657a317161c1f))
* **deps:** update actions/setup-java digest to 0a40ce6 ([#1107](https://github.com/open-feature/java-sdk/issues/1107)) ([37b56ac](https://github.com/open-feature/java-sdk/commit/37b56ac2dad3c24ac1d898a253e936aa2e3d49eb))
* **deps:** update actions/setup-java digest to 2dfa201 ([#1094](https://github.com/open-feature/java-sdk/issues/1094)) ([082f574](https://github.com/open-feature/java-sdk/commit/082f5746c84f1bb4ff54cae4f525949f29e7b9c4))
* **deps:** update actions/setup-java digest to 40b9536 ([#1109](https://github.com/open-feature/java-sdk/issues/1109)) ([244f216](https://github.com/open-feature/java-sdk/commit/244f216582eae071885a950712115ce8b1ad0c19))
* **deps:** update actions/setup-java digest to 7467385 ([#1092](https://github.com/open-feature/java-sdk/issues/1092)) ([58ead7f](https://github.com/open-feature/java-sdk/commit/58ead7fa9153a53ec530e349f16f9e5e183aa0fb))
* **deps:** update actions/setup-java digest to bcfbca5 ([#1100](https://github.com/open-feature/java-sdk/issues/1100)) ([c68f78e](https://github.com/open-feature/java-sdk/commit/c68f78e17b6125d74644a5735f9d58348edcc383))
* **deps:** update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.6 ([#1103](https://github.com/open-feature/java-sdk/issues/1103)) ([29901b8](https://github.com/open-feature/java-sdk/commit/29901b87ea93757abe5f5d7a8afc6fc4555aef5c))
* **deps:** update github/codeql-action digest to 4a01ec7 ([#1101](https://github.com/open-feature/java-sdk/issues/1101)) ([b80fd6d](https://github.com/open-feature/java-sdk/commit/b80fd6d307dee87d8b8f148c954c33b8ff6efae2))
* **deps:** update github/codeql-action digest to 5618c9f ([#1102](https://github.com/open-feature/java-sdk/issues/1102)) ([d1478c0](https://github.com/open-feature/java-sdk/commit/d1478c001a8e88c358d6743ac3d7c9b5523a893e))
* **deps:** update github/codeql-action digest to 64431c6 ([#1106](https://github.com/open-feature/java-sdk/issues/1106)) ([ce19ac9](https://github.com/open-feature/java-sdk/commit/ce19ac91f62689a0e0e02e53538e1035bf95387f))
* **deps:** update github/codeql-action digest to 782de45 ([#1104](https://github.com/open-feature/java-sdk/issues/1104)) ([7cb8908](https://github.com/open-feature/java-sdk/commit/7cb89087daa2809d3fd8447388e58e4f73c975b3))
* **deps:** update github/codeql-action digest to 799e477 ([#1108](https://github.com/open-feature/java-sdk/issues/1108)) ([17a58ef](https://github.com/open-feature/java-sdk/commit/17a58efc7e0244c0db77e77a78f6d0daf948028f))
* **deps:** update github/codeql-action digest to 8fd294e ([#1097](https://github.com/open-feature/java-sdk/issues/1097)) ([6408261](https://github.com/open-feature/java-sdk/commit/64082617fade3fa7d647302cc0c5b698f7038d81))
* **deps:** update github/codeql-action digest to 9b41ced ([#1089](https://github.com/open-feature/java-sdk/issues/1089)) ([870fc27](https://github.com/open-feature/java-sdk/commit/870fc27ed7a30cb011080127f7d040c1a3bb209b))
* **deps:** update github/codeql-action digest to cb28816 ([#1105](https://github.com/open-feature/java-sdk/issues/1105)) ([9d69ebd](https://github.com/open-feature/java-sdk/commit/9d69ebd94a161e6477f2b4f1f5edd0b79f178852))
* **deps:** update github/codeql-action digest to d8b1697 ([#1093](https://github.com/open-feature/java-sdk/issues/1093)) ([d60593f](https://github.com/open-feature/java-sdk/commit/d60593fa11f39c6587e280633cf6e15965c0960f))
* **deps:** update github/codeql-action digest to e817992 ([#1099](https://github.com/open-feature/java-sdk/issues/1099)) ([caec6e3](https://github.com/open-feature/java-sdk/commit/caec6e35e9da3ad88a8de105ca170137f42b907c))
## [1.10.0](https://github.com/open-feature/java-sdk/compare/v1.9.1...v1.10.0) (2024-09-05)
### ✨ New Features
* add logging hook, rm logging from evaluation ([#1084](https://github.com/open-feature/java-sdk/issues/1084)) ([037826f](https://github.com/open-feature/java-sdk/commit/037826fe1b1c7fecdac95b45bfcdef5d66d49f60))
### 🧹 Chore
* **deps:** update actions/checkout digest to 2d7d9f7 ([#1082](https://github.com/open-feature/java-sdk/issues/1082)) ([9196599](https://github.com/open-feature/java-sdk/commit/9196599f30388dd38b8fb11052772c01f16ed481))
* **deps:** update actions/setup-java digest to 8e04ddf ([#1080](https://github.com/open-feature/java-sdk/issues/1080)) ([0cc5ca1](https://github.com/open-feature/java-sdk/commit/0cc5ca1397d33cd8802cf40d19130d03c84da340))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.3 ([#1087](https://github.com/open-feature/java-sdk/issues/1087)) ([78e3371](https://github.com/open-feature/java-sdk/commit/78e3371c0578984b46d70328a8940425786cae4d))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.0 ([#1063](https://github.com/open-feature/java-sdk/issues/1063)) ([7fea9b1](https://github.com/open-feature/java-sdk/commit/7fea9b106c1cf3ffe4ce7d5a9448a179d7041ed0))
* **deps:** update dependency net.bytebuddy:byte-buddy to v1.15.1 ([#1078](https://github.com/open-feature/java-sdk/issues/1078)) ([9836006](https://github.com/open-feature/java-sdk/commit/98360061a889713fa4b67bd1d0721e5496a18714))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.0 ([#1064](https://github.com/open-feature/java-sdk/issues/1064)) ([dd53021](https://github.com/open-feature/java-sdk/commit/dd53021153a192370a0cbf56fbccd42eeb870043))
* **deps:** update dependency net.bytebuddy:byte-buddy-agent to v1.15.1 ([#1079](https://github.com/open-feature/java-sdk/issues/1079)) ([a3285df](https://github.com/open-feature/java-sdk/commit/a3285df729aaa2c89941bfc180cf736228ab10ef))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.5.0 ([#1073](https://github.com/open-feature/java-sdk/issues/1073)) ([c845035](https://github.com/open-feature/java-sdk/commit/c8450358c02d942f7772ccac6c740078f7594a51))
* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.10.0 ([#1072](https://github.com/open-feature/java-sdk/issues/1072)) ([3eed950](https://github.com/open-feature/java-sdk/commit/3eed950d3c296888acc0abe486d6c34d57170141))
* **deps:** update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.25.0 ([#1074](https://github.com/open-feature/java-sdk/issues/1074)) ([5ee3851](https://github.com/open-feature/java-sdk/commit/5ee38510a87d089f4440657569fb34cc3f133415))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.0 ([#1075](https://github.com/open-feature/java-sdk/issues/1075)) ([b772119](https://github.com/open-feature/java-sdk/commit/b772119977b8731668d809f50cacaa66f83d53b7))
* **deps:** update github/codeql-action digest to 7233ec5 ([#1076](https://github.com/open-feature/java-sdk/issues/1076)) ([eb5526d](https://github.com/open-feature/java-sdk/commit/eb5526d75fb94c9b57b5124982e9b3510d654324))
* **deps:** update github/codeql-action digest to 7e27807 ([#1067](https://github.com/open-feature/java-sdk/issues/1067)) ([a07eb67](https://github.com/open-feature/java-sdk/commit/a07eb6786546066b0e416c9e072db770833d3dbd))
* **deps:** update github/codeql-action digest to 821ab42 ([#1081](https://github.com/open-feature/java-sdk/issues/1081)) ([a4d428c](https://github.com/open-feature/java-sdk/commit/a4d428c83c0d243d85b6bf82ffd15248d3dab570))
* **deps:** update github/codeql-action digest to 864b979 ([#1070](https://github.com/open-feature/java-sdk/issues/1070)) ([ee6d8b0](https://github.com/open-feature/java-sdk/commit/ee6d8b094af3dcf83aa08f934035888bc0311c37))
* **deps:** update github/codeql-action digest to 889597e ([#1086](https://github.com/open-feature/java-sdk/issues/1086)) ([dd7696f](https://github.com/open-feature/java-sdk/commit/dd7696f473a23f789098ca3103b474baa274a233))
* **deps:** update github/codeql-action digest to a895f2e ([#1068](https://github.com/open-feature/java-sdk/issues/1068)) ([ea59e7f](https://github.com/open-feature/java-sdk/commit/ea59e7fa587768832f45a836d4da694a8ebcfde6))
* **deps:** update github/codeql-action digest to b43ac1c ([#1077](https://github.com/open-feature/java-sdk/issues/1077)) ([3f5294c](https://github.com/open-feature/java-sdk/commit/3f5294c734278d6ce13bbfae9731c0b46e3e9e15))
* **deps:** update github/codeql-action digest to b4a8631 ([#1083](https://github.com/open-feature/java-sdk/issues/1083)) ([90648d1](https://github.com/open-feature/java-sdk/commit/90648d1c9d9adffa85442b39bd0197ac7e032a51))
* **deps:** update github/codeql-action digest to b8efe4d ([#1071](https://github.com/open-feature/java-sdk/issues/1071)) ([5668987](https://github.com/open-feature/java-sdk/commit/5668987274952693cad77bc37fa054ee1ed603fe))
* **deps:** update github/codeql-action digest to d36c7aa ([#1069](https://github.com/open-feature/java-sdk/issues/1069)) ([0e048c1](https://github.com/open-feature/java-sdk/commit/0e048c1ff5eae3ec121c2219e8ce9685264135bb))
* various non-functional refactors ([#1066](https://github.com/open-feature/java-sdk/issues/1066)) ([35d4cc2](https://github.com/open-feature/java-sdk/commit/35d4cc23c85a24f2d55992cb40b357e450f8e9b7))
## [1.9.1](https://github.com/open-feature/java-sdk/compare/v1.9.0...v1.9.1) (2024-08-22)
### 🐛 Bug Fixes
* **deps:** update dependency io.cucumber:cucumber-bom to v7.18.1 ([#1011](https://github.com/open-feature/java-sdk/issues/1011)) ([91fa8cf](https://github.com/open-feature/java-sdk/commit/91fa8cf7d63374cd67d4c02d291467da379297cf))
* **deps:** update dependency org.slf4j:slf4j-api to v2.0.14 ([#1033](https://github.com/open-feature/java-sdk/issues/1033)) ([4ec155d](https://github.com/open-feature/java-sdk/commit/4ec155d91b4cc637d1d447ea87308401a5fd7d87))
* **deps:** update dependency org.slf4j:slf4j-api to v2.0.15 ([#1036](https://github.com/open-feature/java-sdk/issues/1036)) ([fed9394](https://github.com/open-feature/java-sdk/commit/fed93942b88e0042c50801e8fa193cd156487d4c))
* **deps:** update dependency org.slf4j:slf4j-api to v2.0.16 ([#1039](https://github.com/open-feature/java-sdk/issues/1039)) ([beba1bd](https://github.com/open-feature/java-sdk/commit/beba1bd8d6c6d7f0d7d7c947777ad9e5ee0e4649))
* **deps:** update junit5 monorepo ([#1045](https://github.com/open-feature/java-sdk/issues/1045)) ([5e77f8a](https://github.com/open-feature/java-sdk/commit/5e77f8ad337fa3230a71db7d722cce01a50f654b))
* Pin byte-buddy(-agent) version to 1.14.19 to workaround Mockito issue ([#1060](https://github.com/open-feature/java-sdk/issues/1060)) ([32340a3](https://github.com/open-feature/java-sdk/commit/32340a3e0e11ce49c4405658f40568b04926264e))
* updated context not passed to all hooks ([#1049](https://github.com/open-feature/java-sdk/issues/1049)) ([dbf967a](https://github.com/open-feature/java-sdk/commit/dbf967a860d38f4b76bb6d47b6507e87669fa59a))
* Use ConcurrentHashMap for InMemoryProvider ([#1057](https://github.com/open-feature/java-sdk/issues/1057)) ([b7ed041](https://github.com/open-feature/java-sdk/commit/b7ed041eed19a7a872c2c73f18163f616ec146c2))
### 🧹 Chore
* **deps:** update actions/cache digest to 40c3b67 ([#1026](https://github.com/open-feature/java-sdk/issues/1026)) ([41128b8](https://github.com/open-feature/java-sdk/commit/41128b86fb55d060aed7af836ef9f2365d033446))
* **deps:** update actions/cache digest to 4a28cbc ([#1022](https://github.com/open-feature/java-sdk/issues/1022)) ([865c3bb](https://github.com/open-feature/java-sdk/commit/865c3bb17a2fb5a8ab5832cf32b806b8b4a5660e))
* **deps:** update actions/cache digest to 57b8e40 ([#1030](https://github.com/open-feature/java-sdk/issues/1030)) ([6990e21](https://github.com/open-feature/java-sdk/commit/6990e21b47befdb4c9b2431c63ddb6db6ccecff7))
* **deps:** update actions/cache digest to 81382a7 ([#1044](https://github.com/open-feature/java-sdk/issues/1044)) ([d746dc0](https://github.com/open-feature/java-sdk/commit/d746dc0a11cd837fe9a1472b3cc2ef47fcb616a8))
* **deps:** update actions/checkout digest to 9a9194f ([#1023](https://github.com/open-feature/java-sdk/issues/1023)) ([326a10b](https://github.com/open-feature/java-sdk/commit/326a10ba0160627387fff20c52c50250bb176a3a))
* **deps:** update actions/setup-java digest to 67fbd72 ([#1037](https://github.com/open-feature/java-sdk/issues/1037)) ([b4f0550](https://github.com/open-feature/java-sdk/commit/b4f0550a2b9530dc23603f7e5aedf19a1ce0b08a))
* **deps:** update actions/setup-java digest to 6a0805f ([#1027](https://github.com/open-feature/java-sdk/issues/1027)) ([0968674](https://github.com/open-feature/java-sdk/commit/09686741ad174f3467e7d8b8adfeef13f0afbcbf))
* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.8.6.2 ([#999](https://github.com/open-feature/java-sdk/issues/999)) ([d0b3b35](https://github.com/open-feature/java-sdk/commit/d0b3b3598115e55cda334a6c7ced72b6ae28a063))
* **deps:** update dependency com.google.guava:guava to v33.3.0-jre ([#1050](https://github.com/open-feature/java-sdk/issues/1050)) ([a36d2ab](https://github.com/open-feature/java-sdk/commit/a36d2ab111b3f8e0f88291ea7baec83d082d233c))
* **deps:** update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.5.0 ([#1062](https://github.com/open-feature/java-sdk/issues/1062)) ([8370d42](https://github.com/open-feature/java-sdk/commit/8370d4209de8181bc5d3253b874f296089c110f6))
* **deps:** update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.8.0 ([#1061](https://github.com/open-feature/java-sdk/issues/1061)) ([a81957f](https://github.com/open-feature/java-sdk/commit/a81957ff560c46c5dfb5e38b2f374878e7f5df31))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.3.1 ([#1004](https://github.com/open-feature/java-sdk/issues/1004)) ([7ae703e](https://github.com/open-feature/java-sdk/commit/7ae703e1da581d036c0f970b6712c2fb611bb805))
* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.4.0 ([#1051](https://github.com/open-feature/java-sdk/issues/1051)) ([a1ceb1f](https://github.com/open-feature/java-sdk/commit/a1ceb1fbbfb428c6ea05b68a303640d6dd895713))
* **deps:** update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.2.5 ([#1040](https://github.com/open-feature/java-sdk/issues/1040)) ([b215dec](https://github.com/open-feature/java-sdk/commit/b215dec8b8ea7f87b515404fc14c740370cc67d0))
* **deps:** update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.8.0 ([#1013](https://github.com/open-feature/java-sdk/issues/1013)) ([3d0cd62](https://github.com/open-feature/java-sdk/commit/3d0cd62c9838ef4bd354cb84bcf43518589ae3a7))
* **deps:** update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.24.0 ([#1009](https://github.com/open-feature/java-sdk/issues/1009)) ([efbb69a](https://github.com/open-feature/java-sdk/commit/efbb69a998f20e559b1b610cc190bdbd19ea8100))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.3.1 ([#1005](https://github.com/open-feature/java-sdk/issues/1005)) ([e8568a8](https://github.com/open-feature/java-sdk/commit/e8568a8ea2c130be581a310be2214900eddf9d8f))
* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.4.0 ([#1052](https://github.com/open-feature/java-sdk/issues/1052)) ([13dd70f](https://github.com/open-feature/java-sdk/commit/13dd70f8472be2d0648f4880480c38f4aa51ec04))
* **deps:** update dependency org.assertj:assertj-core to v3.26.3 ([#1002](https://github.com/open-feature/java-sdk/issues/1002)) ([2f5deb1](https://github.com/open-feature/java-sdk/commit/2f5deb1a3a578357bb8b965bc7ad0e61f5a8a782))
* **deps:** update dependency org.awaitility:awaitility to v4.2.2 ([#1035](https://github.com/open-feature/java-sdk/issues/1035)) ([4591d3f](https://github.com/open-feature/java-sdk/commit/4591d3f1da330ba3631618b96576f48def6f59e0))
* **deps:** update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.0 ([#1034](https://github.com/open-feature/java-sdk/issues/1034)) ([ccabb18](https://github.com/open-feature/java-sdk/commit/ccabb1856cd697d54a227d3562278d03088b3aeb))
* **deps:** update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.1 ([#1042](https://github.com/open-feature/java-sdk/issues/1042)) ([37121e9](https://github.com/open-feature/java-sdk/commit/37121e9939338e83102fa004731efc209a8d32c4))
* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.8.1 ([#1029](https://github.com/open-feature/java-sdk/issues/1029)) ([89cb747](https://github.com/open-feature/java-sdk/commit/89cb7479f48b9f930b70e992aa94acd1ad9346a9))
* **deps:** update github/codeql-action digest to 064a406 ([#1000](https://github.com/open-feature/java-sdk/issues/1000)) ([42d2d77](https://github.com/open-feature/java-sdk/commit/42d2d776a8e475bb2247d616cfc07bac896cf089))
* **deps:** update github/codeql-action digest to 0d5982a ([#1043](https://github.com/open-feature/java-sdk/issues/1043)) ([f1ea405](https://github.com/open-feature/java-sdk/commit/f1ea4057fc9bccd4e32ac042060f967f934b0090))
* **deps:** update github/codeql-action digest to 0e346f2 ([#1014](https://github.com/open-feature/java-sdk/issues/1014)) ([f1b0eb1](https://github.com/open-feature/java-sdk/commit/f1b0eb154dcbd1a02158b457a1bf848eb3040925))
* **deps:** update github/codeql-action digest to 16639b4 ([#1024](https://github.com/open-feature/java-sdk/issues/1024)) ([d23a911](https://github.com/open-feature/java-sdk/commit/d23a9115c8f2fa43d05dde37b2aac88c872b0b8c))
* **deps:** update github/codeql-action digest to 1b214db ([#1018](https://github.com/open-feature/java-sdk/issues/1018)) ([aa7f8b9](https://github.com/open-feature/java-sdk/commit/aa7f8b97f0464d36d3a87574915fe95901b612c5))
* **deps:** update github/codeql-action digest to 202b3b9 ([#1056](https://github.com/open-feature/java-sdk/issues/1056)) ([61d821a](https://github.com/open-feature/java-sdk/commit/61d821ae8a2f64dbc20aa97002e973a423e3ccf7))
* **deps:** update github/codeql-action digest to 25ad3c8 ([#1038](https://github.com/open-feature/java-sdk/issues/1038)) ([75b9acd](https://github.com/open-feature/java-sdk/commit/75b9acd79110bba199b84d262a7bf820fc515153))
* **deps:** update github/codeql-action digest to 270a29d ([#1010](https://github.com/open-feature/java-sdk/issues/1010)) ([1d31726](https://github.com/open-feature/java-sdk/commit/1d31726e574ae09aeccb0365f6797e78187eb6ce))
* **deps:** update github/codeql-action digest to 339aada ([#1053](https://github.com/open-feature/java-sdk/issues/1053)) ([aed4ea2](https://github.com/open-feature/java-sdk/commit/aed4ea21d6735c1aa4d2b16c2ec1d95b2de57672))
* **deps:** update github/codeql-action digest to 44534b7 ([#1012](https://github.com/open-feature/java-sdk/issues/1012)) ([eca299b](https://github.com/open-feature/java-sdk/commit/eca299b3ad05dc198a91b29cac27c5df6a94eb3e))
* **deps:** update github/codeql-action digest to 4b1d7da ([#1020](https://github.com/open-feature/java-sdk/issues/1020)) ([7db6d8a](https://github.com/open-feature/java-sdk/commit/7db6d8a3d3fb1dc17cb85740f0666601252a3c6e))
* **deps:** update github/codeql-action digest to 512e306 ([#1055](https://github.com/open-feature/java-sdk/issues/1055)) ([7cac198](https://github.com/open-feature/java-sdk/commit/7cac1984f84e2aea631e98cb605c768123c870be))
* **deps:** update github/codeql-action digest to 5c02493 ([#1032](https://github.com/open-feature/java-sdk/issues/1032)) ([1ed7fc1](https://github.com/open-feature/java-sdk/commit/1ed7fc15774af26b7c73238dc35b39a7c20ef129))
* **deps:** update github/codeql-action digest to 5c681ef ([#1048](https://github.com/open-feature/java-sdk/issues/1048)) ([00bc060](https://github.com/open-feature/java-sdk/commit/00bc0609eb270e15129a3ebadb8671e61603b865))
* **deps:** update github/codeql-action digest to 5cdd182 ([#1025](https://github.com/open-feature/java-sdk/issues/1025)) ([c574ec5](https://github.com/open-feature/java-sdk/commit/c574ec5c777017b2cdae770fbf35def4b6be1b55))
* **deps:** update github/codeql-action digest to 6e04d51 ([#1001](https://github.com/open-feature/java-sdk/issues/1001)) ([145dfc7](https://github.com/open-feature/java-sdk/commit/145dfc70c276c0e9d3fe28f582ad5385a84ec0f6))
* **deps:** update github/codeql-action digest to 79e9a50 ([#995](https://github.com/open-feature/java-sdk/issues/995)) ([e2c70d9](https://github.com/open-feature/java-sdk/commit/e2c70d9f0b4768ccbe9796cb14e99a92e5ba3dbc))
* **deps:** update github/codeql-action digest to 7adf9ac ([#998](https://github.com/open-feature/java-sdk/issues/998)) ([62f95b6](https://github.com/open-feature/java-sdk/commit/62f95b651bb7bc18f984e42264900f2b486bf6bb))
* **deps:** update github/codeql-action digest to 857f661 ([#1007](https://github.com/open-feature/java-sdk/issues/1007)) ([aab84b8](https://github.com/open-feature/java-sdk/commit/aab84b80af81a280d5729455048202090de7f7da))
* **deps:** update github/codeql-action digest to 9ab7277 ([#1006](https://github.com/open-feature/java-sdk/issues/1006)) ([2bb58d6](https://github.com/open-feature/java-sdk/commit/2bb58d6e1b160848e7cb92394ae9f1b98f091b34))
* **deps:** update github/codeql-action digest to 9c646c2 ([#1028](https://github.com/open-feature/java-sdk/issues/1028)) ([cd4c823](https://github.com/open-feature/java-sdk/commit/cd4c8239cd8c70dd8cdbc5398bfcb74668a65499))
* **deps:** update github/codeql-action digest to a93f8c2 ([#1046](https://github.com/open-feature/java-sdk/issues/1046)) ([2934195](https://github.com/open-feature/java-sdk/commit/2934195a8f81b66c5b1ae45f0d7ec2252f830c24))
* **deps:** update github/codeql-action digest to aa96d09 ([#1021](https://github.com/open-feature/java-sdk/issues/1021)) ([e57eafd](https://github.com/open-feature/java-sdk/commit/e57eafd86d9e333d70d027a64d7b83d4f2ce4f9f))
* **deps:** update github/codeql-action digest to b400d0f ([#1016](https://github.com/open-feature/java-sdk/issues/1016)) ([5db43ad](https://github.com/open-feature/java-sdk/commit/5db43ad1aae4581d92f18eb8b209c701af55b1a5))
* **deps:** update github/codeql-action digest to be825d5 ([#1003](https://github.com/open-feature/java-sdk/issues/1003)) ([f3d9a55](https://github.com/open-feature/java-sdk/commit/f3d9a55eb7c3955bc3dbf2c9db5f494749e2c890))
* **deps:** update github/codeql-action digest to c24926b ([#1031](https://github.com/open-feature/java-sdk/issues/1031)) ([22435a6](https://github.com/open-feature/java-sdk/commit/22435a694a98022998d1b75a0cbee59caceccf15))
* **deps:** update github/codeql-action digest to c2585ec ([#1008](https://github.com/open-feature/java-sdk/issues/1008)) ([9cc9241](https://github.com/open-feature/java-sdk/commit/9cc9241b014edb8ac25aa830ab250009d4bc506a))
* **deps:** update github/codeql-action digest to d620faa ([#1041](https://github.com/open-feature/java-sdk/issues/1041)) ([69db287](https://github.com/open-feature/java-sdk/commit/69db2870071bfc5b307a0b5f6df27dc7f77daa26))
* **deps:** update github/codeql-action digest to ee4ad8b ([#997](https://github.com/open-feature/java-sdk/issues/997)) ([fc40209](https://github.com/open-feature/java-sdk/commit/fc40209edcffc063a474aec7bfe9a880e0966750))
* **deps:** update github/codeql-action digest to f67c9cd ([#1017](https://github.com/open-feature/java-sdk/issues/1017)) ([baa1331](https://github.com/open-feature/java-sdk/commit/baa13313e8cc10ab4f9f6dc6a216326dfcdc74b2))
* **deps:** update github/codeql-action digest to f8e94f9 ([#1019](https://github.com/open-feature/java-sdk/issues/1019)) ([cf760e4](https://github.com/open-feature/java-sdk/commit/cf760e4cc4227b7bac4c4ce5192d06ed39a7783b))
* **deps:** update github/codeql-action digest to fd5fa13 ([#1058](https://github.com/open-feature/java-sdk/issues/1058)) ([b0f915b](https://github.com/open-feature/java-sdk/commit/b0f915bb09d294e8b399941974b546cbd3bff187))
### 📚 Documentation
* Small typo sonartype vs sonatype ([#989](https://github.com/open-feature/java-sdk/issues/989)) ([7bff3ee](https://github.com/open-feature/java-sdk/commit/7bff3eebe624c9fecd705dd5fdd51d9483cb4643))
## [1.9.0](https://github.com/open-feature/java-sdk/compare/v1.8.0...v1.9.0) (2024-06-28)

View File

@ -3,4 +3,4 @@
#
# Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-java/workgroup.yaml
#
* @open-feature/sdk-java-maintainers
* @open-feature/sdk-java-maintainers @open-feature/maintainers

View File

@ -12,21 +12,69 @@ Any contributions you make are expected to be tested with unit tests. You can va
Further, it is recommended to verify code styling and static code analysis with `mvn verify -P !deploy`.
Regardless, the automation itself will run them for you when you open a PR.
> [!TIP]
> For easier usage maven wrapper is available. Example usage: `./mvnw verify`
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.
## Code Styles
### Overview
Our project follows strict code formatting standards to maintain consistency and readability across the codebase. We use [Spotless](https://github.com/diffplug/spotless) integrated with the [Palantir Java Format](https://github.com/palantir/palantir-java-format) for code formatting.
**Spotless** ensures that all code complies with the formatting rules automatically, reducing style-related issues during code reviews.
### How to Format Your Code
1. **Before Committing Changes:**
Run the Spotless plugin to format your code. This will apply the Palantir Java Format style:
```bash
mvn spotless:apply
```
2. **Verify Formatting:**
To check if your code adheres to the style guidelines without making changes:
```bash
mvn spotless:check
```
- If this command fails, your code does not follow the required formatting. Use `mvn spotless:apply` to fix it.
### CI/CD Integration
Our Continuous Integration (CI) pipeline automatically checks code formatting using the Spotless plugin. Any code that does not pass the `spotless:check` step will cause the build to fail.
### Best Practices
- Regularly run `mvn spotless:apply` during your work to ensure your code remains aligned with the standards.
- Configure your IDE (e.g., IntelliJ IDEA or Eclipse) to follow the Palantir Java format guidelines to reduce discrepancies during development.
### Support
If you encounter issues with code formatting, please raise a GitHub issue or contact the maintainers.
## 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/spec/blob/main/specification/assets/gherkin/evaluation.feature) using `InMemoryProvider`.
to run alone:
```
mvn test -P e2e
```
## Benchmarking
There is a small JMH benchmark suite for testing allocations that can be run with:
```sh
mvn -P benchmark clean compile test-compile jmh:benchmark -Djmh.f=1 -Djmh.prof='dev.openfeature.sdk.benchmark.AllocationProfiler'
```
If you are concerned about the repercussions of a change on memory usage, run this an compare the results to the committed. `benchmark.txt` file.
Note that the ONLY MEANINGFUL RESULTS of this benchmark are the `totalAllocatedBytes` and the `totalAllocatedInstances`.
The `run` score, and maven task time are not relevant since this benchmark is purely memory-related and has nothing to do with speed.
You can also view the heap breakdown to see which objects are taking up the most memory.
## Releasing
See [releasing](./docs/release.md).

View File

@ -18,8 +18,8 @@
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/java-sdk/releases/tag/v1.9.0">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.9.0&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/java-sdk/releases/tag/v1.16.0">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.16.0&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
@ -46,7 +46,7 @@
### Requirements
- Java 8+ (compiler target is 1.8)
- Java 11+ (compiler target is 11)
Note that this library is intended to be used in server-side contexts and has not been evaluated for use on mobile devices.
@ -59,7 +59,7 @@ Note that this library is intended to be used in server-side contexts and has no
<dependency>
<groupId>dev.openfeature</groupId>
<artifactId>sdk</artifactId>
<version>1.9.0</version>
<version>1.16.0</version>
</dependency>
```
<!-- x-release-please-end-version -->
@ -72,8 +72,8 @@ If you would like snapshot builds, this is the relevant repository information:
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonartype</id>
<name>Sonartype Repository</name>
<id>sonatype</id>
<name>Sonatype Repository</name>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
@ -84,7 +84,7 @@ If you would like snapshot builds, this is the relevant repository information:
<!-- x-release-please-start-version -->
```groovy
dependencies {
implementation 'dev.openfeature:sdk:1.9.0'
implementation 'dev.openfeature:sdk:1.16.0'
}
```
<!-- x-release-please-end-version -->
@ -104,7 +104,12 @@ public void example(){
// configure a provider
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(new InMemoryProvider(myFlags));
try {
api.setProviderAndWait(new InMemoryProvider(myFlags));
} catch (Exception e) {
// handle initialization failure
e.printStackTrace();
}
// create a client
Client client = api.getClient();
@ -120,17 +125,18 @@ 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. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread). |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
| 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. |
| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations. |
| ✅ | [Logging](#logging) | Integrate with popular logging packages. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread). |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
<sub>Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌</sub>
@ -148,7 +154,12 @@ To register a provider in a blocking manner to ensure it is ready before further
```java
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(new MyProvider());
try {
api.setProviderAndWait(new MyProvider());
} catch (Exception e) {
// handle initialization failure
e.printStackTrace();
}
```
#### Asynchronous
@ -215,9 +226,27 @@ Once you've added a hook as a dependency, it can be registered at the global, cl
FlagEvaluationOptions.builder().hook(new ExampleHook()).build());
```
### Tracking
The [tracking API](https://openfeature.dev/specification/sections/tracking/) allows you to use OpenFeature abstractions to associate user actions with feature flag evaluations.
This is essential for robust experimentation powered by feature flags. Note that, unlike methods that handle feature flag evaluations, calling `track(...)` may throw an `IllegalArgumentException` if an empty string is passed as the `trackingEventName`.
```java
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.getClient().track("visited-promo-page", new MutableTrackingEventDetails(99.77).add("currency", "USD"));
```
### Logging
The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation.
Note that in accordance with the OpenFeature specification, the SDK doesn't generally log messages during flag evaluation.
#### Logging Hook
The Java SDK includes a `LoggingHook`, which logs detailed information at key points during flag evaluation, using SLF4J's structured logging API.
This hook can be particularly helpful for troubleshooting and debugging; simply attach it at the global, client or invocation level and ensure your log level is set to "debug".
See [hooks](#hooks) for more information on configuring hooks.
### Domains
@ -309,11 +338,6 @@ public class MyProvider implements FeatureProvider {
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
@ -360,11 +384,6 @@ class MyEventProvider extends EventProvider {
return () -> "My Event Provider";
}
@Override
public ProviderState getState() {
// indicate your provider's state (required for EventProviders)
}
@Override
public void initialize(EvaluationContext evaluationContext) throws Exception {
// emit events when flags are changed in a hypothetical REST API
@ -383,6 +402,13 @@ class MyEventProvider extends EventProvider {
}
```
Providers no longer need to manage their own state, this is done by the SDK itself. If desired, the state of a provider
can be queried through the client that uses the provider.
```java
OpenFeatureAPI.getInstance().getClient().getProviderState();
```
> 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
@ -410,7 +436,7 @@ class MyHook implements Hook {
}
@Override
public void finallyAfter(HookContext ctx, Map hints) {
public void finallyAfter(HookContext ctx, FlagEvaluationDetails details, Map hints) {
// code that runs regardless of success or error
}
};

294
benchmark.txt Normal file
View File

@ -0,0 +1,294 @@
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< dev.openfeature:sdk >-------------------------
[INFO] Building OpenFeature Java SDK 1.12.1
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ sdk ---
[INFO] Deleting /home/todd/git/java-sdk/target
[INFO]
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
[INFO] Starting audit...
Audit done.
[INFO] You have 0 Checkstyle violations.
[INFO]
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
[INFO] surefireArgLine set to -javaagent:/home/todd/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/home/todd/git/java-sdk/target/coverage-reports/jacoco-ut.exec
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 65 source files with javac [debug target 1.8] to target/classes
[WARNING] bootstrap class path not set in conjunction with -source 8
[WARNING] source value 8 is obsolete and will be removed in a future release
[WARNING] target value 8 is obsolete and will be removed in a future release
[WARNING] To suppress warnings about obsolete options, use -Xlint:-options.
[INFO] Annotation processing is enabled because one or more processors were found
on the class path. A future release of javac may disable annotation processing
unless at least one processor is specified by name (-processor), or a search
path is specified (--processor-path, --processor-module-path), or annotation
processing is enabled explicitly (-proc:only, -proc:full).
Use -Xlint:-options to suppress this message.
Use -proc:none to disable annotation processing.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/MutableStructure.java:[19,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/ImmutableStructure.java:[22,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/EventDetails.java:[9,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java:[27,26] finalize() in java.lang.Object has been deprecated and marked for removal
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/NoOpProvider.java: Some input files use or override a deprecated API.
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/NoOpProvider.java: Recompile with -Xlint:deprecation for details.
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java: Some input files use unchecked or unsafe operations.
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java: Recompile with -Xlint:unchecked for details.
[INFO]
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
[INFO] Starting audit...
Audit done.
[INFO] You have 0 Checkstyle violations.
[INFO]
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
[INFO] surefireArgLine set to -javaagent:/home/todd/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/home/todd/git/java-sdk/target/coverage-reports/jacoco-ut.exec
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ sdk ---
[INFO] Copying 2 resources from src/test/resources to target/test-classes
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ sdk ---
[INFO] Recompiling the module because of changed dependency.
[INFO] Compiling 52 source files with javac [debug target 1.8] to target/test-classes
[WARNING] bootstrap class path not set in conjunction with -source 8
[WARNING] source value 8 is obsolete and will be removed in a future release
[WARNING] target value 8 is obsolete and will be removed in a future release
[WARNING] To suppress warnings about obsolete options, use -Xlint:-options.
[INFO] Annotation processing is enabled because one or more processors were found
on the class path. A future release of javac may disable annotation processing
unless at least one processor is specified by name (-processor), or a search
path is specified (--processor-path, --processor-module-path), or annotation
processing is enabled explicitly (-proc:only, -proc:full).
Use -Xlint:-options to suppress this message.
Use -proc:none to disable annotation processing.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/EventsTest.java: Some input files use or override a deprecated API.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/EventsTest.java: Recompile with -Xlint:deprecation for details.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/HookSpecTest.java: Some input files use unchecked or unsafe operations.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/HookSpecTest.java: Recompile with -Xlint:unchecked for details.
[INFO]
[INFO] >>> jmh:0.2.2:benchmark (default-cli) > process-test-resources @ sdk >>>
[INFO]
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
[INFO] Starting audit...
Audit done.
[INFO] You have 0 Checkstyle violations.
[INFO]
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
[INFO] surefireArgLine set to -javaagent:/home/todd/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar=destfile=/home/todd/git/java-sdk/target/coverage-reports/jacoco-ut.exec
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ sdk ---
[INFO] Copying 2 resources from src/test/resources to target/test-classes
[INFO]
[INFO] <<< jmh:0.2.2:benchmark (default-cli) < process-test-resources @ sdk <<<
[INFO]
[INFO]
[INFO] --- jmh:0.2.2:benchmark (default-cli) @ sdk ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 52 source files to /home/todd/git/java-sdk/target/test-classes
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/LockingTest.java: Some input files use or override a deprecated API.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/LockingTest.java: Recompile with -Xlint:deprecation for details.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java: Some input files use unchecked or unsafe operations.
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java: Recompile with -Xlint:unchecked for details.
[INFO] Executing the JMH benchmarks
# JMH version: 1.37
# VM version: JDK 21.0.4, OpenJDK 64-Bit Server VM, 21.0.4+7
# VM invoker: /usr/lib/jvm/java-21-openjdk/bin/java
# VM options: -Xmx1024m -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: <none>
# Measurement: 1 iterations, single-shot each
# Timeout: 10 min per iteration
# Threads: 1 thread
# Benchmark mode: Single shot invocation time
# Benchmark: dev.openfeature.sdk.benchmark.AllocationBenchmark.run
# Run progress: 0.00% complete, ETA 00:00:00
# Fork: 1 of 1
[0.001s][warning][gc,init] Consider setting -Xms equal to -Xmx to avoid resizing hiccups
[0.001s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups
Iteration 1: num #instances #bytes class name (module)
-------------------------------------------------------
1: 480234 23051232 java.util.HashMap (java.base@21.0.4)
2: 150497 12050088 [Ljava.util.HashMap$Node; (java.base@21.0.4)
3: 332017 10624544 java.util.HashMap$Node (java.base@21.0.4)
4: 47815 9732480 [B (java.base@21.0.4)
5: 305991 8105872 [Ljava.lang.Object; (java.base@21.0.4)
6: 366682 5866912 java.util.Optional (java.base@21.0.4)
7: 183332 5866624 java.util.HashMap$EntryIterator (java.base@21.0.4)
8: 172970 5535040 java.util.Collections$UnmodifiableMap (java.base@21.0.4)
9: 100000 4000000 dev.openfeature.sdk.HookContext
10: 100000 4000000 dev.openfeature.sdk.HookContext$HookContextBuilder
11: 230006 3680096 dev.openfeature.sdk.Value
12: 200062 3200992 java.util.HashMap$EntrySet (java.base@21.0.4)
13: 132870 3188880 java.util.ArrayList (java.base@21.0.4)
14: 192292 3076672 dev.openfeature.sdk.ImmutableStructure
15: 182292 2916672 dev.openfeature.sdk.ImmutableContext
16: 50000 2000000 dev.openfeature.sdk.FlagEvaluationDetails
17: 50000 2000000 dev.openfeature.sdk.ProviderEvaluation
18: 122968 1967488 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet (java.base@21.0.4)
19: 149 1884376 [Ljdk.internal.vm.FillerElement; (java.base@21.0.4)
20: 56476 1807232 java.util.ArrayList$Itr (java.base@21.0.4)
21: 37481 1799088 dev.openfeature.sdk.FlagEvaluationDetails$FlagEvaluationDetailsBuilder
22: 100001 1600016 dev.openfeature.sdk.NoOpProvider$$Lambda/0x000076e79c02fa78
23: 50000 1600000 [Ldev.openfeature.sdk.EvaluationContext;
24: 50000 1600000 [Ljava.util.List; (java.base@21.0.4)
25: 100000 1600000 dev.openfeature.sdk.OpenFeatureClient$$Lambda/0x000076e79c082800
26: 36720 1468800 dev.openfeature.sdk.ProviderEvaluation$ProviderEvaluationBuilder
27: 87481 1399696 dev.openfeature.sdk.ImmutableMetadata
28: 50000 1200000 dev.openfeature.sdk.FlagEvaluationOptions
29: 74201 1187216 dev.openfeature.sdk.ImmutableMetadata$ImmutableMetadataBuilder
30: 73235 1171760 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry (java.base@21.0.4)
31: 45869 1100856 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1 (java.base@21.0.4)
32: 43776 1050624 dev.openfeature.sdk.FlagEvaluationOptions$FlagEvaluationOptionsBuilder
33: 40016 960384 dev.openfeature.sdk.HookSupport$$Lambda/0x000076e79c081b78
34: 39967 959208 dev.openfeature.sdk.HookSupport$$Lambda/0x000076e79c081da8
35: 57783 924528 dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock$$Lambda/0x000076e79c02eae8
36: 4490 721440 [I (java.base@21.0.4)
37: 26594 638256 java.lang.String (java.base@21.0.4)
38: 1461 390008 [J (java.base@21.0.4)
39: 2361 288784 java.lang.Class (java.base@21.0.4)
40: 4632 259392 jdk.internal.org.objectweb.asm.SymbolTable$Entry (java.base@21.0.4)
41: 10001 240024 java.lang.Double (java.base@21.0.4)
42: 2502 180144 java.lang.reflect.Field (java.base@21.0.4)
43: 6007 144168 java.lang.StringBuilder (java.base@21.0.4)
44: 180 140968 [Ljdk.internal.org.objectweb.asm.SymbolTable$Entry; (java.base@21.0.4)
45: 3827 122464 java.util.concurrent.ConcurrentHashMap$Node (java.base@21.0.4)
46: 48 122168 [C (java.base@21.0.4)
47: 1440 113512 [S (java.base@21.0.4)
48: 1201 105688 java.lang.reflect.Method (java.base@21.0.4)
49: 3031 79600 [Ljava.lang.Class; (java.base@21.0.4)
50: 1351 75656 jdk.internal.org.objectweb.asm.Label (java.base@21.0.4)
51: 1561 74928 java.lang.invoke.MemberName (java.base@21.0.4)
52: 334 74816 jdk.internal.org.objectweb.asm.MethodWriter (java.base@21.0.4)
53: 1799 71960 java.lang.invoke.MethodType (java.base@21.0.4)
54: 1089 69696 java.net.URL (java.base@21.0.4)
55: 121 50512 [Ljava.util.concurrent.ConcurrentHashMap$Node; (java.base@21.0.4)
56: 3147 50352 jdk.internal.util.StrongReferenceKey (java.base@21.0.4)
57: 1057 42280 java.io.ObjectStreamField (java.base@21.0.4)
58: 1225 39200 java.io.File (java.base@21.0.4)
59: 779 37392 jdk.internal.org.objectweb.asm.Frame (java.base@21.0.4)
60: 243 25272 java.util.jar.JarFile$JarFileEntry (java.base@21.0.4)
61: 794 25248 [Ljava.lang.String; (java.base@21.0.4)
62: 622 24880 java.lang.NoSuchFieldException (java.base@21.0.4)
63: 571 22840 java.util.LinkedHashMap$Entry (java.base@21.0.4)
64: 474 22752 jdk.internal.ref.CleanerImpl$PhantomCleanableRef (java.base@21.0.4)
65: 690 22080 jdk.internal.util.WeakReferenceKey (java.base@21.0.4)
66: 828 19872 jdk.internal.org.objectweb.asm.ByteVector (java.base@21.0.4)
67: 248 18848 [Ljava.lang.ref.SoftReference; (java.base@21.0.4)
68: 118 17936 jdk.internal.org.objectweb.asm.ClassWriter (java.base@21.0.4)
69: 380 16824 [Ljava.lang.invoke.LambdaForm$Name; (java.base@21.0.4)
70: 625 15000 java.lang.Long (java.base@21.0.4)
71: 463 14816 java.lang.invoke.LambdaForm$Name (java.base@21.0.4)
72: 904 14464 java.lang.Object (java.base@21.0.4)
73: 198 14256 java.lang.reflect.Constructor (java.base@21.0.4)
74: 249 13944 java.util.zip.ZipFile$ZipFileInputStream (java.base@21.0.4)
75: 334 13360 jdk.internal.org.objectweb.asm.Handler (java.base@21.0.4)
76: 202 12928 java.util.concurrent.ConcurrentHashMap (java.base@21.0.4)
77: 201 12864 jdk.internal.org.objectweb.asm.FieldWriter (java.base@21.0.4)
78: 316 12640 java.util.WeakHashMap$Entry (java.base@21.0.4)
79: 102 12240 java.io.ObjectStreamClass (java.base@21.0.4)
80: 249 11952 java.util.zip.ZipFile$ZipFileInflaterInputStream (java.base@21.0.4)
81: 359 11488 jdk.internal.org.objectweb.asm.Type (java.base@21.0.4)
82: 465 11160 java.lang.invoke.ResolvedMethodName (java.base@21.0.4)
83: 464 11136 jdk.internal.org.objectweb.asm.Edge (java.base@21.0.4)
84: 341 10912 jdk.internal.math.FDBigInteger (java.base@21.0.4)
85: 94 10728 [Ljava.lang.reflect.Field; (java.base@21.0.4)
86: 266 10640 java.lang.NoSuchMethodException (java.base@21.0.4)
87: 266 10640 java.security.CodeSource (java.base@21.0.4)
88: 221 10608 java.lang.invoke.DirectMethodHandle$Constructor (java.base@21.0.4)
89: 264 10560 sun.security.util.KnownOIDs (java.base@21.0.4)
90: 75 10200 sun.nio.fs.UnixFileAttributes (java.base@21.0.4)
91: 245 9800 java.lang.ref.SoftReference (java.base@21.0.4)
92: 118 9440 jdk.internal.event.DeserializationEvent (java.base@21.0.4)
93: 115 9200 [Ljava.util.WeakHashMap$Entry; (java.base@21.0.4)
94: 368 8832 java.lang.module.ModuleDescriptor$Exports (java.base@21.0.4)
95: 63 8384 [Ljava.lang.invoke.MethodHandle; (java.base@21.0.4)
96: 146 8176 java.io.FileCleanable (java.base@21.0.4)
97: 125 8000 java.lang.Class$ReflectionData (java.base@21.0.4)
98: 323 7752 java.util.ImmutableCollections$Set12 (java.base@21.0.4)
99: 121 7744 jdk.internal.org.objectweb.asm.SymbolTable (java.base@21.0.4)
100: 70 7280 java.lang.invoke.InnerClassLambdaMetafactory (java.base@21.0.4)
101: 144 6912 jdk.internal.org.objectweb.asm.AnnotationWriter (java.base@21.0.4)
102: 167 6680 jdk.internal.loader.URLClassPath$JarLoader$2 (java.base@21.0.4)
103: 199 6368 java.lang.invoke.MethodHandles$Lookup (java.base@21.0.4)
104: 156 6240 java.util.StringJoiner (java.base@21.0.4)
105: 153 6120 java.io.FileDescriptor (java.base@21.0.4)
106: 126 6048 java.lang.invoke.LambdaForm (java.base@21.0.4)
107: 77 6016 [Ljava.lang.reflect.Method; (java.base@21.0.4)
108: 249 5976 java.util.zip.ZipFile$InflaterCleanupAction (java.base@21.0.4)
109: 373 5968 java.lang.Byte (java.base@21.0.4)
110: 74 5920 java.util.zip.ZipFile$Source (java.base@21.0.4)
111: 82 5720 [Ljava.io.ObjectStreamField; (java.base@21.0.4)
112: 40 5640 [Ljava.lang.ClassValue$Entry; (java.base@21.0.4)
113: 234 5616 java.util.jar.Attributes$Name (java.base@21.0.4)
114: 174 5568 java.util.concurrent.locks.ReentrantLock$NonfairSync (java.base@21.0.4)
115: 98 5488 java.lang.Module (java.base@21.0.4)
116: 219 5256 java.lang.PublicMethods$MethodList (java.base@21.0.4)
117: 65 5200 java.net.URI (java.base@21.0.4)
118: 215 5104 [Ljdk.internal.org.objectweb.asm.Type; (java.base@21.0.4)
truncated...
Total 4452140 139359040
0.186 s/op
+totalAllocatedBytes: 139359040.000 bytes
+totalAllocatedInstances: 4452140.000 instances
+totalHeap: 521412608.000 bytes
Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalAllocatedBytes":
139359040.000 bytes
Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalAllocatedInstances":
4452140.000 instances
Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalHeap":
521412608.000 bytes
# Run complete. Total time: 00:00:00
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.
NOTE: Current JVM experimentally supports Compiler Blackholes, and they are in use. Please exercise
extra caution when trusting the results, look into the generated code to check the benchmark still
works, and factor in a small probability of new VM bugs. Additionally, while comparisons between
different JVMs are already problematic, the performance difference caused by different Blackhole
modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons.
Benchmark Mode Cnt Score Error Units
AllocationBenchmark.run ss 0.186 s/op
AllocationBenchmark.run:+totalAllocatedBytes ss 139359040.000 bytes
AllocationBenchmark.run:+totalAllocatedInstances ss 4452140.000 instances
AllocationBenchmark.run:+totalHeap ss 521412608.000 bytes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.280 s
[INFO] Finished at: 2024-10-23T12:37:24-04:00
[INFO] ------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
@ -13,17 +13,18 @@
To completely disable a check, just comment it out or delete it from the file.
To suppress certain violations please review suppression filters.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
Authors: Max Vetrenko, Mauryan Kansara, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
<!-- See https://checkstyle.org/filefilters/index.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
@ -34,9 +35,16 @@
<property name="optional" value="true"/>
</module>
<!-- https://checkstyle.org/filters/suppresswithnearbytextfilter.html -->
<!--<module name="SuppressWithNearbyTextFilter">
<property name="nearbyTextPattern"
value="CHECKSTYLE.SUPPRESS\: (\w+) for ([+-]\d+) lines"/>
<property name="checkPattern" value="$1"/>
<property name="lineRange" value="$2"/>
</module>-->
<!-- Checks for whitespace -->
<!-- See http://checkstyle.org/config_whitespace.html -->
<!-- See http://checkstyle.org/checks/whitespace/index.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
@ -52,7 +60,7 @@
<module name="TreeWalker">
<!-- needed for SuppressWarningsFilter -->
<module name="SuppressWarningsHolder" />
<module name="SuppressWarnings">
<property name="id" value="checkstyle:suppresswarnings"/>
</module>
@ -69,48 +77,68 @@
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces">
<property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
<module name="LeftCurly">
<property name="id" value="LeftCurlyEol"/>
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT"/>
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LITERAL_CATCH,
LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF,
LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="LeftCurly">
<property name="id" value="LeftCurlyNl"/>
<property name="option" value="nl"/>
<property name="tokens"
value=" LITERAL_DEFAULT"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- LITERAL_DEFAULT are reused in SWITCH_RULE -->
<property name="id" value="LeftCurlyNl"/>
<property name="query" value="//SWITCH_RULE/SLIST"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
value="LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF"/>
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppression is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
<property name="id" value="RightCurlyAlone"/>
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/>
</module>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
@ -118,18 +146,35 @@
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<!--<property name="allowEmptySwitchBlockStatements" value="true"/>-->
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAND,
LCURLY, LE, LITERAL_DO, LITERAL_ELSE,
LITERAL_FOR, LITERAL_IF,
LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT,
TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="WhitespaceAround"/>
<property name="query" value="//*[self::LITERAL_IF or self::LITERAL_ELSE or self::STATIC_INIT
or self::LITERAL_TRY or self::LITERAL_CATCH]/SLIST[count(./*)=1]
| //*[self::STATIC_INIT or self::LITERAL_TRY or self::LITERAL_IF]
//*[self::RCURLY][parent::SLIST[count(./*)=1]]"/>
</module>
<module name="RegexpSinglelineJava">
<property name="format" value="\{[ ]+\}"/>
<property name="message" value="Empty blocks should have no spaces. Empty blocks
may only be represented as '{}' when not part of a
multi-block statement (4.1.3)"/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
@ -140,8 +185,9 @@
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
@ -155,13 +201,13 @@
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
@ -174,22 +220,23 @@
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
@ -199,38 +246,53 @@
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
@ -240,44 +302,62 @@
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="4"/>
</module>
<!-- Suppression for block code until we find a way to detect them properly
until https://github.com/checkstyle/checkstyle/issues/15769 -->
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="Indentation"/>
<property name="query" value="//SLIST[not(parent::CASE_GROUP)]/SLIST
| //SLIST[not(parent::CASE_GROUP)]/SLIST/RCURLY"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="true"/>
<property name="allowedAbbreviations" value="API" />
<property name="allowedAbbreviationLength" value="1"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF"/>
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OverloadMethodsDeclarationOrder"/>
<!--<module name="ConstructorsDeclarationGrouping"/>-->
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF,
TYPE_EXTENSION_AND "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
@ -289,46 +369,83 @@
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="JavadocParagraph">
</module>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="MissingJavadocMethod"/>
<property name="query" value="//*[self::METHOD_DEF or self::CTOR_DEF
or self::ANNOTATION_FIELD_DEF or self::COMPACT_CTOR_DEF]
[ancestor::*[self::INTERFACE_DEF or self::CLASS_DEF
or self::RECORD_DEF or self::ENUM_DEF]
[not(./MODIFIERS/LITERAL_PUBLIC)]]"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="MethodName"/>
<property name="query" value="//METHOD_DEF[
./MODIFIERS/ANNOTATION//IDENT[contains(@text, 'Test')]
]/IDENT"/>
<property name="message" value="'[a-z][a-z0-9][a-zA-Z0-9]*(?:_[a-z][a-z0-9][a-zA-Z0-9]*)*'"/>
</module>
<module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<!-- https://checkstyle.org/filters/suppressionxpathfilter.html -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<module name="SuppressWarningsHolder" />
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)" />
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)" />
<property name="checkFormat" value="$1" />
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE.SUPPRESS\: ([\w\|]+)"/>
<!-- $1 refers to the first match group in the regex defined in commentFormat -->
<property name="checkFormat" value="$1"/>
<!-- The check is suppressed in the next line of code after the comment -->
<property name="influenceFormat" value="1"/>
</module>
</module>
</module>

259
mvnw vendored Normal file
View File

@ -0,0 +1,259 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

149
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,149 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.2
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
if ($env:MAVEN_USER_HOME) {
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
}
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

1219
pom.xml

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
{
"bootstrap-sha": "c701a6c4ebbe1170a25ca7636a31508b9628831c",
"bootstrap-sha": "d7b591c9f910afad303d6d814f65c7f9dab33b89",
"signoff": "OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>",
"packages": {
".": {
"package-name": "dev.openfeature.sdk",

View File

@ -5,5 +5,10 @@
<username>${env.OSSRH_USERNAME}</username>
<password>${env.OSSRH_PASSWORD}</password>
</server>
<server>
<id>central</id>
<username>${env.CENTRAL_USERNAME}</username>
<password>${env.CENTRAL_PASSWORD}</password>
</server>
</servers>
</settings>

1
spec Submodule

@ -0,0 +1 @@
Subproject commit d4a9a910946eded57cf82d6fd4921785a5e64c2b

View File

@ -1,19 +1,36 @@
package dev.openfeature.sdk;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
@SuppressWarnings({ "PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType" })
@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"})
@EqualsAndHashCode
abstract class AbstractStructure implements Structure {
protected final Map<String, Value> attributes;
@Override
public boolean isEmpty() {
return attributes == null || attributes.isEmpty();
}
AbstractStructure() {
this.attributes = new HashMap<>();
}
AbstractStructure(Map<String, Value> attributes) {
this.attributes = new HashMap<>(attributes);
this.attributes = attributes;
}
/**
* Returns an unmodifiable representation of the internal attribute map.
*
* @return immutable map
*/
public Map<String, Value> asUnmodifiableMap() {
return Collections.unmodifiableMap(attributes);
}
/**
@ -23,12 +40,11 @@ abstract class AbstractStructure implements Structure {
*/
@Override
public Map<String, Object> asObjectMap() {
return attributes
.entrySet()
.stream()
return attributes.entrySet().stream()
// custom collector, workaround for Collectors.toMap in JDK8
// https://bugs.openjdk.org/browse/JDK-8148463
.collect(HashMap::new,
.collect(
HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(), convertValue(entry.getValue())),
HashMap::putAll);
}

View File

@ -0,0 +1,44 @@
package dev.openfeature.sdk;
/**
* A class to help with synchronization by allowing the optional awaiting of the associated action.
*/
public class Awaitable {
/**
* An already-completed Awaitable. Awaiting this will return immediately.
*/
public static final Awaitable FINISHED = new Awaitable(true);
private boolean isDone = false;
public Awaitable() {}
private Awaitable(boolean isDone) {
this.isDone = isDone;
}
/**
* Lets the calling thread wait until some other thread calls {@link Awaitable#wakeup()}. If
* {@link Awaitable#wakeup()} has been called before the current thread invokes this method, it will return
* immediately.
*/
@SuppressWarnings("java:S2142")
public synchronized void await() {
while (!isDone) {
try {
this.wait();
} catch (InterruptedException ignored) {
// ignored, do not propagate the interrupted state
}
}
}
/**
* Wakes up all threads that have called {@link Awaitable#await()} and lets them proceed.
*/
public synchronized void wakeup() {
isDone = true;
this.notifyAll();
}
}

View File

@ -2,29 +2,34 @@ package dev.openfeature.sdk;
/**
* This is a common interface between the evaluation results that providers return and what is given to the end users.
*
* @param <T> The type of flag being evaluated.
*/
public interface BaseEvaluation<T> {
/**
* Returns the resolved value of the evaluation.
*
* @return {T} the resolve value
*/
T getValue();
/**
* Returns an identifier for this value, if applicable.
*
* @return {String} value identifier
*/
String getVariant();
/**
* Describes how we came to the value that we're returning.
*
* @return {Reason}
*/
String getReason();
/**
* The error code, if applicable. Should only be set when the Reason is ERROR.
*
* @return {ErrorCode}
*/
ErrorCode getErrorCode();
@ -32,6 +37,7 @@ public interface BaseEvaluation<T> {
/**
* The error message (usually from exception.getMessage()), if applicable.
* Should only be set when the Reason is ERROR.
*
* @return {String}
*/
String getErrorMessage();

View File

@ -1,7 +1,10 @@
package dev.openfeature.sdk;
/**
* {@inheritDoc}
* An extension point which can run around flag resolution. They are intended to be used as a way to add custom logic
* to the lifecycle of flag evaluation.
*
* @see Hook
*/
public interface BooleanHook extends Hook<Boolean> {

View File

@ -5,17 +5,19 @@ import java.util.List;
/**
* Interface used to resolve flags of varying types.
*/
public interface Client extends Features, EventBus<Client> {
public interface Client extends Features, Tracking, EventBus<Client> {
ClientMetadata getMetadata();
/**
* Return an optional client-level evaluation context.
*
* @return {@link EvaluationContext}
*/
EvaluationContext getEvaluationContext();
/**
* Set the client-level evaluation context.
*
* @param ctx Client level context.
*/
Client setEvaluationContext(EvaluationContext ctx);
@ -30,7 +32,15 @@ public interface Client extends Features, EventBus<Client> {
/**
* Fetch the hooks associated to this client.
*
* @return A list of {@link Hook}s.
*/
List<Hook> getHooks();
/**
* Returns the current state of the associated provider.
*
* @return the provider state
*/
ProviderState getProviderState();
}

View File

@ -1,7 +1,10 @@
package dev.openfeature.sdk;
/**
* {@inheritDoc}
* An extension point which can run around flag resolution. They are intended to be used as a way to add custom logic
* to the lifecycle of flag evaluation.
*
* @see Hook
*/
public interface DoubleHook extends Hook<Double> {
@ -9,4 +12,4 @@ public interface DoubleHook extends Hook<Double> {
default boolean supportsFlagValueType(FlagValueType flagValueType) {
return FlagValueType.DOUBLE == flagValueType;
}
}
}

View File

@ -2,5 +2,12 @@ package dev.openfeature.sdk;
@SuppressWarnings("checkstyle:MissingJavadocType")
public enum ErrorCode {
PROVIDER_NOT_READY, FLAG_NOT_FOUND, PARSE_ERROR, TYPE_MISMATCH, TARGETING_KEY_MISSING, INVALID_CONTEXT, GENERAL
PROVIDER_NOT_READY,
FLAG_NOT_FOUND,
PARSE_ERROR,
TYPE_MISMATCH,
TARGETING_KEY_MISSING,
INVALID_CONTEXT,
GENERAL,
PROVIDER_FATAL
}

View File

@ -1,5 +1,9 @@
package dev.openfeature.sdk;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
/**
* The EvaluationContext is a container for arbitrary contextual data
* that can be used as a basis for dynamic evaluation.
@ -19,4 +23,41 @@ public interface EvaluationContext extends Structure {
* @return resulting merged context
*/
EvaluationContext merge(EvaluationContext overridingContext);
/**
* Recursively merges the overriding map into the base Value map.
* The base map is mutated, the overriding map is not.
* Null maps will cause no-op.
*
* @param newStructure function to create the right structure(s) for Values
* @param base base map to merge
* @param overriding overriding map to merge
*/
static void mergeMaps(
Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
if (base == null) {
return;
}
if (overriding == null || overriding.isEmpty()) {
return;
}
for (Entry<String, Value> overridingEntry : overriding.entrySet()) {
String key = overridingEntry.getKey();
if (overridingEntry.getValue().isStructure()
&& base.containsKey(key)
&& base.get(key).isStructure()) {
Structure mergedValue = base.get(key).asStructure();
Structure overridingValue = overridingEntry.getValue().asStructure();
Map<String, Value> newMap = mergedValue.asMap();
mergeMaps(newStructure, newMap, overridingValue.asUnmodifiableMap());
base.put(key, new Value(newStructure.apply(newMap)));
} else {
base.put(key, overridingEntry.getValue());
}
}
}
}

View File

@ -0,0 +1,24 @@
package dev.openfeature.sdk;
import java.util.HashMap;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
/**
* Represents an evaluation event.
*/
@Builder
@Getter
public class EvaluationEvent {
private String name;
@Singular("attribute")
private Map<String, Object> attributes;
public Map<String, Object> getAttributes() {
return new HashMap<>(attributes);
}
}

View File

@ -6,38 +6,38 @@ import java.util.function.Consumer;
* Interface for attaching event handlers.
*/
public interface EventBus<T> {
/**
* Add a handler for the {@link ProviderEvent#PROVIDER_READY} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderReady(Consumer<EventDetails> handler);
/**
* Add a handler for the {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderConfigurationChanged(Consumer<EventDetails> handler);
/**
* Add a handler for the {@link ProviderEvent#PROVIDER_STALE} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderError(Consumer<EventDetails> handler);
/**
* Add a handler for the {@link ProviderEvent#PROVIDER_ERROR} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
*
* @param handler behavior to add with this event
* @return this
*/
@ -45,18 +45,18 @@ public interface EventBus<T> {
/**
* Add a handler for the specified {@link ProviderEvent}.
*
* @param event event type
*
* @param event event type
* @param handler behavior to add with this event
* @return this
*/
T on(ProviderEvent event, Consumer<EventDetails> handler);
/**
* Remove the previously attached handler by reference.
* If the handler doesn't exists, no-op.
*
* @param event event type
*
* @param event event type
* @param handler to be removed
* @return this
*/

View File

@ -1,11 +1,13 @@
package dev.openfeature.sdk;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.SuperBuilder;
/**
* The details of a particular event.
*/
@EqualsAndHashCode(callSuper = true)
@Data
@SuperBuilder(toBuilder = true)
public class EventDetails extends ProviderEventDetails {
@ -17,9 +19,7 @@ public class EventDetails extends ProviderEventDetails {
}
static EventDetails fromProviderEventDetails(
ProviderEventDetails providerEventDetails,
String providerName,
String domain) {
ProviderEventDetails providerEventDetails, String providerName, String domain) {
return builder()
.domain(domain)
.providerName(providerName)

View File

@ -1,6 +1,10 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.internal.TriConsumer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
/**
* Abstract EventProvider. Providers must extend this class to support events.
@ -14,23 +18,23 @@ import dev.openfeature.sdk.internal.TriConsumer;
*
* @see FeatureProvider
*/
@Slf4j
public abstract class EventProvider implements FeatureProvider {
private EventProviderListener eventProviderListener;
private final ExecutorService emitterExecutor = Executors.newCachedThreadPool();
/**
* {@inheritDoc}
*/
@Override
public abstract ProviderState getState();
void setEventProviderListener(EventProviderListener eventProviderListener) {
this.eventProviderListener = eventProviderListener;
}
private TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit = null;
/**
* "Attach" this EventProvider to an SDK, which allows events to propagate from this provider.
* No-op if the same onEmit is already attached.
* No-op if the same onEmit is already attached.
*
* @param onEmit the function to run when a provider emits events.
* @throws IllegalStateException if attempted to bind a new emitter for already bound provider
*
*/
void attach(TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit) {
if (this.onEmit != null && this.onEmit != onEmit) {
@ -48,56 +52,96 @@ public abstract class EventProvider implements FeatureProvider {
this.onEmit = null;
}
/**
* Stop the event emitter executor and block until either termination has completed
* or timeout period has elapsed.
*/
@Override
public void shutdown() {
emitterExecutor.shutdown();
try {
if (!emitterExecutor.awaitTermination(EventSupport.SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
log.warn("Emitter executor did not terminate before the timeout period had elapsed");
emitterExecutor.shutdownNow();
}
} catch (InterruptedException e) {
emitterExecutor.shutdownNow();
Thread.currentThread().interrupt();
}
}
/**
* Emit the specified {@link ProviderEvent}.
*
*
* @param event The event type
* @param details The details of the event
*/
public void emit(ProviderEvent event, ProviderEventDetails details) {
if (this.onEmit != null) {
this.onEmit.accept(this, event, details);
public Awaitable emit(final ProviderEvent event, final ProviderEventDetails details) {
final var localEventProviderListener = this.eventProviderListener;
final var localOnEmit = this.onEmit;
if (localEventProviderListener == null && localOnEmit == null) {
return Awaitable.FINISHED;
}
final var awaitable = new Awaitable();
// These calls need to be executed on a different thread to prevent deadlocks when the provider initialization
// relies on a ready event to be emitted
emitterExecutor.submit(() -> {
try (var ignored = OpenFeatureAPI.lock.readLockAutoCloseable()) {
if (localEventProviderListener != null) {
localEventProviderListener.onEmit(event, details);
}
if (localOnEmit != null) {
localOnEmit.accept(this, event, details);
}
} finally {
awaitable.wakeup();
}
});
return awaitable;
}
/**
* Emit a {@link ProviderEvent#PROVIDER_READY} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
*
* @param details The details of the event
*/
public void emitProviderReady(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_READY, details);
public Awaitable emitProviderReady(ProviderEventDetails details) {
return emit(ProviderEvent.PROVIDER_READY, details);
}
/**
* Emit a
* {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED}
* event. Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
*
* @param details The details of the event
*/
public void emitProviderConfigurationChanged(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
public Awaitable emitProviderConfigurationChanged(ProviderEventDetails details) {
return emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
}
/**
* Emit a {@link ProviderEvent#PROVIDER_STALE} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
*
* @param details The details of the event
*/
public void emitProviderStale(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_STALE, details);
public Awaitable emitProviderStale(ProviderEventDetails details) {
return emit(ProviderEvent.PROVIDER_STALE, details);
}
/**
* Emit a {@link ProviderEvent#PROVIDER_ERROR} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
*
* @param details The details of the event
*/
public void emitProviderError(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_ERROR, details);
public Awaitable emitProviderError(ProviderEventDetails details) {
return emit(ProviderEvent.PROVIDER_ERROR, details);
}
}

View File

@ -0,0 +1,6 @@
package dev.openfeature.sdk;
@FunctionalInterface
interface EventProviderListener {
void onEmit(ProviderEvent event, ProviderEventDetails details);
}

View File

@ -1,18 +1,17 @@
package dev.openfeature.sdk;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
/**
* Util class for storing and running handlers.
@ -20,89 +19,79 @@ import java.util.function.Consumer;
@Slf4j
class EventSupport {
public static final int SHUTDOWN_TIMEOUT_SECONDS = 3;
// we use a v4 uuid as a "placeholder" for anonymous clients, since
// ConcurrentHashMap doesn't support nulls
private static final String defaultClientUuid = UUID.randomUUID().toString();
private static final int SHUTDOWN_TIMEOUT_SECONDS = 3;
private static final String DEFAULT_CLIENT_UUID = UUID.randomUUID().toString();
private final Map<String, HandlerStore> handlerStores = new ConcurrentHashMap<>();
private final HandlerStore globalHandlerStore = new HandlerStore();
private final ExecutorService taskExecutor = Executors.newCachedThreadPool(runnable -> {
final Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
});
private final ExecutorService taskExecutor = Executors.newCachedThreadPool();
/**
* Run all the event handlers associated with this domain.
* If the domain is null, handlers attached to unnamed clients will run.
*
*
* @param domain the domain to run event handlers for, or null
* @param event the event type
* @param eventDetails the event details
*/
public void runClientHandlers(String domain, ProviderEvent event, EventDetails eventDetails) {
domain = Optional.ofNullable(domain)
.orElse(defaultClientUuid);
domain = Optional.ofNullable(domain).orElse(DEFAULT_CLIENT_UUID);
// run handlers if they exist
Optional.ofNullable(handlerStores.get(domain))
.filter(store -> Optional.of(store).isPresent())
.map(store -> store.handlerMap.get(event))
.ifPresent(handlers -> handlers
.forEach(handler -> runHandler(handler, eventDetails)));
.ifPresent(handlers -> handlers.forEach(handler -> runHandler(handler, eventDetails)));
}
/**
* Run all the API (global) event handlers.
*
*
* @param event the event type
* @param eventDetails the event details
*/
public void runGlobalHandlers(ProviderEvent event, EventDetails eventDetails) {
globalHandlerStore.handlerMap.get(event)
.forEach(handler -> {
runHandler(handler, eventDetails);
});
globalHandlerStore.handlerMap.get(event).forEach(handler -> {
runHandler(handler, eventDetails);
});
}
/**
* Add a handler for the specified domain, or all unnamed clients.
*
* @param domain the domain to add handlers for, or else unnamed
* @param event the event type
* @param handler the handler function to run
*
* @param domain the domain to add handlers for, or else unnamed
* @param event the event type
* @param handler the handler function to run
*/
public void addClientHandler(String domain, ProviderEvent event, Consumer<EventDetails> handler) {
final String name = Optional.ofNullable(domain)
.orElse(defaultClientUuid);
final String name = Optional.ofNullable(domain).orElse(DEFAULT_CLIENT_UUID);
// lazily create and cache a HandlerStore if it doesn't exist
HandlerStore store = Optional.ofNullable(this.handlerStores.get(name))
.orElseGet(() -> {
HandlerStore newStore = new HandlerStore();
this.handlerStores.put(name, newStore);
return newStore;
});
HandlerStore store = Optional.ofNullable(this.handlerStores.get(name)).orElseGet(() -> {
HandlerStore newStore = new HandlerStore();
this.handlerStores.put(name, newStore);
return newStore;
});
store.addHandler(event, handler);
}
/**
* Remove a client event handler for the specified event type.
*
* @param domain the domain of the client handler to remove, or null to remove
* from unnamed clients
* @param event the event type
* @param handler the handler ref to be removed
*
* @param domain the domain of the client handler to remove, or null to remove
* from unnamed clients
* @param event the event type
* @param handler the handler ref to be removed
*/
public void removeClientHandler(String domain, ProviderEvent event, Consumer<EventDetails> handler) {
domain = Optional.ofNullable(domain)
.orElse(defaultClientUuid);
domain = Optional.ofNullable(domain).orElse(DEFAULT_CLIENT_UUID);
this.handlerStores.get(domain).removeHandler(event, handler);
}
/**
* Add a global event handler of the specified event type.
*
*
* @param event the event type
* @param handler the handler to be added
*/
@ -112,7 +101,7 @@ class EventSupport {
/**
* Remove a global event handler for the specified event type.
*
*
* @param event the event type
* @param handler the handler ref to be removed
*/
@ -122,7 +111,7 @@ class EventSupport {
/**
* Get all domain names for which we have event handlers registered.
*
*
* @return set of domain names
*/
public Set<String> getAllDomainNames() {
@ -131,7 +120,7 @@ class EventSupport {
/**
* Run the passed handler on the taskExecutor.
*
*
* @param handler the handler to run
* @param eventDetails the event details
*/
@ -167,14 +156,14 @@ class EventSupport {
// instantiated when a handler is added to that client.
static class HandlerStore {
private final Map<ProviderEvent, List<Consumer<EventDetails>>> handlerMap;
private final Map<ProviderEvent, Collection<Consumer<EventDetails>>> handlerMap;
HandlerStore() {
handlerMap = new ConcurrentHashMap<>();
handlerMap.put(ProviderEvent.PROVIDER_READY, new ArrayList<>());
handlerMap.put(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, new ArrayList<>());
handlerMap.put(ProviderEvent.PROVIDER_ERROR, new ArrayList<>());
handlerMap.put(ProviderEvent.PROVIDER_STALE, new ArrayList<>());
handlerMap.put(ProviderEvent.PROVIDER_READY, new ConcurrentLinkedQueue<>());
handlerMap.put(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, new ConcurrentLinkedQueue<>());
handlerMap.put(ProviderEvent.PROVIDER_ERROR, new ConcurrentLinkedQueue<>());
handlerMap.put(ProviderEvent.PROVIDER_STALE, new ConcurrentLinkedQueue<>());
}
void addHandler(ProviderEvent event, Consumer<EventDetails> handler) {

View File

@ -30,6 +30,7 @@ public interface FeatureProvider {
* can overwrite this method,
* if they have special initialization needed prior being called for flag
* evaluation.
*
* <p>
* It is ok if the method is expensive as it is executed in the background. All
* runtime exceptions will be
@ -45,6 +46,7 @@ public interface FeatureProvider {
* flags, or the SDK is shut down.
* Providers can overwrite this method, if they have special shutdown actions
* needed.
*
* <p>
* It is ok if the method is expensive as it is executed in the background. All
* runtime exceptions will be
@ -60,13 +62,23 @@ public interface FeatureProvider {
* If the provider needs to be initialized, it should return {@link ProviderState#NOT_READY}.
* If the provider is in an error state, it should return {@link ProviderState#ERROR}.
* If the provider is functioning normally, it should return {@link ProviderState#READY}.
*
*
* <p><i>Providers which do not implement this method are assumed to be ready immediately.</i></p>
*
*
* @return ProviderState
* @deprecated The state is handled by the SDK internally. Query the state from the {@link Client} instead.
*/
@Deprecated
default ProviderState getState() {
return ProviderState.READY;
}
/**
* Feature provider implementations can opt in for to support Tracking by implementing this method.
*
* @param eventName The name of the tracking event
* @param context Evaluation context used in flag evaluation (Optional)
* @param details Data pertinent to a particular tracking event (Optional)
*/
default void track(String eventName, EvaluationContext context, TrackingEventDetails details) {}
}

View File

@ -0,0 +1,88 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class FeatureProviderStateManager implements EventProviderListener {
private final FeatureProvider delegate;
private final AtomicBoolean isInitialized = new AtomicBoolean();
private final AtomicReference<ProviderState> state = new AtomicReference<>(ProviderState.NOT_READY);
public FeatureProviderStateManager(FeatureProvider delegate) {
this.delegate = delegate;
if (delegate instanceof EventProvider) {
((EventProvider) delegate).setEventProviderListener(this);
}
}
public void initialize(EvaluationContext evaluationContext) throws Exception {
if (isInitialized.getAndSet(true)) {
return;
}
try {
delegate.initialize(evaluationContext);
setState(ProviderState.READY);
} catch (OpenFeatureError openFeatureError) {
if (ErrorCode.PROVIDER_FATAL.equals(openFeatureError.getErrorCode())) {
setState(ProviderState.FATAL);
} else {
setState(ProviderState.ERROR);
}
isInitialized.set(false);
throw openFeatureError;
} catch (Exception e) {
setState(ProviderState.ERROR);
isInitialized.set(false);
throw e;
}
}
public void shutdown() {
delegate.shutdown();
setState(ProviderState.NOT_READY);
isInitialized.set(false);
}
@Override
public void onEmit(ProviderEvent event, ProviderEventDetails details) {
if (ProviderEvent.PROVIDER_ERROR.equals(event)) {
if (details != null && details.getErrorCode() == ErrorCode.PROVIDER_FATAL) {
setState(ProviderState.FATAL);
} else {
setState(ProviderState.ERROR);
}
} else if (ProviderEvent.PROVIDER_STALE.equals(event)) {
setState(ProviderState.STALE);
} else if (ProviderEvent.PROVIDER_READY.equals(event)) {
setState(ProviderState.READY);
}
}
private void setState(ProviderState state) {
ProviderState oldState = this.state.getAndSet(state);
if (oldState != state) {
String providerName;
if (delegate.getMetadata() == null || delegate.getMetadata().getName() == null) {
providerName = "unknown";
} else {
providerName = delegate.getMetadata().getName();
}
log.info("Provider {} transitioned from state {} to state {}", providerName, oldState, state);
}
}
public ProviderState getState() {
return state.get();
}
FeatureProvider getProvider() {
return delegate;
}
public boolean hasSameProvider(FeatureProvider featureProvider) {
return this.delegate.equals(featureProvider);
}
}

View File

@ -15,8 +15,8 @@ public interface Features {
FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defaultValue, EvaluationContext ctx);
FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options);
FlagEvaluationDetails<Boolean> getBooleanDetails(
String key, Boolean defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
String getStringValue(String key, String defaultValue);
@ -28,8 +28,8 @@ public interface Features {
FlagEvaluationDetails<String> getStringDetails(String key, String defaultValue, EvaluationContext ctx);
FlagEvaluationDetails<String> getStringDetails(String key, String defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options);
FlagEvaluationDetails<String> getStringDetails(
String key, String defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
Integer getIntegerValue(String key, Integer defaultValue);
@ -41,8 +41,8 @@ public interface Features {
FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defaultValue, EvaluationContext ctx);
FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options);
FlagEvaluationDetails<Integer> getIntegerDetails(
String key, Integer defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
Double getDoubleValue(String key, Double defaultValue);
@ -54,22 +54,19 @@ public interface Features {
FlagEvaluationDetails<Double> getDoubleDetails(String key, Double defaultValue, EvaluationContext ctx);
FlagEvaluationDetails<Double> getDoubleDetails(String key, Double defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options);
FlagEvaluationDetails<Double> getDoubleDetails(
String key, Double defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
Value getObjectValue(String key, Value defaultValue);
Value getObjectValue(String key, Value defaultValue, EvaluationContext ctx);
Value getObjectValue(String key, Value defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options);
Value getObjectValue(String key, Value defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue);
FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue,
EvaluationContext ctx);
FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue, EvaluationContext ctx);
FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue,
EvaluationContext ctx,
FlagEvaluationOptions options);
FlagEvaluationDetails<Value> getObjectDetails(
String key, Value defaultValue, EvaluationContext ctx, FlagEvaluationOptions options);
}

View File

@ -1,7 +1,6 @@
package dev.openfeature.sdk;
import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -25,6 +24,7 @@ public class FlagEvaluationDetails<T> implements BaseEvaluation<T> {
private String reason;
private ErrorCode errorCode;
private String errorMessage;
@Builder.Default
private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build();
@ -44,8 +44,8 @@ public class FlagEvaluationDetails<T> implements BaseEvaluation<T> {
.reason(providerEval.getReason())
.errorMessage(providerEval.getErrorMessage())
.errorCode(providerEval.getErrorCode())
.flagMetadata(
Optional.ofNullable(providerEval.getFlagMetadata()).orElse(ImmutableMetadata.builder().build()))
.flagMetadata(Optional.ofNullable(providerEval.getFlagMetadata())
.orElse(ImmutableMetadata.builder().build()))
.build();
}
}

View File

@ -3,7 +3,6 @@ package dev.openfeature.sdk;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Singular;
@ -13,6 +12,7 @@ import lombok.Singular;
public class FlagEvaluationOptions {
@Singular
List<Hook> hooks;
@Builder.Default
Map<String, Object> hookHints = new HashMap<>();
}

View File

@ -2,5 +2,9 @@ package dev.openfeature.sdk;
@SuppressWarnings("checkstyle:MissingJavadocType")
public enum FlagValueType {
STRING, INTEGER, DOUBLE, OBJECT, BOOLEAN;
STRING,
INTEGER,
DOUBLE,
OBJECT,
BOOLEAN;
}

View File

@ -16,7 +16,7 @@ public interface Hook<T> {
* @param ctx Information about the particular flag evaluation
* @param hints An immutable mapping of data for users to communicate to the hooks.
* @return An optional {@link EvaluationContext}. If returned, it will be merged with the EvaluationContext
* instances from other hooks, the client and API.
* instances from other hooks, the client and API.
*/
default Optional<EvaluationContext> before(HookContext<T> ctx, Map<String, Object> hints) {
return Optional.empty();
@ -29,8 +29,7 @@ public interface Hook<T> {
* @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.
*/
default void after(HookContext<T> ctx, FlagEvaluationDetails<T> details, Map<String, Object> hints) {
}
default void after(HookContext<T> ctx, FlagEvaluationDetails<T> details, Map<String, Object> hints) {}
/**
* Run when evaluation encounters an error. This will always run. Errors thrown will be swallowed.
@ -39,8 +38,7 @@ public interface Hook<T> {
* @param error The exception that was thrown.
* @param hints An immutable mapping of data for users to communicate to the hooks.
*/
default void error(HookContext<T> ctx, Exception error, Map<String, Object> hints) {
}
default void error(HookContext<T> ctx, Exception error, Map<String, Object> hints) {}
/**
* Run after flag evaluation, including any error processing. This will always run. Errors will be swallowed.
@ -48,8 +46,7 @@ public interface Hook<T> {
* @param ctx Information about the particular flag evaluation
* @param hints An immutable mapping of data for users to communicate to the hooks.
*/
default void finallyAfter(HookContext<T> ctx, Map<String, Object> hints) {
}
default void finallyAfter(HookContext<T> ctx, FlagEvaluationDetails<T> details, Map<String, Object> hints) {}
default boolean supportsFlagValueType(FlagValueType flagValueType) {
return true;

View File

@ -10,28 +10,40 @@ import lombok.With;
*
* @param <T> the type for the flag being evaluated
*/
@Value @Builder @With
@Value
@Builder
@With
public class HookContext<T> {
@NonNull String flagKey;
@NonNull FlagValueType type;
@NonNull T defaultValue;
@NonNull EvaluationContext ctx;
ClientMetadata clientMetadata;
Metadata providerMetadata;
/**
* Builds a {@link HookContext} instances from request data.
* @param key feature flag key
* @param type flag value type
* @param clientMetadata info on which client is calling
*
* @param key feature flag key
* @param type flag value type
* @param clientMetadata info on which client is calling
* @param providerMetadata info on the provider
* @param ctx Evaluation Context for the request
* @param defaultValue Fallback value
* @param <T> type that the flag is evaluating against
* @param ctx Evaluation Context for the request
* @param defaultValue Fallback value
* @param <T> type that the flag is evaluating against
* @return resulting context for hook
*/
public static <T> HookContext<T> from(String key, FlagValueType type, ClientMetadata clientMetadata,
Metadata providerMetadata, EvaluationContext ctx, T defaultValue) {
public static <T> HookContext<T> from(
String key,
FlagValueType type,
ClientMetadata clientMetadata,
Metadata providerMetadata,
EvaluationContext ctx,
T defaultValue) {
return HookContext.<T>builder()
.flagKey(key)
.type(type)

View File

@ -1,93 +1,101 @@
package dev.openfeature.sdk;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({"unchecked", "rawtypes"})
class HookSupport {
public void errorHooks(FlagValueType flagValueType, HookContext hookCtx, Exception e, List<Hook> hooks,
public EvaluationContext beforeHooks(
FlagValueType flagValueType, HookContext hookCtx, List<Hook> hooks, Map<String, Object> hints) {
return callBeforeHooks(flagValueType, hookCtx, hooks, hints);
}
public void afterHooks(
FlagValueType flagValueType,
HookContext hookContext,
FlagEvaluationDetails details,
List<Hook> hooks,
Map<String, Object> hints) {
executeHooksUnchecked(flagValueType, hooks, hook -> hook.after(hookContext, details, hints));
}
public void afterAllHooks(
FlagValueType flagValueType,
HookContext hookCtx,
FlagEvaluationDetails details,
List<Hook> hooks,
Map<String, Object> hints) {
executeHooks(flagValueType, hooks, "finally", hook -> hook.finallyAfter(hookCtx, details, hints));
}
public void errorHooks(
FlagValueType flagValueType,
HookContext hookCtx,
Exception e,
List<Hook> hooks,
Map<String, Object> hints) {
executeHooks(flagValueType, hooks, "error", hook -> hook.error(hookCtx, e, hints));
}
public void afterAllHooks(FlagValueType flagValueType, HookContext hookCtx, List<Hook> hooks,
Map<String, Object> hints) {
executeHooks(flagValueType, hooks, "finally", hook -> hook.finallyAfter(hookCtx, hints));
}
public void afterHooks(FlagValueType flagValueType, HookContext hookContext, FlagEvaluationDetails details,
List<Hook> hooks, Map<String, Object> hints) {
executeHooksUnchecked(flagValueType, hooks, hook -> hook.after(hookContext, details, hints));
}
private <T> void executeHooks(
FlagValueType flagValueType, List<Hook> hooks,
String hookMethod,
Consumer<Hook<T>> hookCode) {
FlagValueType flagValueType, List<Hook> hooks, String hookMethod, Consumer<Hook<T>> hookCode) {
if (hooks != null) {
hooks
.stream()
.filter(hook -> hook.supportsFlagValueType(flagValueType))
.forEach(hook -> executeChecked(hook, hookCode, hookMethod));
}
}
private <T> void executeHooksUnchecked(
FlagValueType flagValueType, List<Hook> hooks,
Consumer<Hook<T>> hookCode) {
if (hooks != null) {
hooks
.stream()
.filter(hook -> hook.supportsFlagValueType(flagValueType))
.forEach(hookCode::accept);
for (Hook hook : hooks) {
if (hook.supportsFlagValueType(flagValueType)) {
executeChecked(hook, hookCode, hookMethod);
}
}
}
}
// before, error, and finally hooks shouldn't throw
private <T> void executeChecked(Hook<T> hook, Consumer<Hook<T>> hookCode, String hookMethod) {
try {
hookCode.accept(hook);
} catch (Exception exception) {
log.error("Exception when running {} hooks {}", hookMethod, hook.getClass(), exception);
log.error(
"Unhandled exception when running {} hook {} (only 'after' hooks should throw)",
hookMethod,
hook.getClass(),
exception);
}
}
public EvaluationContext beforeHooks(FlagValueType flagValueType, HookContext hookCtx, List<Hook> hooks,
Map<String, Object> hints) {
Stream<EvaluationContext> result = callBeforeHooks(flagValueType, hookCtx, hooks, hints);
return hookCtx.getCtx().merge(
result.reduce(hookCtx.getCtx(), (EvaluationContext accumulated, EvaluationContext current) -> {
return accumulated.merge(current);
}));
// after hooks can throw in order to do validation
private <T> void executeHooksUnchecked(FlagValueType flagValueType, List<Hook> hooks, Consumer<Hook<T>> hookCode) {
if (hooks != null) {
for (Hook hook : hooks) {
if (hook.supportsFlagValueType(flagValueType)) {
hookCode.accept(hook);
}
}
}
}
private Stream<EvaluationContext> callBeforeHooks(FlagValueType flagValueType, HookContext hookCtx,
List<Hook> hooks, Map<String, Object> hints) {
private EvaluationContext callBeforeHooks(
FlagValueType flagValueType, HookContext hookCtx, List<Hook> hooks, Map<String, Object> hints) {
// These traverse backwards from normal.
List<Hook> reversedHooks = IntStream
.range(0, hooks.size())
.map(i -> hooks.size() - 1 - i)
.mapToObj(hooks::get)
.collect(Collectors.toList());
return reversedHooks
.stream()
.filter(hook -> hook.supportsFlagValueType(flagValueType))
.map(hook -> hook.before(hookCtx, hints))
.filter(Objects::nonNull)
.filter(Optional::isPresent)
.map(Optional::get)
.map(EvaluationContext.class::cast);
List<Hook> reversedHooks = new ArrayList<>(hooks);
Collections.reverse(reversedHooks);
EvaluationContext context = hookCtx.getCtx();
for (Hook hook : reversedHooks) {
if (hook.supportsFlagValueType(flagValueType)) {
Optional<EvaluationContext> optional =
Optional.ofNullable(hook.before(hookCtx, hints)).orElse(Optional.empty());
if (optional.isPresent()) {
context = context.merge(optional.get());
}
}
}
return context;
}
}

View File

@ -1,26 +1,31 @@
package dev.openfeature.sdk;
import lombok.ToString;
import lombok.experimental.Delegate;
import dev.openfeature.sdk.internal.ExcludeFromGeneratedCoverageReport;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Delegate;
/**
* The EvaluationContext is a container for arbitrary contextual data
* that can be used as a basis for dynamic evaluation.
* The ImmutableContext is an EvaluationContext implementation which is threadsafe, and whose attributes can
* The ImmutableContext is an EvaluationContext implementation which is
* threadsafe, and whose attributes can
* not be modified after instantiation.
*/
@ToString
@EqualsAndHashCode
@SuppressWarnings("PMD.BeanMembersShouldSerialize")
public final class ImmutableContext implements EvaluationContext {
@Delegate
private final Structure structure;
@Delegate(excludes = DelegateExclusions.class)
private final ImmutableStructure structure;
/**
* Create an immutable context with an empty targeting_key and attributes provided.
* Create an immutable context with an empty targeting_key and attributes
* provided.
*/
public ImmutableContext() {
this(new HashMap<>());
@ -41,7 +46,7 @@ public final class ImmutableContext implements EvaluationContext {
* @param attributes evaluation context attributes
*/
public ImmutableContext(Map<String, Value> attributes) {
this("", attributes);
this(null, attributes);
}
/**
@ -52,9 +57,7 @@ public final class ImmutableContext implements EvaluationContext {
*/
public ImmutableContext(String targetingKey, Map<String, Value> attributes) {
if (targetingKey != null && !targetingKey.trim().isEmpty()) {
final Map<String, Value> actualAttribs = new HashMap<>(attributes);
actualAttribs.put(TARGETING_KEY, new Value(targetingKey));
this.structure = new ImmutableStructure(actualAttribs);
this.structure = new ImmutableStructure(targetingKey, attributes);
} else {
this.structure = new ImmutableStructure(attributes);
}
@ -70,18 +73,34 @@ public final class ImmutableContext implements EvaluationContext {
}
/**
* Merges this EvaluationContext object with the passed EvaluationContext, overriding in case of conflict.
* Merges this EvaluationContext object with the passed EvaluationContext,
* overriding in case of conflict.
*
* @param overridingContext overriding context
* @return resulting merged context
* @return new, resulting merged context
*/
@Override
public EvaluationContext merge(EvaluationContext overridingContext) {
if (overridingContext == null) {
return new ImmutableContext(this.asMap());
if (overridingContext == null || overridingContext.isEmpty()) {
return new ImmutableContext(this.asUnmodifiableMap());
}
if (this.isEmpty()) {
return new ImmutableContext(overridingContext.asUnmodifiableMap());
}
return new ImmutableContext(
this.merge(ImmutableStructure::new, this.asMap(), overridingContext.asMap()));
Map<String, Value> attributes = this.asMap();
EvaluationContext.mergeMaps(ImmutableStructure::new, attributes, overridingContext.asUnmodifiableMap());
return new ImmutableContext(attributes);
}
@SuppressWarnings("all")
private static class DelegateExclusions {
@ExcludeFromGeneratedCoverageReport
public <T extends Structure> Map<String, Value> merge(
Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
return null;
}
}
}

View File

@ -1,10 +1,9 @@
package dev.openfeature.sdk;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
/**
* Immutable Flag Metadata representation. Implementation is backed by a {@link Map} and immutability is provided
@ -98,6 +97,13 @@ public class ImmutableMetadata {
}
}
public boolean isEmpty() {
return metadata.isEmpty();
}
public boolean isNotEmpty() {
return !metadata.isEmpty();
}
/**
* Obtain a builder for {@link ImmutableMetadata}.
@ -188,6 +194,5 @@ public class ImmutableMetadata {
public ImmutableMetadata build() {
return new ImmutableMetadata(this.metadata);
}
}
}

View File

@ -3,9 +3,9 @@ package dev.openfeature.sdk;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ -18,8 +18,8 @@ import lombok.ToString;
* not be modified after instantiation. All references are clones.
*/
@ToString
@EqualsAndHashCode
@SuppressWarnings({ "PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType" })
@EqualsAndHashCode(callSuper = true)
@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"})
public final class ImmutableStructure extends AbstractStructure {
/**
@ -35,14 +35,11 @@ public final class ImmutableStructure extends AbstractStructure {
* @param attributes attributes.
*/
public ImmutableStructure(Map<String, Value> attributes) {
super(new HashMap<>(attributes.entrySet()
.stream()
.collect(HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(),
Optional.ofNullable(entry.getValue())
.map(Value::clone)
.orElse(null)),
HashMap::putAll)));
super(copyAttributes(attributes, null));
}
ImmutableStructure(String targetingKey, Map<String, Value> attributes) {
super(copyAttributes(attributes, targetingKey));
}
@Override
@ -53,7 +50,7 @@ public final class ImmutableStructure extends AbstractStructure {
// getters
@Override
public Value getValue(String key) {
Value value = this.attributes.get(key);
Value value = attributes.get(key);
return value != null ? value.clone() : null;
}
@ -64,14 +61,27 @@ public final class ImmutableStructure extends AbstractStructure {
*/
@Override
public Map<String, Value> asMap() {
return attributes
.entrySet()
.stream()
.collect(HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(),
Optional.ofNullable(entry.getValue())
.map(Value::clone)
.orElse(null)),
HashMap::putAll);
return copyAttributes(attributes);
}
private static Map<String, Value> copyAttributes(Map<String, Value> in) {
return copyAttributes(in, null);
}
private static Map<String, Value> copyAttributes(Map<String, Value> in, String targetingKey) {
Map<String, Value> copy = new HashMap<>();
if (in != null) {
for (Entry<String, Value> entry : in.entrySet()) {
copy.put(
entry.getKey(),
Optional.ofNullable(entry.getValue())
.map((Value val) -> val.clone())
.orElse(null));
}
}
if (targetingKey != null) {
copy.put(EvaluationContext.TARGETING_KEY, new Value(targetingKey));
}
return copy;
}
}

View File

@ -0,0 +1,51 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.internal.ExcludeFromGeneratedCoverageReport;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import lombok.experimental.Delegate;
/**
* ImmutableTrackingEventDetails represents data pertinent to a particular tracking event.
*/
public class ImmutableTrackingEventDetails implements TrackingEventDetails {
@Delegate(excludes = DelegateExclusions.class)
private final ImmutableStructure structure;
private final Number value;
public ImmutableTrackingEventDetails() {
this.value = null;
this.structure = new ImmutableStructure();
}
public ImmutableTrackingEventDetails(final Number value) {
this.value = value;
this.structure = new ImmutableStructure();
}
public ImmutableTrackingEventDetails(final Number value, final Map<String, Value> attributes) {
this.value = value;
this.structure = new ImmutableStructure(attributes);
}
/**
* Returns the optional tracking value.
*/
public Optional<Number> getValue() {
return Optional.ofNullable(value);
}
@SuppressWarnings("all")
private static class DelegateExclusions {
@ExcludeFromGeneratedCoverageReport
public <T extends Structure> Map<String, Value> merge(
Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
return null;
}
}
}

View File

@ -1,7 +1,10 @@
package dev.openfeature.sdk;
/**
* {@inheritDoc}
* An extension point which can run around flag resolution. They are intended to be used as a way to add custom logic
* to the lifecycle of flag evaluation.
*
* @see Hook
*/
public interface IntegerHook extends Hook<Integer> {

View File

@ -1,13 +1,14 @@
package dev.openfeature.sdk;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Delegate;
import dev.openfeature.sdk.internal.ExcludeFromGeneratedCoverageReport;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Delegate;
/**
* The EvaluationContext is a container for arbitrary contextual data
@ -20,7 +21,8 @@ import java.util.Map;
@SuppressWarnings("PMD.BeanMembersShouldSerialize")
public class MutableContext implements EvaluationContext {
@Delegate(excludes = HideDelegateAddMethods.class) private final MutableStructure structure;
@Delegate(excludes = DelegateExclusions.class)
private final MutableStructure structure;
public MutableContext() {
this(new HashMap<>());
@ -31,7 +33,7 @@ public class MutableContext implements EvaluationContext {
}
public MutableContext(Map<String, Value> attributes) {
this("", attributes);
this(null, new HashMap<>(attributes));
}
/**
@ -42,7 +44,7 @@ public class MutableContext implements EvaluationContext {
* @param attributes evaluation context attributes
*/
public MutableContext(String targetingKey, Map<String, Value> attributes) {
this.structure = new MutableStructure(attributes);
this.structure = new MutableStructure(new HashMap<>(attributes));
if (targetingKey != null && !targetingKey.trim().isEmpty()) {
this.structure.attributes.put(TARGETING_KEY, new Value(targetingKey));
}
@ -94,7 +96,6 @@ public class MutableContext implements EvaluationContext {
return this;
}
/**
* Retrieve targetingKey from the context.
*/
@ -112,23 +113,37 @@ public class MutableContext implements EvaluationContext {
*/
@Override
public EvaluationContext merge(EvaluationContext overridingContext) {
if (overridingContext == null) {
return new MutableContext(this.asMap());
if (overridingContext == null || overridingContext.isEmpty()) {
return this;
}
if (this.isEmpty()) {
return overridingContext;
}
Map<String, Value> merged = this.merge(
MutableStructure::new, this.asMap(), overridingContext.asMap());
return new MutableContext(merged);
Map<String, Value> attributes = this.asMap();
EvaluationContext.mergeMaps(MutableStructure::new, attributes, overridingContext.asUnmodifiableMap());
return new MutableContext(attributes);
}
/**
* Hidden class to tell Lombok not to copy these methods over via delegation.
*/
private static class HideDelegateAddMethods {
@SuppressWarnings("all")
private static class DelegateExclusions {
@ExcludeFromGeneratedCoverageReport
public <T extends Structure> Map<String, Value> merge(
Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
return null;
}
public MutableStructure add(String ignoredKey, Boolean ignoredValue) {
return null;
}
public MutableStructure add(String ignoredKey, Double ignoredValue) {
return null;
}

View File

@ -5,19 +5,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* {@link MutableStructure} represents a potentially nested object type which is used to represent
* {@link MutableStructure} represents a potentially nested object type which is used to represent
* structured data.
* The MutableStructure is a Structure implementation which is not threadsafe, and whose attributes can
* The MutableStructure is a Structure implementation which is not threadsafe, and whose attributes can
* be modified after instantiation.
*/
@ToString
@EqualsAndHashCode
@SuppressWarnings({"PMD.BeanMembersShouldSerialize", "checkstyle:MissingJavadocType"})
@EqualsAndHashCode(callSuper = true)
public class MutableStructure extends AbstractStructure {
public MutableStructure() {
@ -30,13 +29,13 @@ public class MutableStructure extends AbstractStructure {
@Override
public Set<String> keySet() {
return this.attributes.keySet();
return attributes.keySet();
}
// getters
@Override
public Value getValue(String key) {
return this.attributes.get(key);
return attributes.get(key);
}
// adders
@ -87,6 +86,6 @@ public class MutableStructure extends AbstractStructure {
*/
@Override
public Map<String, Value> asMap() {
return new HashMap<>(this.attributes);
return new HashMap<>(attributes);
}
}

View File

@ -0,0 +1,94 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.internal.ExcludeFromGeneratedCoverageReport;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Delegate;
/**
* MutableTrackingEventDetails represents data pertinent to a particular tracking event.
*/
@EqualsAndHashCode
@ToString
public class MutableTrackingEventDetails implements TrackingEventDetails {
private final Number value;
@Delegate(excludes = MutableTrackingEventDetails.DelegateExclusions.class)
private final MutableStructure structure;
public MutableTrackingEventDetails() {
this.value = null;
this.structure = new MutableStructure();
}
public MutableTrackingEventDetails(final Number value) {
this.value = value;
this.structure = new MutableStructure();
}
/**
* Returns the optional tracking value.
*/
public Optional<Number> getValue() {
return Optional.ofNullable(value);
}
// override @Delegate methods so that we can use "add" methods and still return MutableTrackingEventDetails,
// not Structure
public MutableTrackingEventDetails add(String key, Boolean value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, String value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, Integer value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, Double value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, Instant value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, Structure value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, List<Value> value) {
this.structure.add(key, value);
return this;
}
public MutableTrackingEventDetails add(String key, Value value) {
this.structure.add(key, value);
return this;
}
@SuppressWarnings("all")
private static class DelegateExclusions {
@ExcludeFromGeneratedCoverageReport
public <T extends Structure> Map<String, Value> merge(
Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
return null;
}
}
}

View File

@ -7,6 +7,7 @@ import lombok.Getter;
*/
public class NoOpProvider implements FeatureProvider {
public static final String PASSED_IN_DEFAULT = "Passed in default";
@Getter
private final String name = "No-op Provider";
@ -58,8 +59,8 @@ public class NoOpProvider implements FeatureProvider {
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue,
EvaluationContext invocationContext) {
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext invocationContext) {
return ProviderEvaluation.<Value>builder()
.value(defaultValue)
.variant(PASSED_IN_DEFAULT)

View File

@ -7,6 +7,7 @@ public class NoOpTransactionContextPropagator implements TransactionContextPropa
/**
* {@inheritDoc}
*
* @return empty immutable context
*/
@Override
@ -18,7 +19,5 @@ public class NoOpTransactionContextPropagator implements TransactionContextPropa
* {@inheritDoc}
*/
@Override
public void setTransactionContext(EvaluationContext evaluationContext) {
}
public void setTransactionContext(EvaluationContext evaluationContext) {}
}

View File

@ -3,14 +3,16 @@ package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import dev.openfeature.sdk.internal.AutoCloseableLock;
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
/**
* A global singleton which holds base configuration for the OpenFeature
@ -22,15 +24,15 @@ import java.util.function.Consumer;
public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
// package-private multi-read/single-write lock
static AutoCloseableReentrantReadWriteLock lock = new AutoCloseableReentrantReadWriteLock();
private final List<Hook> apiHooks;
private final ConcurrentLinkedQueue<Hook> apiHooks;
private ProviderRepository providerRepository;
private EventSupport eventSupport;
private EvaluationContext evaluationContext;
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
private TransactionContextPropagator transactionContextPropagator;
protected OpenFeatureAPI() {
apiHooks = new ArrayList<>();
providerRepository = new ProviderRepository();
apiHooks = new ConcurrentLinkedQueue<>();
providerRepository = new ProviderRepository(this);
eventSupport = new EventSupport();
transactionContextPropagator = new NoOpTransactionContextPropagator();
}
@ -69,7 +71,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
}
/**
* A factory function for creating new, OpenFeature clients.
* A factory function for creating new, OpenFeature client.
* Clients can contain their own state (e.g. logger, hook, context).
* Multiple clients can be used to segment feature flag configuration.
* All un-named or unbound clients use the default provider.
@ -81,12 +83,12 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
}
/**
* A factory function for creating new domainless OpenFeature clients.
* A factory function for creating new domainless OpenFeature client.
* Clients can contain their own state (e.g. logger, hook, context).
* Multiple clients can be used to segment feature flag configuration.
* If there is already a provider bound to this domain, this provider will be used.
* Otherwise, the default provider is used until a provider is assigned to that domain.
*
*
* @param domain an identifier which logically binds clients with providers
* @return a new client instance
*/
@ -95,20 +97,18 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
}
/**
* A factory function for creating new domainless OpenFeature clients.
* A factory function for creating new domainless OpenFeature client.
* Clients can contain their own state (e.g. logger, hook, context).
* Multiple clients can be used to segment feature flag configuration.
* If there is already a provider bound to this domain, this provider will be used.
* Otherwise, the default provider is used until a provider is assigned to that domain.
*
* @param domain a identifier which logically binds clients with providers
*
* @param domain a identifier which logically binds clients with providers
* @param version a version identifier
* @return a new client instance
*/
public Client getClient(String domain, String version) {
return new OpenFeatureClient(this,
domain,
version);
return new OpenFeatureClient(this, domain, version);
}
/**
@ -118,9 +118,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
* @return api instance
*/
public OpenFeatureAPI setEvaluationContext(EvaluationContext evaluationContext) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
this.evaluationContext = evaluationContext;
}
this.evaluationContext.set(evaluationContext);
return this;
}
@ -130,16 +128,14 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
* @return evaluation context
*/
public EvaluationContext getEvaluationContext() {
try (AutoCloseableLock __ = lock.readLockAutoCloseable()) {
return this.evaluationContext;
}
return evaluationContext.get();
}
/**
* Return the transaction context propagator.
*/
public TransactionContextPropagator getTransactionContextPropagator() {
try (AutoCloseableLock __ = lock.readLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.readLockAutoCloseable()) {
return this.transactionContextPropagator;
}
}
@ -153,7 +149,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
if (transactionContextPropagator == null) {
throw new IllegalArgumentException("Transaction context propagator cannot be null");
}
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
this.transactionContextPropagator = transactionContextPropagator;
}
}
@ -179,7 +175,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
* Set the default provider.
*/
public void setProvider(FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
provider,
this::attachEventProvider,
@ -193,12 +189,13 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
/**
* Add a provider for a domain.
*
* @param domain The domain to bind the provider to.
* @param provider The provider to set.
* @param domain The domain to bind the provider to.
* @param provider The provider to set.
*/
public void setProvider(String domain, FeatureProvider provider) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(domain,
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
domain,
provider,
this::attachEventProvider,
this::emitReady,
@ -209,10 +206,16 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
}
/**
* Set the default provider and wait for initialization to finish.
* Sets the default provider and waits for its initialization to complete.
*
* <p>Note: If the provider fails during initialization, an {@link OpenFeatureError} will be thrown.
* It is recommended to wrap this call in a try-catch block to handle potential initialization failures gracefully.
*
* @param provider the {@link FeatureProvider} to set as the default.
* @throws OpenFeatureError if the provider fails during initialization.
*/
public void setProviderAndWait(FeatureProvider provider) throws OpenFeatureError {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
provider,
this::attachEventProvider,
@ -226,12 +229,17 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
/**
* Add a provider for a domain and wait for initialization to finish.
*
* @param domain The domain to bind the provider to.
* @param provider The provider to set.
* <p>Note: If the provider fails during initialization, an {@link OpenFeatureError} will be thrown.
* It is recommended to wrap this call in a try-catch block to handle potential initialization failures gracefully.
*
* @param domain The domain to bind the provider to.
* @param provider The provider to set.
* @throws OpenFeatureError if the provider fails during initialization.
*/
public void setProviderAndWait(String domain, FeatureProvider provider) throws OpenFeatureError {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(domain,
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
providerRepository.setProvider(
domain,
provider,
this::attachEventProvider,
this::emitReady,
@ -243,14 +251,15 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
private void attachEventProvider(FeatureProvider provider) {
if (provider instanceof EventProvider) {
((EventProvider) provider).attach((p, event, details) -> {
runHandlersForProvider(p, event, details);
});
((EventProvider) provider).attach(this::runHandlersForProvider);
}
}
private void emitReady(FeatureProvider provider) {
runHandlersForProvider(provider, ProviderEvent.PROVIDER_READY, ProviderEventDetails.builder().build());
runHandlersForProvider(
provider,
ProviderEvent.PROVIDER_READY,
ProviderEventDetails.builder().build());
}
private void detachEventProvider(FeatureProvider provider) {
@ -260,7 +269,9 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
}
private void emitError(FeatureProvider provider, OpenFeatureError exception) {
runHandlersForProvider(provider, ProviderEvent.PROVIDER_ERROR,
runHandlersForProvider(
provider,
ProviderEvent.PROVIDER_ERROR,
ProviderEventDetails.builder().message(exception.getMessage()).build());
}
@ -293,28 +304,32 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
* @param hooks The hook to add.
*/
public void addHooks(Hook... hooks) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
this.apiHooks.addAll(Arrays.asList(hooks));
}
this.apiHooks.addAll(Arrays.asList(hooks));
}
/**
* Fetch the hooks associated to this client.
*
* @return A list of {@link Hook}s.
*/
public List<Hook> getHooks() {
try (AutoCloseableLock __ = lock.readLockAutoCloseable()) {
return this.apiHooks;
}
return new ArrayList<>(this.apiHooks);
}
/**
* Returns a reference to the collection of {@link Hook}s.
*
* @return The collection of {@link Hook}s.
*/
Collection<Hook> getMutableHooks() {
return this.apiHooks;
}
/**
* Removes all hooks.
*/
public void clearHooks() {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
this.apiHooks.clear();
}
this.apiHooks.clear();
}
/**
@ -324,11 +339,11 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
* Once shut down is complete, API is reset and ready to use again.
*/
public void shutdown() {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
providerRepository.shutdown();
eventSupport.shutdown();
providerRepository = new ProviderRepository();
providerRepository = new ProviderRepository(this);
eventSupport = new EventSupport();
}
}
@ -370,7 +385,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
*/
@Override
public OpenFeatureAPI on(ProviderEvent event, Consumer<EventDetails> handler) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
this.eventSupport.addGlobalHandler(event, handler);
return this;
}
@ -381,62 +396,65 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
*/
@Override
public OpenFeatureAPI removeHandler(ProviderEvent event, Consumer<EventDetails> handler) {
this.eventSupport.removeGlobalHandler(event, handler);
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
this.eventSupport.removeGlobalHandler(event, handler);
}
return this;
}
void removeHandler(String domain, ProviderEvent event, Consumer<EventDetails> handler) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
eventSupport.removeClientHandler(domain, event, handler);
}
}
void addHandler(String domain, ProviderEvent event, Consumer<EventDetails> handler) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
// if the provider is in the state associated with event, run immediately
if (Optional.ofNullable(this.providerRepository.getProvider(domain).getState())
.orElse(ProviderState.READY).matchesEvent(event)) {
eventSupport.runHandler(handler, EventDetails.builder().domain(domain).build());
if (Optional.ofNullable(this.providerRepository.getProviderState(domain))
.orElse(ProviderState.READY)
.matchesEvent(event)) {
eventSupport.runHandler(
handler, EventDetails.builder().domain(domain).build());
}
eventSupport.addClientHandler(domain, event, handler);
}
}
FeatureProviderStateManager getFeatureProviderStateManager(String domain) {
return providerRepository.getFeatureProviderStateManager(domain);
}
/**
* 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
*/
private void runHandlersForProvider(FeatureProvider provider, ProviderEvent event, ProviderEventDetails details) {
try (AutoCloseableLock __ = lock.readLockAutoCloseable()) {
try (AutoCloseableLock ignored = lock.readLockAutoCloseable()) {
List<String> domainsForProvider = providerRepository
.getDomainsForProvider(provider);
List<String> domainsForProvider = providerRepository.getDomainsForProvider(provider);
final String providerName = Optional.ofNullable(provider.getMetadata())
.map(metadata -> metadata.getName())
.map(Metadata::getName)
.orElse(null);
// run the global handlers
eventSupport.runGlobalHandlers(event, EventDetails.fromProviderEventDetails(details, providerName));
// run the handlers associated with domains for this provider
domainsForProvider.forEach(domain -> {
eventSupport.runClientHandlers(domain, event,
EventDetails.fromProviderEventDetails(details, providerName, domain));
});
domainsForProvider.forEach(domain -> eventSupport.runClientHandlers(
domain, event, EventDetails.fromProviderEventDetails(details, providerName, domain)));
if (providerRepository.isDefaultProvider(provider)) {
// run handlers for clients that have no bound providers (since this is the default)
Set<String> allDomainNames = eventSupport.getAllDomainNames();
Set<String> boundDomains = providerRepository.getAllBoundDomains();
allDomainNames.removeAll(boundDomains);
allDomainNames.forEach(domain -> {
eventSupport.runClientHandlers(domain, event,
EventDetails.fromProviderEventDetails(details, providerName, domain));
});
allDomainNames.forEach(domain -> eventSupport.runClientHandlers(
domain, event, EventDetails.fromProviderEventDetails(details, providerName, domain)));
}
}
}

View File

@ -1,67 +1,130 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.ExceptionUtils;
import dev.openfeature.sdk.exceptions.FatalError;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
import dev.openfeature.sdk.internal.ObjectUtils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import dev.openfeature.sdk.internal.AutoCloseableLock;
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
import dev.openfeature.sdk.exceptions.ExceptionUtils;
import dev.openfeature.sdk.internal.ObjectUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
* {@inheritDoc}
* OpenFeature Client implementation.
* You should not instantiate this or reference this class.
* Use the dev.openfeature.sdk.Client interface instead.
*
* @see Client
* @deprecated // TODO: eventually we will make this non-public. See issue #872
*/
@Slf4j
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis", "PMD.BeanMembersShouldSerialize",
"PMD.UnusedLocalVariable", "unchecked", "rawtypes" })
@SuppressWarnings({
"PMD.DataflowAnomalyAnalysis",
"PMD.BeanMembersShouldSerialize",
"PMD.UnusedLocalVariable",
"unchecked",
"rawtypes"
})
@Deprecated() // TODO: eventually we will make this non-public. See issue #872
public class OpenFeatureClient implements Client {
private final OpenFeatureAPI openfeatureApi;
@Getter
private final String domain;
@Getter
private final String version;
private final List<Hook> clientHooks;
private final ConcurrentLinkedQueue<Hook> clientHooks;
private final HookSupport hookSupport;
AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock();
AutoCloseableReentrantReadWriteLock contextLock = new AutoCloseableReentrantReadWriteLock();
private EvaluationContext evaluationContext;
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
/**
* Deprecated public constructor. Use OpenFeature.API.getClient() instead.
*
* @param openFeatureAPI Backing global singleton
* @param domain An identifier which logically binds clients with providers (used by observability tools).
* @param domain An identifier which logically binds clients with
* providers (used by observability tools).
* @param version Version of the client (used by observability tools).
* @deprecated Do not use this constructor. It's for internal use only.
* Clients created using it will not run event handlers.
* Use the OpenFeatureAPI's getClient factory method instead.
* Clients created using it will not run event handlers.
* Use the OpenFeatureAPI's getClient factory method instead.
*/
@Deprecated() // TODO: eventually we will make this non-public. See issue #872
public OpenFeatureClient(OpenFeatureAPI openFeatureAPI, String domain, String version) {
this.openfeatureApi = openFeatureAPI;
this.domain = domain;
this.version = version;
this.clientHooks = new ArrayList<>();
this.clientHooks = new ConcurrentLinkedQueue<>();
this.hookSupport = new HookSupport();
}
/**
* {@inheritDoc}
*/
@Override
public ProviderState getProviderState() {
return openfeatureApi.getFeatureProviderStateManager(domain).getState();
}
/**
* {@inheritDoc}
*/
@Override
public void track(String trackingEventName) {
validateTrackingEventName(trackingEventName);
invokeTrack(trackingEventName, null, null);
}
/**
* {@inheritDoc}
*/
@Override
public void track(String trackingEventName, EvaluationContext context) {
validateTrackingEventName(trackingEventName);
Objects.requireNonNull(context);
invokeTrack(trackingEventName, context, null);
}
/**
* {@inheritDoc}
*/
@Override
public void track(String trackingEventName, TrackingEventDetails details) {
validateTrackingEventName(trackingEventName);
Objects.requireNonNull(details);
invokeTrack(trackingEventName, null, details);
}
/**
* {@inheritDoc}
*/
@Override
public void track(String trackingEventName, EvaluationContext context, TrackingEventDetails details) {
validateTrackingEventName(trackingEventName);
Objects.requireNonNull(context);
Objects.requireNonNull(details);
invokeTrack(trackingEventName, mergeEvaluationContext(context), details);
}
/**
* {@inheritDoc}
*/
@Override
public OpenFeatureClient addHooks(Hook... hooks) {
try (AutoCloseableLock __ = this.hooksLock.writeLockAutoCloseable()) {
this.clientHooks.addAll(Arrays.asList(hooks));
}
this.clientHooks.addAll(Arrays.asList(hooks));
return this;
}
@ -70,9 +133,7 @@ public class OpenFeatureClient implements Client {
*/
@Override
public List<Hook> getHooks() {
try (AutoCloseableLock __ = this.hooksLock.readLockAutoCloseable()) {
return this.clientHooks;
}
return new ArrayList<>(this.clientHooks);
}
/**
@ -80,9 +141,7 @@ public class OpenFeatureClient implements Client {
*/
@Override
public OpenFeatureClient setEvaluationContext(EvaluationContext evaluationContext) {
try (AutoCloseableLock __ = contextLock.writeLockAutoCloseable()) {
this.evaluationContext = evaluationContext;
}
this.evaluationContext.set(evaluationContext);
return this;
}
@ -91,50 +150,70 @@ public class OpenFeatureClient implements Client {
*/
@Override
public EvaluationContext getEvaluationContext() {
try (AutoCloseableLock __ = contextLock.readLockAutoCloseable()) {
return this.evaluationContext;
}
return this.evaluationContext.get();
}
private <T> FlagEvaluationDetails<T> evaluateFlag(FlagValueType type, String key, T defaultValue,
EvaluationContext ctx, FlagEvaluationOptions options) {
FlagEvaluationOptions flagOptions = ObjectUtils.defaultIfNull(options,
() -> FlagEvaluationOptions.builder().build());
Map<String, Object> hints = Collections.unmodifiableMap(flagOptions.getHookHints());
ctx = ObjectUtils.defaultIfNull(ctx, () -> new ImmutableContext());
@SuppressFBWarnings(
value = {"REC_CATCH_EXCEPTION"},
justification = "We don't want to allow any exception to reach the user. "
+ "Instead, we return an evaluation result with the appropriate error code.")
private <T> FlagEvaluationDetails<T> evaluateFlag(
FlagValueType type, String key, T defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
var flagOptions = ObjectUtils.defaultIfNull(
options, () -> FlagEvaluationOptions.builder().build());
var hints = Collections.unmodifiableMap(flagOptions.getHookHints());
FlagEvaluationDetails<T> details = null;
List<Hook> mergedHooks = null;
HookContext<T> hookCtx = null;
FeatureProvider provider;
HookContext<T> afterHookContext = null;
try {
// openfeatureApi.getProvider() must be called once to maintain a consistent reference
provider = openfeatureApi.getProvider(this.domain);
var stateManager = openfeatureApi.getFeatureProviderStateManager(this.domain);
// provider must be accessed once to maintain a consistent reference
var provider = stateManager.getProvider();
var state = stateManager.getState();
mergedHooks = ObjectUtils.merge(provider.getProviderHooks(), flagOptions.getHooks(), clientHooks,
openfeatureApi.getHooks());
mergedHooks = ObjectUtils.merge(
provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getMutableHooks());
hookCtx = HookContext.from(key, type, this.getMetadata(),
provider.getMetadata(), ctx, defaultValue);
var mergedCtx = hookSupport.beforeHooks(
type,
HookContext.from(
key,
type,
this.getMetadata(),
provider.getMetadata(),
mergeEvaluationContext(ctx),
defaultValue),
mergedHooks,
hints);
EvaluationContext ctxFromHook = hookSupport.beforeHooks(type, hookCtx, mergedHooks, hints);
afterHookContext =
HookContext.from(key, type, this.getMetadata(), provider.getMetadata(), mergedCtx, defaultValue);
EvaluationContext mergedCtx = mergeEvaluationContext(ctxFromHook, ctx);
// "short circuit" if the provider is in NOT_READY or FATAL state
if (ProviderState.NOT_READY.equals(state)) {
throw new ProviderNotReadyError("Provider not yet initialized");
}
if (ProviderState.FATAL.equals(state)) {
throw new FatalError("Provider is in an irrecoverable error state");
}
ProviderEvaluation<T> providerEval = (ProviderEvaluation<T>) createProviderEvaluation(type, key,
defaultValue, provider, mergedCtx);
var providerEval =
(ProviderEvaluation<T>) createProviderEvaluation(type, key, defaultValue, provider, mergedCtx);
details = FlagEvaluationDetails.from(providerEval, key);
if (details.getErrorCode() != null) {
throw ExceptionUtils.instantiateErrorByErrorCode(details.getErrorCode(), details.getErrorMessage());
var error =
ExceptionUtils.instantiateErrorByErrorCode(details.getErrorCode(), details.getErrorMessage());
enrichDetailsWithErrorDefaults(defaultValue, details);
hookSupport.errorHooks(type, afterHookContext, error, mergedHooks, hints);
} else {
hookSupport.afterHooks(type, hookCtx, details, mergedHooks, hints);
hookSupport.afterHooks(type, afterHookContext, details, mergedHooks, hints);
}
} catch (Exception e) {
log.error("Unable to correctly evaluate flag with key '{}'", key, e);
if (details == null) {
details = FlagEvaluationDetails.<T>builder().build();
details = FlagEvaluationDetails.<T>builder().flagKey(key).build();
}
if (e instanceof OpenFeatureError) {
details.setErrorCode(((OpenFeatureError) e).getErrorCode());
@ -142,37 +221,58 @@ public class OpenFeatureClient implements Client {
details.setErrorCode(ErrorCode.GENERAL);
}
details.setErrorMessage(e.getMessage());
details.setValue(defaultValue);
details.setReason(Reason.ERROR.toString());
hookSupport.errorHooks(type, hookCtx, e, mergedHooks, hints);
enrichDetailsWithErrorDefaults(defaultValue, details);
hookSupport.errorHooks(type, afterHookContext, e, mergedHooks, hints);
} finally {
hookSupport.afterAllHooks(type, hookCtx, mergedHooks, hints);
hookSupport.afterAllHooks(type, afterHookContext, details, mergedHooks, hints);
}
return details;
}
private static <T> void enrichDetailsWithErrorDefaults(T defaultValue, FlagEvaluationDetails<T> details) {
details.setValue(defaultValue);
details.setReason(Reason.ERROR.toString());
}
private static void validateTrackingEventName(String str) {
Objects.requireNonNull(str);
if (str.isEmpty()) {
throw new IllegalArgumentException("trackingEventName cannot be empty");
}
}
private void invokeTrack(String trackingEventName, EvaluationContext context, TrackingEventDetails details) {
openfeatureApi
.getFeatureProviderStateManager(domain)
.getProvider()
.track(trackingEventName, mergeEvaluationContext(context), details);
}
/**
* Merge hook and invocation contexts with API, transaction and client contexts.
* Merge invocation contexts with API, transaction and client contexts.
* Does not merge before context.
*
* @param hookContext hook context
* @param invocationContext invocation context
* @return merged evaluation context
*/
private EvaluationContext mergeEvaluationContext(
EvaluationContext hookContext,
EvaluationContext invocationContext) {
final EvaluationContext apiContext = openfeatureApi.getEvaluationContext() != null
? openfeatureApi.getEvaluationContext()
: new ImmutableContext();
final EvaluationContext clientContext = this.getEvaluationContext() != null
? this.getEvaluationContext()
: new ImmutableContext();
final EvaluationContext transactionContext = openfeatureApi.getTransactionContext() != null
? openfeatureApi.getTransactionContext()
: new ImmutableContext();
private EvaluationContext mergeEvaluationContext(EvaluationContext invocationContext) {
final EvaluationContext apiContext = openfeatureApi.getEvaluationContext();
final EvaluationContext clientContext = evaluationContext.get();
final EvaluationContext transactionContext = openfeatureApi.getTransactionContext();
return mergeContextMaps(apiContext, transactionContext, clientContext, invocationContext);
}
return apiContext.merge(transactionContext.merge(clientContext.merge(invocationContext.merge(hookContext))));
private EvaluationContext mergeContextMaps(EvaluationContext... contexts) {
// avoid any unnecessary context instantiations and stream usage here; this is
// called with every evaluation.
Map merged = new HashMap<>();
for (EvaluationContext evaluationContext : contexts) {
if (evaluationContext != null && !evaluationContext.isEmpty()) {
EvaluationContext.mergeMaps(ImmutableStructure::new, merged, evaluationContext.asUnmodifiableMap());
}
}
return new ImmutableContext(merged);
}
private <T> ProviderEvaluation<?> createProviderEvaluation(
@ -208,8 +308,8 @@ public class OpenFeatureClient implements Client {
}
@Override
public Boolean getBooleanValue(String key, Boolean defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public Boolean getBooleanValue(
String key, Boolean defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return getBooleanDetails(key, defaultValue, ctx, options).getValue();
}
@ -220,12 +320,13 @@ public class OpenFeatureClient implements Client {
@Override
public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defaultValue, EvaluationContext ctx) {
return getBooleanDetails(key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getBooleanDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
}
@Override
public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public FlagEvaluationDetails<Boolean> getBooleanDetails(
String key, Boolean defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.BOOLEAN, key, defaultValue, ctx, options);
}
@ -240,8 +341,8 @@ public class OpenFeatureClient implements Client {
}
@Override
public String getStringValue(String key, String defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public String getStringValue(
String key, String defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return getStringDetails(key, defaultValue, ctx, options).getValue();
}
@ -252,12 +353,13 @@ public class OpenFeatureClient implements Client {
@Override
public FlagEvaluationDetails<String> getStringDetails(String key, String defaultValue, EvaluationContext ctx) {
return getStringDetails(key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getStringDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
}
@Override
public FlagEvaluationDetails<String> getStringDetails(String key, String defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public FlagEvaluationDetails<String> getStringDetails(
String key, String defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.STRING, key, defaultValue, ctx, options);
}
@ -272,8 +374,8 @@ public class OpenFeatureClient implements Client {
}
@Override
public Integer getIntegerValue(String key, Integer defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public Integer getIntegerValue(
String key, Integer defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return getIntegerDetails(key, defaultValue, ctx, options).getValue();
}
@ -284,12 +386,13 @@ public class OpenFeatureClient implements Client {
@Override
public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defaultValue, EvaluationContext ctx) {
return getIntegerDetails(key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getIntegerDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
}
@Override
public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public FlagEvaluationDetails<Integer> getIntegerDetails(
String key, Integer defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.INTEGER, key, defaultValue, ctx, options);
}
@ -304,9 +407,10 @@ public class OpenFeatureClient implements Client {
}
@Override
public Double getDoubleValue(String key, Double defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.DOUBLE, key, defaultValue, ctx, options).getValue();
public Double getDoubleValue(
String key, Double defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.DOUBLE, key, defaultValue, ctx, options)
.getValue();
}
@Override
@ -320,8 +424,8 @@ public class OpenFeatureClient implements Client {
}
@Override
public FlagEvaluationDetails<Double> getDoubleDetails(String key, Double defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public FlagEvaluationDetails<Double> getDoubleDetails(
String key, Double defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.DOUBLE, key, defaultValue, ctx, options);
}
@ -336,8 +440,7 @@ public class OpenFeatureClient implements Client {
}
@Override
public Value getObjectValue(String key, Value defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public Value getObjectValue(String key, Value defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return getObjectDetails(key, defaultValue, ctx, options).getValue();
}
@ -347,14 +450,14 @@ public class OpenFeatureClient implements Client {
}
@Override
public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue,
EvaluationContext ctx) {
return getObjectDetails(key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue, EvaluationContext ctx) {
return getObjectDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
}
@Override
public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue, EvaluationContext ctx,
FlagEvaluationOptions options) {
public FlagEvaluationDetails<Value> getObjectDetails(
String key, Value defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
return this.evaluateFlag(FlagValueType.OBJECT, key, defaultValue, ctx, options);
}
@ -400,7 +503,7 @@ public class OpenFeatureClient implements Client {
*/
@Override
public Client on(ProviderEvent event, Consumer<EventDetails> handler) {
OpenFeatureAPI.getInstance().addHandler(domain, event, handler);
openfeatureApi.addHandler(domain, event, handler);
return this;
}
@ -409,7 +512,7 @@ public class OpenFeatureClient implements Client {
*/
@Override
public Client removeHandler(ProviderEvent event, Consumer<EventDetails> handler) {
OpenFeatureAPI.getInstance().removeHandler(domain, event, handler);
openfeatureApi.removeHandler(domain, event, handler);
return this;
}
}

View File

@ -20,6 +20,7 @@ public class ProviderEvaluation<T> implements BaseEvaluation<T> {
private String reason;
ErrorCode errorCode;
private String errorMessage;
@Builder.Default
private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build();
}

View File

@ -4,5 +4,8 @@ package dev.openfeature.sdk;
* Provider event types.
*/
public enum ProviderEvent {
PROVIDER_READY, PROVIDER_CONFIGURATION_CHANGED, PROVIDER_ERROR, PROVIDER_STALE;
PROVIDER_READY,
PROVIDER_CONFIGURATION_CHANGED,
PROVIDER_ERROR,
PROVIDER_STALE;
}

View File

@ -1,16 +1,17 @@
package dev.openfeature.sdk;
import java.util.List;
import lombok.Data;
import lombok.experimental.SuperBuilder;
/**
* The details of a particular event.
*/
@Data @SuperBuilder(toBuilder = true)
@Data
@SuperBuilder(toBuilder = true)
public class ProviderEventDetails {
private List<String> flagsChanged;
private String message;
private ImmutableMetadata eventMetadata;
private ErrorCode errorCode;
}

View File

@ -1,5 +1,7 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -12,27 +14,47 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class ProviderRepository {
private final Map<String, FeatureProvider> providers = new ConcurrentHashMap<>();
private final AtomicReference<FeatureProvider> defaultProvider = new AtomicReference<>(new NoOpProvider());
private final Map<String, FeatureProviderStateManager> stateManagers = new ConcurrentHashMap<>();
private final AtomicReference<FeatureProviderStateManager> defaultStateManger =
new AtomicReference<>(new FeatureProviderStateManager(new NoOpProvider()));
private final ExecutorService taskExecutor = Executors.newCachedThreadPool(runnable -> {
final Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
});
private final Object registerStateManagerLock = new Object();
private final OpenFeatureAPI openFeatureAPI;
public ProviderRepository(OpenFeatureAPI openFeatureAPI) {
this.openFeatureAPI = openFeatureAPI;
}
FeatureProviderStateManager getFeatureProviderStateManager() {
return defaultStateManger.get();
}
FeatureProviderStateManager getFeatureProviderStateManager(String domain) {
if (domain == null) {
return defaultStateManger.get();
}
FeatureProviderStateManager fromMap = this.stateManagers.get(domain);
if (fromMap == null) {
return this.defaultStateManger.get();
} else {
return fromMap;
}
}
/**
* Return the default provider.
*/
public FeatureProvider getProvider() {
return defaultProvider.get();
return defaultStateManger.get().getProvider();
}
/**
@ -42,17 +64,47 @@ class ProviderRepository {
* @return A named {@link FeatureProvider}
*/
public FeatureProvider getProvider(String domain) {
return Optional.ofNullable(domain).map(this.providers::get).orElse(this.defaultProvider.get());
return getFeatureProviderStateManager(domain).getProvider();
}
public ProviderState getProviderState() {
return getFeatureProviderStateManager().getState();
}
public ProviderState getProviderState(FeatureProvider featureProvider) {
if (featureProvider instanceof FeatureProviderStateManager) {
return ((FeatureProviderStateManager) featureProvider).getState();
}
FeatureProviderStateManager defaultProvider = this.defaultStateManger.get();
if (defaultProvider.hasSameProvider(featureProvider)) {
return defaultProvider.getState();
}
for (FeatureProviderStateManager wrapper : stateManagers.values()) {
if (wrapper.hasSameProvider(featureProvider)) {
return wrapper.getState();
}
}
return null;
}
public ProviderState getProviderState(String domain) {
return Optional.ofNullable(domain)
.map(this.stateManagers::get)
.orElse(this.defaultStateManger.get())
.getState();
}
public List<String> getDomainsForProvider(FeatureProvider provider) {
return providers.entrySet().stream()
.filter(entry -> entry.getValue().equals(provider))
.map(entry -> entry.getKey()).collect(Collectors.toList());
return stateManagers.entrySet().stream()
.filter(entry -> entry.getValue().hasSameProvider(provider))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
public Set<String> getAllBoundDomains() {
return providers.keySet();
return stateManagers.keySet();
}
public boolean isDefaultProvider(FeatureProvider provider) {
@ -62,7 +114,8 @@ class ProviderRepository {
/**
* Set the default provider.
*/
public void setProvider(FeatureProvider provider,
public void setProvider(
FeatureProvider provider,
Consumer<FeatureProvider> afterSet,
Consumer<FeatureProvider> afterInit,
Consumer<FeatureProvider> afterShutdown,
@ -82,7 +135,8 @@ class ProviderRepository {
* @param waitForInit When true, wait for initialization to finish, then returns.
* Otherwise, initialization happens in the background.
*/
public void setProvider(String domain,
public void setProvider(
String domain,
FeatureProvider provider,
Consumer<FeatureProvider> afterSet,
Consumer<FeatureProvider> afterInit,
@ -98,69 +152,107 @@ class ProviderRepository {
prepareAndInitializeProvider(domain, provider, afterSet, afterInit, afterShutdown, afterError, waitForInit);
}
private void prepareAndInitializeProvider(String domain,
FeatureProvider newProvider,
Consumer<FeatureProvider> afterSet,
Consumer<FeatureProvider> afterInit,
Consumer<FeatureProvider> afterShutdown,
BiConsumer<FeatureProvider, OpenFeatureError> afterError,
boolean waitForInit) {
private void prepareAndInitializeProvider(
String domain,
FeatureProvider newProvider,
Consumer<FeatureProvider> afterSet,
Consumer<FeatureProvider> afterInit,
Consumer<FeatureProvider> afterShutdown,
BiConsumer<FeatureProvider, OpenFeatureError> afterError,
boolean waitForInit) {
final FeatureProviderStateManager newStateManager;
final FeatureProviderStateManager oldStateManager;
if (!isProviderRegistered(newProvider)) {
// only run afterSet if new provider is not already attached
afterSet.accept(newProvider);
synchronized (registerStateManagerLock) {
FeatureProviderStateManager existing = getExistingStateManagerForProvider(newProvider);
if (existing == null) {
newStateManager = new FeatureProviderStateManager(newProvider);
// only run afterSet if new provider is not already attached
afterSet.accept(newProvider);
} else {
newStateManager = existing;
}
// provider is set immediately, on this thread
oldStateManager = domain != null
? this.stateManagers.put(domain, newStateManager)
: this.defaultStateManger.getAndSet(newStateManager);
}
// provider is set immediately, on this thread
FeatureProvider oldProvider = domain != null
? this.providers.put(domain, newProvider)
: this.defaultProvider.getAndSet(newProvider);
if (waitForInit) {
initializeProvider(newProvider, afterInit, afterShutdown, afterError, oldProvider);
initializeProvider(newStateManager, afterInit, afterShutdown, afterError, oldStateManager);
} else {
taskExecutor.submit(() -> {
// initialization happens in a different thread if we're not waiting it
initializeProvider(newProvider, afterInit, afterShutdown, afterError, oldProvider);
// initialization happens in a different thread if we're not waiting for it
initializeProvider(newStateManager, afterInit, afterShutdown, afterError, oldStateManager);
});
}
}
private void initializeProvider(FeatureProvider newProvider,
private FeatureProviderStateManager getExistingStateManagerForProvider(FeatureProvider provider) {
for (FeatureProviderStateManager stateManager : stateManagers.values()) {
if (stateManager.hasSameProvider(provider)) {
return stateManager;
}
}
FeatureProviderStateManager defaultFeatureProviderStateManager = defaultStateManger.get();
if (defaultFeatureProviderStateManager.hasSameProvider(provider)) {
return defaultFeatureProviderStateManager;
}
return null;
}
private void initializeProvider(
FeatureProviderStateManager newManager,
Consumer<FeatureProvider> afterInit,
Consumer<FeatureProvider> afterShutdown,
BiConsumer<FeatureProvider, OpenFeatureError> afterError,
FeatureProvider oldProvider) {
FeatureProviderStateManager oldManager) {
try {
if (ProviderState.NOT_READY.equals(newProvider.getState())) {
newProvider.initialize(OpenFeatureAPI.getInstance().getEvaluationContext());
afterInit.accept(newProvider);
if (ProviderState.NOT_READY.equals(newManager.getState())) {
newManager.initialize(openFeatureAPI.getEvaluationContext());
afterInit.accept(newManager.getProvider());
}
shutDownOld(oldProvider, afterShutdown);
shutDownOld(oldManager, afterShutdown);
} catch (OpenFeatureError e) {
log.error("Exception when initializing feature provider {}", newProvider.getClass().getName(), e);
afterError.accept(newProvider, e);
log.error(
"Exception when initializing feature provider {}",
newManager.getProvider().getClass().getName(),
e);
afterError.accept(newManager.getProvider(), e);
} catch (Exception e) {
log.error("Exception when initializing feature provider {}", newProvider.getClass().getName(), e);
afterError.accept(newProvider, new GeneralError(e));
log.error(
"Exception when initializing feature provider {}",
newManager.getProvider().getClass().getName(),
e);
afterError.accept(newManager.getProvider(), new GeneralError(e));
}
}
private void shutDownOld(FeatureProvider oldProvider, Consumer<FeatureProvider> afterShutdown) {
if (!isProviderRegistered(oldProvider)) {
shutdownProvider(oldProvider);
afterShutdown.accept(oldProvider);
private void shutDownOld(FeatureProviderStateManager oldManager, Consumer<FeatureProvider> afterShutdown) {
if (oldManager != null && !isStateManagerRegistered(oldManager)) {
shutdownProvider(oldManager);
afterShutdown.accept(oldManager.getProvider());
}
}
/**
* Helper to check if provider is already known (registered).
* @param provider provider to check for registration
* Helper to check if manager is already known (registered).
*
* @param manager manager to check for registration
* @return boolean true if already registered, false otherwise
*/
private boolean isProviderRegistered(FeatureProvider provider) {
return provider != null
&& (this.providers.containsValue(provider) || this.defaultProvider.get().equals(provider));
private boolean isStateManagerRegistered(FeatureProviderStateManager manager) {
return manager != null
&& (this.stateManagers.containsValue(manager)
|| this.defaultStateManger.get().equals(manager));
}
private void shutdownProvider(FeatureProviderStateManager manager) {
if (manager == null) {
return;
}
shutdownProvider(manager.getProvider());
}
private void shutdownProvider(FeatureProvider provider) {
@ -168,7 +260,10 @@ class ProviderRepository {
try {
provider.shutdown();
} catch (Exception e) {
log.error("Exception when shutting down feature provider {}", provider.getClass().getName(), e);
log.error(
"Exception when shutting down feature provider {}",
provider.getClass().getName(),
e);
}
});
}
@ -179,11 +274,10 @@ class ProviderRepository {
* including the default feature provider.
*/
public void shutdown() {
Stream
.concat(Stream.of(this.defaultProvider.get()), this.providers.values().stream())
Stream.concat(Stream.of(this.defaultStateManger.get()), this.stateManagers.values().stream())
.distinct()
.forEach(this::shutdownProvider);
this.providers.clear();
this.stateManagers.clear();
taskExecutor.shutdown();
}
}

View File

@ -4,11 +4,15 @@ package dev.openfeature.sdk;
* Indicates the state of the provider.
*/
public enum ProviderState {
READY, NOT_READY, ERROR, STALE;
READY,
NOT_READY,
ERROR,
STALE,
FATAL;
/**
* Returns true if the passed ProviderEvent maps to this ProviderState.
*
*
* @param event event to compare
* @return boolean if matches.
*/

View File

@ -4,5 +4,12 @@ package dev.openfeature.sdk;
* Predefined resolution reasons.
*/
public enum Reason {
DISABLED, SPLIT, TARGETING_MATCH, DEFAULT, UNKNOWN, CACHED, STATIC, ERROR
DISABLED,
SPLIT,
TARGETING_MATCH,
DEFAULT,
UNKNOWN,
CACHED,
STATIC,
ERROR
}

View File

@ -1,7 +1,10 @@
package dev.openfeature.sdk;
/**
* {@inheritDoc}
* An extension point which can run around flag resolution. They are intended to be used as a way to add custom logic
* to the lifecycle of flag evaluation.
*
* @see Hook
*/
public interface StringHook extends Hook<String> {

View File

@ -1,23 +1,27 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.ValueNotConvertableError;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
import static dev.openfeature.sdk.Value.objectToValue;
import dev.openfeature.sdk.exceptions.ValueNotConvertableError;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* {@link Structure} represents a potentially nested object type which is used to represent
* {@link Structure} represents a potentially nested object type which is used to represent
* structured data.
*/
@SuppressWarnings("PMD.BeanMembersShouldSerialize")
public interface Structure {
/**
* Boolean indicating if this structure is empty.
*
* @return boolean for emptiness
*/
boolean isEmpty();
/**
* Get all keys.
*
@ -40,6 +44,13 @@ public interface Structure {
*/
Map<String, Value> asMap();
/**
* Get all values, as a map of Values.
*
* @return all attributes on the structure into a Map
*/
Map<String, Value> asUnmodifiableMap();
/**
* Get all values, with as a map of Object.
*
@ -81,54 +92,21 @@ public interface Structure {
}
if (value.isList()) {
return value.asList()
.stream()
.map(this::convertValue)
.collect(Collectors.toList());
return value.asList().stream().map(this::convertValue).collect(Collectors.toList());
}
if (value.isStructure()) {
Structure s = value.asStructure();
return s.asMap()
.entrySet()
.stream()
.collect(HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(),
convertValue(entry.getValue())),
return s.asUnmodifiableMap().entrySet().stream()
.collect(
HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(), convertValue(entry.getValue())),
HashMap::putAll);
}
throw new ValueNotConvertableError();
}
/**
* Recursively merges the base map with the overriding map.
*
* @param <T> Structure type
* @param newStructure function to create the right structure
* @param base base map to merge
* @param overriding overriding map to merge
* @return resulting merged map
*/
default <T extends Structure> Map<String, Value> merge(Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {
final Map<String, Value> merged = new HashMap<>(base);
for (Entry<String, Value> overridingEntry : overriding.entrySet()) {
String key = overridingEntry.getKey();
if (overridingEntry.getValue().isStructure() && merged.containsKey(key) && merged.get(key).isStructure()) {
Structure mergedValue = merged.get(key).asStructure();
Structure overridingValue = overridingEntry.getValue().asStructure();
Map<String, Value> newMap = this.merge(newStructure, mergedValue.asMap(), overridingValue.asMap());
merged.put(key, new Value(newStructure.apply(newMap)));
} else {
merged.put(key, overridingEntry.getValue());
}
}
return merged;
}
/**
* Transform an object map to a {@link Structure} type.
*
@ -137,9 +115,9 @@ public interface Structure {
*/
static Structure mapToStructure(Map<String, Object> map) {
return new MutableStructure(map.entrySet().stream()
.collect(HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(),
objectToValue(entry.getValue())),
.collect(
HashMap::new,
(accumulated, entry) -> accumulated.put(entry.getKey(), objectToValue(entry.getValue())),
HashMap::putAll));
}
}

View File

@ -0,0 +1,95 @@
package dev.openfeature.sdk;
/**
* The Telemetry class provides constants and methods for creating OpenTelemetry compliant
* evaluation events.
*/
public class Telemetry {
private Telemetry() {}
/*
The OpenTelemetry compliant event attributes for flag evaluation.
Specification: https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
*/
public static final String TELEMETRY_KEY = "feature_flag.key";
public static final String TELEMETRY_ERROR_CODE = "error.type";
public static final String TELEMETRY_VARIANT = "feature_flag.result.variant";
public static final String TELEMETRY_VALUE = "feature_flag.result.value";
public static final String TELEMETRY_CONTEXT_ID = "feature_flag.context.id";
public static final String TELEMETRY_ERROR_MSG = "feature_flag.evaluation.error.message";
public static final String TELEMETRY_REASON = "feature_flag.result.reason";
public static final String TELEMETRY_PROVIDER = "feature_flag.provider.name";
public static final String TELEMETRY_FLAG_SET_ID = "feature_flag.set.id";
public static final String TELEMETRY_VERSION = "feature_flag.version";
// Well-known flag metadata attributes for telemetry events.
// Specification: https://openfeature.dev/specification/appendix-d#flag-metadata
public static final String TELEMETRY_FLAG_META_CONTEXT_ID = "contextId";
public static final String TELEMETRY_FLAG_META_FLAG_SET_ID = "flagSetId";
public static final String TELEMETRY_FLAG_META_VERSION = "version";
public static final String FLAG_EVALUATION_EVENT_NAME = "feature_flag.evaluation";
/**
* Creates an EvaluationEvent using the provided HookContext and ProviderEvaluation.
*
* @param hookContext the context containing flag evaluation details
* @param evaluationDetails the evaluation result from the provider
*
* @return an EvaluationEvent populated with telemetry data
*/
public static EvaluationEvent createEvaluationEvent(
HookContext<?> hookContext, FlagEvaluationDetails<?> evaluationDetails) {
EvaluationEvent.EvaluationEventBuilder evaluationEventBuilder = EvaluationEvent.builder()
.name(FLAG_EVALUATION_EVENT_NAME)
.attribute(TELEMETRY_KEY, hookContext.getFlagKey())
.attribute(TELEMETRY_PROVIDER, hookContext.getProviderMetadata().getName());
if (evaluationDetails.getReason() != null) {
evaluationEventBuilder.attribute(
TELEMETRY_REASON, evaluationDetails.getReason().toLowerCase());
} else {
evaluationEventBuilder.attribute(
TELEMETRY_REASON, Reason.UNKNOWN.name().toLowerCase());
}
if (evaluationDetails.getVariant() != null) {
evaluationEventBuilder.attribute(TELEMETRY_VARIANT, evaluationDetails.getVariant());
} else {
evaluationEventBuilder.attribute(TELEMETRY_VALUE, evaluationDetails.getValue());
}
String contextId = evaluationDetails.getFlagMetadata().getString(TELEMETRY_FLAG_META_CONTEXT_ID);
if (contextId != null) {
evaluationEventBuilder.attribute(TELEMETRY_CONTEXT_ID, contextId);
} else {
evaluationEventBuilder.attribute(
TELEMETRY_CONTEXT_ID, hookContext.getCtx().getTargetingKey());
}
String setID = evaluationDetails.getFlagMetadata().getString(TELEMETRY_FLAG_META_FLAG_SET_ID);
if (setID != null) {
evaluationEventBuilder.attribute(TELEMETRY_FLAG_SET_ID, setID);
}
String version = evaluationDetails.getFlagMetadata().getString(TELEMETRY_FLAG_META_VERSION);
if (version != null) {
evaluationEventBuilder.attribute(TELEMETRY_VERSION, version);
}
if (Reason.ERROR.name().equals(evaluationDetails.getReason())) {
if (evaluationDetails.getErrorCode() != null) {
evaluationEventBuilder.attribute(TELEMETRY_ERROR_CODE, evaluationDetails.getErrorCode());
} else {
evaluationEventBuilder.attribute(TELEMETRY_ERROR_CODE, ErrorCode.GENERAL);
}
if (evaluationDetails.getErrorMessage() != null) {
evaluationEventBuilder.attribute(TELEMETRY_ERROR_MSG, evaluationDetails.getErrorMessage());
}
}
return evaluationEventBuilder.build();
}
}

View File

@ -0,0 +1,42 @@
package dev.openfeature.sdk;
/**
* Interface for Tracking events.
*/
public interface Tracking {
/**
* Performs tracking of a particular action or application state.
*
* @param trackingEventName Event name to track
* @throws IllegalArgumentException if {@code trackingEventName} is null
*/
void track(String trackingEventName);
/**
* Performs tracking of a particular action or application state.
*
* @param trackingEventName Event name to track
* @param context Evaluation context used in flag evaluation
* @throws IllegalArgumentException if {@code trackingEventName} is null
*/
void track(String trackingEventName, EvaluationContext context);
/**
* Performs tracking of a particular action or application state.
*
* @param trackingEventName Event name to track
* @param details Data pertinent to a particular tracking event
* @throws IllegalArgumentException if {@code trackingEventName} is null
*/
void track(String trackingEventName, TrackingEventDetails details);
/**
* Performs tracking of a particular action or application state.
*
* @param trackingEventName Event name to track
* @param context Evaluation context used in flag evaluation
* @param details Data pertinent to a particular tracking event
* @throws IllegalArgumentException if {@code trackingEventName} is null
*/
void track(String trackingEventName, EvaluationContext context, TrackingEventDetails details);
}

View File

@ -0,0 +1,14 @@
package dev.openfeature.sdk;
import java.util.Optional;
/**
* Data pertinent to a particular tracking event.
*/
public interface TrackingEventDetails extends Structure {
/**
* Returns the optional numeric tracking value.
*/
Optional<Number> getValue();
}

View File

@ -5,6 +5,7 @@ package dev.openfeature.sdk;
* for the duration of a single transaction.
* Examples of potential transaction specific context include: a user id, user agent, IP.
* Transaction context is merged with evaluation context prior to flag evaluation.
*
* <p>
* The precedence of merging context can be seen in
* <a href=https://openfeature.dev/specification/sections/evaluation-context#requirement-323>the specification</a>.

View File

@ -1,17 +1,16 @@
package dev.openfeature.sdk;
import static dev.openfeature.sdk.Structure.mapToStructure;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.ToString;
import static dev.openfeature.sdk.Structure.mapToStructure;
/**
* Values serve as a generic return type for structure data from providers.
* Providers may deal in JSON, protobuf, XML or some other data-interchange format.
@ -37,33 +36,34 @@ public class Value implements Cloneable {
/**
* Construct a new Value with an Object.
*
* @param value to be wrapped.
* @throws InstantiationException if value is not a valid type
* (boolean, string, int, double, list, structure, instant)
* (boolean, string, int, double, list, structure, instant)
*/
public Value(Object value) throws InstantiationException {
this.innerObject = value;
if (!this.isNull()
&& !this.isBoolean()
&& !this.isString()
&& !this.isNumber()
&& !this.isStructure()
&& !this.isList()
&& !this.isInstant()) {
&& !this.isBoolean()
&& !this.isString()
&& !this.isNumber()
&& !this.isStructure()
&& !this.isList()
&& !this.isInstant()) {
throw new InstantiationException("Invalid value type: " + value.getClass());
}
}
public Value(Value value) {
this.innerObject = value.innerObject;
this.innerObject = value.innerObject;
}
public Value(Boolean value) {
this.innerObject = value;
this.innerObject = value;
}
public Value(String value) {
this.innerObject = value;
this.innerObject = value;
}
public Value(Integer value) {
@ -71,69 +71,69 @@ public class Value implements Cloneable {
}
public Value(Double value) {
this.innerObject = value;
this.innerObject = value;
}
public Value(Structure value) {
this.innerObject = value;
this.innerObject = value;
}
public Value(List<Value> value) {
this.innerObject = value;
this.innerObject = value;
}
public Value(Instant value) {
this.innerObject = value;
}
/**
/**
* Check if this Value represents null.
*
*
* @return boolean
*/
public boolean isNull() {
return this.innerObject == null;
}
/**
/**
* Check if this Value represents a Boolean.
*
*
* @return boolean
*/
public boolean isBoolean() {
return this.innerObject instanceof Boolean;
}
/**
/**
* Check if this Value represents a String.
*
*
* @return boolean
*/
public boolean isString() {
return this.innerObject instanceof String;
}
/**
/**
* Check if this Value represents a numeric value.
*
*
* @return boolean
*/
public boolean isNumber() {
return this.innerObject instanceof Number;
}
/**
/**
* Check if this Value represents a Structure.
*
*
* @return boolean
*/
public boolean isStructure() {
return this.innerObject instanceof Structure;
}
/**
/**
* Check if this Value represents a List of Values.
*
*
* @return boolean
*/
public boolean isList() {
@ -155,87 +155,88 @@ public class Value implements Cloneable {
return true;
}
/**
/**
* Check if this Value represents an Instant.
*
*
* @return boolean
*/
public boolean isInstant() {
return this.innerObject instanceof Instant;
}
/**
/**
* Retrieve the underlying Boolean value, or null.
*
*
* @return Boolean
*/
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "NP_BOOLEAN_RETURN_NULL",
justification = "This is not a plain true/false method. It's understood it can return null.")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
value = "NP_BOOLEAN_RETURN_NULL",
justification = "This is not a plain true/false method. It's understood it can return null.")
public Boolean asBoolean() {
if (this.isBoolean()) {
return (Boolean)this.innerObject;
return (Boolean) this.innerObject;
}
return null;
}
/**
/**
* Retrieve the underlying object.
*
*
* @return Object
*/
public Object asObject() {
return this.innerObject;
}
/**
/**
* Retrieve the underlying String value, or null.
*
*
* @return String
*/
public String asString() {
if (this.isString()) {
return (String)this.innerObject;
return (String) this.innerObject;
}
return null;
}
/**
/**
* Retrieve the underlying numeric value as an Integer, or null.
* If the value is not an integer, it will be rounded using Math.round().
*
*
* @return Integer
*/
public Integer asInteger() {
if (this.isNumber() && !this.isNull()) {
return ((Number)this.innerObject).intValue();
}
return null;
}
/**
* Retrieve the underlying numeric value as a Double, or null.
*
* @return Double
*/
public Double asDouble() {
if (this.isNumber() && !isNull()) {
return ((Number)this.innerObject).doubleValue();
return ((Number) this.innerObject).intValue();
}
return null;
}
/**
/**
* Retrieve the underlying numeric value as a Double, or null.
*
* @return Double
*/
public Double asDouble() {
if (this.isNumber() && !isNull()) {
return ((Number) this.innerObject).doubleValue();
}
return null;
}
/**
* Retrieve the underlying Structure value, or null.
*
*
* @return Structure
*/
public Structure asStructure() {
if (this.isStructure()) {
return (Structure)this.innerObject;
return (Structure) this.innerObject;
}
return null;
}
/**
* Retrieve the underlying List value, or null.
*
@ -249,14 +250,14 @@ public class Value implements Cloneable {
return null;
}
/**
/**
* Retrieve the underlying Instant value, or null.
*
*
* @return Instant
*/
public Instant asInstant() {
if (this.isInstant()) {
return (Instant)this.innerObject;
return (Instant) this.innerObject;
}
return null;
}
@ -274,7 +275,7 @@ public class Value implements Cloneable {
return new Value(copy);
}
if (this.isStructure()) {
return new Value(new ImmutableStructure(this.asStructure().asMap()));
return new Value(new ImmutableStructure(this.asStructure().asUnmodifiableMap()));
}
if (this.isInstant()) {
Instant copy = Instant.ofEpochMilli(this.asInstant().toEpochMilli());
@ -305,9 +306,8 @@ public class Value implements Cloneable {
} else if (object instanceof Structure) {
return new Value((Structure) object);
} else if (object instanceof List) {
return new Value(((List<Object>) object).stream()
.map(o -> objectToValue(o))
.collect(Collectors.toList()));
return new Value(
((List<Object>) object).stream().map(o -> objectToValue(o)).collect(Collectors.toList()));
} else if (object instanceof Instant) {
return new Value((Instant) object);
} else if (object instanceof Map) {

View File

@ -9,7 +9,8 @@ public class ExceptionUtils {
/**
* Creates an Error for the specific error code.
* @param errorCode the ErrorCode to use
*
* @param errorCode the ErrorCode to use
* @param errorMessage the error message to include in the returned error
* @return the specific OpenFeatureError for the errorCode
*/

View File

@ -0,0 +1,14 @@
package dev.openfeature.sdk.exceptions;
import dev.openfeature.sdk.ErrorCode;
import lombok.Getter;
import lombok.experimental.StandardException;
@SuppressWarnings("checkstyle:MissingJavadocType")
@StandardException
public class FatalError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter
private final ErrorCode errorCode = ErrorCode.PROVIDER_FATAL;
}

View File

@ -4,14 +4,11 @@ import dev.openfeature.sdk.ErrorCode;
import lombok.Getter;
import lombok.experimental.StandardException;
@SuppressWarnings("checkstyle:MissingJavadocType")
@SuppressWarnings({"checkstyle:MissingJavadocType", "squid:S110"})
@StandardException
public class FlagNotFoundError extends OpenFeatureError {
public class FlagNotFoundError extends OpenFeatureErrorWithoutStacktrace {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.FLAG_NOT_FOUND;
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
@Getter
private final ErrorCode errorCode = ErrorCode.FLAG_NOT_FOUND;
}

View File

@ -8,6 +8,7 @@ import lombok.experimental.StandardException;
@StandardException
public class GeneralError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter
private final ErrorCode errorCode = ErrorCode.GENERAL;
}

View File

@ -11,6 +11,6 @@ import lombok.experimental.StandardException;
public class InvalidContextError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.INVALID_CONTEXT;
@Getter
private final ErrorCode errorCode = ErrorCode.INVALID_CONTEXT;
}

View File

@ -0,0 +1,14 @@
package dev.openfeature.sdk.exceptions;
import lombok.experimental.StandardException;
@SuppressWarnings("checkstyle:MissingJavadocType")
@StandardException
public abstract class OpenFeatureErrorWithoutStacktrace extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}

View File

@ -11,6 +11,6 @@ import lombok.experimental.StandardException;
public class ParseError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.PARSE_ERROR;
@Getter
private final ErrorCode errorCode = ErrorCode.PARSE_ERROR;
}

View File

@ -4,9 +4,11 @@ import dev.openfeature.sdk.ErrorCode;
import lombok.Getter;
import lombok.experimental.StandardException;
@SuppressWarnings("checkstyle:MissingJavadocType")
@SuppressWarnings({"checkstyle:MissingJavadocType", "squid:S110"})
@StandardException
public class ProviderNotReadyError extends OpenFeatureError {
public class ProviderNotReadyError extends OpenFeatureErrorWithoutStacktrace {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY;
@Getter
private final ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY;
}

View File

@ -11,6 +11,6 @@ import lombok.experimental.StandardException;
public class TargetingKeyMissingError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.TARGETING_KEY_MISSING;
@Getter
private final ErrorCode errorCode = ErrorCode.TARGETING_KEY_MISSING;
}

View File

@ -7,10 +7,11 @@ import lombok.experimental.StandardException;
/**
* The type of the flag value does not match the expected type.
*/
@SuppressWarnings({"checkstyle:MissingJavadocType", "squid:S110"})
@StandardException
public class TypeMismatchError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter private final ErrorCode errorCode = ErrorCode.TYPE_MISMATCH;
@Getter
private final ErrorCode errorCode = ErrorCode.TYPE_MISMATCH;
}

View File

@ -10,6 +10,7 @@ import lombok.experimental.StandardException;
@StandardException
public class ValueNotConvertableError extends OpenFeatureError {
private static final long serialVersionUID = 1L;
@Getter
private final ErrorCode errorCode = ErrorCode.GENERAL;
}

View File

@ -0,0 +1,94 @@
package dev.openfeature.sdk.hooks.logging;
import dev.openfeature.sdk.ErrorCode;
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.FlagEvaluationDetails;
import dev.openfeature.sdk.Hook;
import dev.openfeature.sdk.HookContext;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.spi.LoggingEventBuilder;
/**
* A hook for logging flag evaluations.
* Useful for debugging.
* Flag evaluation data is logged at debug and error in before/after stages and error stages, respectively.
*/
@Slf4j
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
value = "RV_RETURN_VALUE_IGNORED",
justification = "we can ignore return values of chainables (builders) here")
public class LoggingHook implements Hook<Object> {
static final String DOMAIN_KEY = "domain";
static final String PROVIDER_NAME_KEY = "provider_name";
static final String FLAG_KEY_KEY = "flag_key";
static final String DEFAULT_VALUE_KEY = "default_value";
static final String EVALUATION_CONTEXT_KEY = "evaluation_context";
static final String ERROR_CODE_KEY = "error_code";
static final String ERROR_MESSAGE_KEY = "error_message";
static final String REASON_KEY = "reason";
static final String VARIANT_KEY = "variant";
static final String VALUE_KEY = "value";
private boolean includeEvaluationContext;
/**
* Construct a new LoggingHook.
*/
public LoggingHook() {
this(false);
}
/**
* Construct a new LoggingHook.
*
* @param includeEvaluationContext include a serialized evaluation context in the log message (defaults to false)
*/
public LoggingHook(boolean includeEvaluationContext) {
this.includeEvaluationContext = includeEvaluationContext;
}
@Override
public Optional<EvaluationContext> before(HookContext<Object> hookContext, Map<String, Object> hints) {
LoggingEventBuilder builder = log.atDebug();
addCommonProps(builder, hookContext);
builder.log("Before stage");
return Optional.empty();
}
@Override
public void after(
HookContext<Object> hookContext, FlagEvaluationDetails<Object> details, Map<String, Object> hints) {
LoggingEventBuilder builder = log.atDebug()
.addKeyValue(REASON_KEY, details.getReason())
.addKeyValue(VARIANT_KEY, details.getVariant())
.addKeyValue(VALUE_KEY, details.getValue());
addCommonProps(builder, hookContext);
builder.log("After stage");
}
@Override
public void error(HookContext<Object> hookContext, Exception error, Map<String, Object> hints) {
LoggingEventBuilder builder = log.atError().addKeyValue(ERROR_MESSAGE_KEY, error.getMessage());
addCommonProps(builder, hookContext);
ErrorCode errorCode = error instanceof OpenFeatureError ? ((OpenFeatureError) error).getErrorCode() : null;
builder.addKeyValue(ERROR_CODE_KEY, errorCode);
builder.log("Error stage", error);
}
private void addCommonProps(LoggingEventBuilder builder, HookContext<Object> hookContext) {
builder.addKeyValue(DOMAIN_KEY, hookContext.getClientMetadata().getDomain())
.addKeyValue(
PROVIDER_NAME_KEY, hookContext.getProviderMetadata().getName())
.addKeyValue(FLAG_KEY_KEY, hookContext.getFlagKey())
.addKeyValue(DEFAULT_VALUE_KEY, hookContext.getDefaultValue());
if (includeEvaluationContext) {
builder.addKeyValue(EVALUATION_CONTEXT_KEY, hookContext.getCtx());
}
}
}

View File

@ -2,7 +2,7 @@ package dev.openfeature.sdk.internal;
@SuppressWarnings("checkstyle:MissingJavadocType")
public interface AutoCloseableLock extends AutoCloseable {
/**
* Override the exception in AutoClosable.
*/

View File

@ -10,6 +10,7 @@ public class AutoCloseableReentrantReadWriteLock extends ReentrantReadWriteLock
/**
* Get the single write lock as an AutoCloseableLock.
*
* @return unlock method ref
*/
public AutoCloseableLock writeLockAutoCloseable() {
@ -19,10 +20,11 @@ public class AutoCloseableReentrantReadWriteLock extends ReentrantReadWriteLock
/**
* Get the multi read lock as an AutoCloseableLock.
*
* @return unlock method ref
*/
public AutoCloseableLock readLockAutoCloseable() {
this.readLock().lock();
return this.readLock()::unlock;
}
}
}

View File

@ -0,0 +1,13 @@
package dev.openfeature.sdk.internal;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* JaCoCo ignores coverage of methods annotated with any annotation with "generated" in the name.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExcludeFromGeneratedCoverageReport {}

View File

@ -1,12 +1,10 @@
package dev.openfeature.sdk.internal;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import lombok.experimental.UtilityClass;
@SuppressWarnings("checkstyle:MissingJavadocType")
@ -15,9 +13,10 @@ public class ObjectUtils {
/**
* If the source param is null, return the default value.
* @param source maybe null object
*
* @param source maybe null object
* @param defaultValue thing to use if source is null
* @param <T> list type
* @param <T> list type
* @return resulting object
*/
public static <T> List<T> defaultIfNull(List<T> source, Supplier<List<T>> defaultValue) {
@ -29,10 +28,11 @@ public class ObjectUtils {
/**
* If the source param is null, return the default value.
* @param source maybe null object
*
* @param source maybe null object
* @param defaultValue thing to use if source is null
* @param <K> map key type
* @param <V> map value type
* @param <K> map key type
* @param <V> map value type
* @return resulting map
*/
public static <K, V> Map<K, V> defaultIfNull(Map<K, V> source, Supplier<Map<K, V>> defaultValue) {
@ -44,9 +44,10 @@ public class ObjectUtils {
/**
* If the source param is null, return the default value.
* @param source maybe null object
*
* @param source maybe null object
* @param defaultValue thing to use if source is null
* @param <T> type
* @param <T> type
* @return resulting object
*/
public static <T> T defaultIfNull(T source, Supplier<T> defaultValue) {
@ -58,15 +59,17 @@ public class ObjectUtils {
/**
* Concatenate a bunch of lists.
*
* @param sources bunch of lists.
* @param <T> list type
* @param <T> list type
* @return resulting object
*/
@SafeVarargs
public static <T> List<T> merge(List<T>... sources) {
return Arrays
.stream(sources)
.flatMap(Collection::stream)
.collect(Collectors.toList());
public static <T> List<T> merge(Collection<T>... sources) {
List<T> merged = new ArrayList<>();
for (Collection<T> source : sources) {
merged.addAll(source);
}
return merged;
}
}

View File

@ -4,7 +4,7 @@ import java.util.Objects;
/**
* Like {@link java.util.function.BiConsumer} but with 3 params.
*
*
* @see java.util.function.BiConsumer
*/
@FunctionalInterface
@ -35,4 +35,4 @@ public interface TriConsumer<T, U, V> {
after.accept(t, u, v);
};
}
}
}

View File

@ -4,6 +4,7 @@ import dev.openfeature.sdk.EvaluationContext;
/**
* Context evaluator - use for resolving flag according to evaluation context, for handling targeting.
*
* @param <T> expected value type
*/
public interface ContextEvaluator<T> {

View File

@ -1,12 +1,12 @@
package dev.openfeature.sdk.providers.memory;
import dev.openfeature.sdk.ImmutableMetadata;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import java.util.Map;
/**
* Flag representation for the in-memory provider.
*/
@ -16,6 +16,8 @@ import java.util.Map;
public class Flag<T> {
@Singular
private Map<String, Object> variants;
private String defaultVariant;
private ContextEvaluator<T> contextEvaluator;
private ImmutableMetadata flagMetadata;
}

View File

@ -1,12 +1,5 @@
package dev.openfeature.sdk.providers.memory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.EventProvider;
import dev.openfeature.sdk.Metadata;
@ -15,11 +8,18 @@ import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.ProviderState;
import dev.openfeature.sdk.Reason;
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.FatalError;
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
import dev.openfeature.sdk.exceptions.GeneralError;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@ -33,7 +33,7 @@ public class InMemoryProvider extends EventProvider {
@Getter
private static final String NAME = "InMemoryProvider";
private Map<String, Flag<?>> flags;
private final Map<String, Flag<?>> flags;
@Getter
private ProviderState state = ProviderState.NOT_READY;
@ -44,11 +44,12 @@ public class InMemoryProvider extends EventProvider {
}
public InMemoryProvider(Map<String, Flag<?>> flags) {
this.flags = new HashMap<>(flags);
this.flags = new ConcurrentHashMap<>(flags);
}
/**
* Initialize the provider.
* Initializes the provider.
*
* @param evaluationContext evaluation context
* @throws Exception on error
*/
@ -60,72 +61,79 @@ public class InMemoryProvider extends EventProvider {
}
/**
* Updating provider flags configuration, replacing existing flags.
* @param flags the flags to use instead of the previous flags.
* Updates the provider flags configuration.
* For existing flags, the new configurations replace the old one.
* For new flags, they are added to the configuration.
*
* @param newFlags the new flag configurations
*/
public void updateFlags(Map<String, Flag<?>> flags) {
Set<String> flagsChanged = new HashSet<>();
flagsChanged.addAll(this.flags.keySet());
flagsChanged.addAll(flags.keySet());
this.flags = new HashMap<>(flags);
public void updateFlags(Map<String, Flag<?>> newFlags) {
Set<String> flagsChanged = new HashSet<>(newFlags.keySet());
this.flags.putAll(newFlags);
ProviderEventDetails details = ProviderEventDetails.builder()
.flagsChanged(new ArrayList<>(flagsChanged))
.message("flags changed")
.build();
.flagsChanged(new ArrayList<>(flagsChanged))
.message("flags changed")
.build();
emitProviderConfigurationChanged(details);
}
/**
* Updating provider flags configuration with adding or updating a flag.
* @param flag the flag to update. If a flag with this key already exists, new flag replaces it.
* Updates a single provider flag configuration.
* For existing flag, the new configuration replaces the old one.
* For new flag, they are added to the configuration.
*
* @param newFlag the flag to update
*/
public void updateFlag(String flagKey, Flag<?> flag) {
this.flags.put(flagKey, flag);
public void updateFlag(String flagKey, Flag<?> newFlag) {
this.flags.put(flagKey, newFlag);
ProviderEventDetails details = ProviderEventDetails.builder()
.flagsChanged(Arrays.asList(flagKey))
.message("flag added/updated")
.build();
.flagsChanged(Collections.singletonList(flagKey))
.message("flag added/updated")
.build();
emitProviderConfigurationChanged(details);
}
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue,
EvaluationContext evaluationContext) {
public ProviderEvaluation<Boolean> getBooleanEvaluation(
String key, Boolean defaultValue, EvaluationContext evaluationContext) {
return getEvaluation(key, evaluationContext, Boolean.class);
}
@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue,
EvaluationContext evaluationContext) {
public ProviderEvaluation<String> getStringEvaluation(
String key, String defaultValue, EvaluationContext evaluationContext) {
return getEvaluation(key, evaluationContext, String.class);
}
@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue,
EvaluationContext evaluationContext) {
public ProviderEvaluation<Integer> getIntegerEvaluation(
String key, Integer defaultValue, EvaluationContext evaluationContext) {
return getEvaluation(key, evaluationContext, Integer.class);
}
@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue,
EvaluationContext evaluationContext) {
public ProviderEvaluation<Double> getDoubleEvaluation(
String key, Double defaultValue, EvaluationContext evaluationContext) {
return getEvaluation(key, evaluationContext, Double.class);
}
@SneakyThrows
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue,
EvaluationContext evaluationContext) {
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext evaluationContext) {
return getEvaluation(key, evaluationContext, Value.class);
}
private <T> ProviderEvaluation<T> getEvaluation(
String key, EvaluationContext evaluationContext, Class<?> expectedType
) throws OpenFeatureError {
String key, EvaluationContext evaluationContext, Class<?> expectedType) throws OpenFeatureError {
if (!ProviderState.READY.equals(state)) {
if (ProviderState.NOT_READY.equals(state)) {
throw new ProviderNotReadyError("provider not yet initialized");
}
if (ProviderState.FATAL.equals(state)) {
throw new FatalError("provider in fatal error state");
}
throw new GeneralError("unknown error");
}
Flag<?> flag = flags.get(key);
@ -141,10 +149,10 @@ public class InMemoryProvider extends EventProvider {
value = (T) flag.getVariants().get(flag.getDefaultVariant());
}
return ProviderEvaluation.<T>builder()
.value(value)
.variant(flag.getDefaultVariant())
.reason(Reason.STATIC.toString())
.build();
.value(value)
.variant(flag.getDefaultVariant())
.reason(Reason.STATIC.toString())
.flagMetadata(flag.getFlagMetadata())
.build();
}
}

View File

@ -0,0 +1,52 @@
package dev.openfeature.sdk;
public class AlwaysBrokenWithDetailsProvider implements FeatureProvider {
private final String name = "always broken with details";
@Override
public Metadata getMetadata() {
return () -> name;
}
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
return ProviderEvaluation.<Boolean>builder()
.errorMessage(TestConstants.BROKEN_MESSAGE)
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
}
@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
return ProviderEvaluation.<String>builder()
.errorMessage(TestConstants.BROKEN_MESSAGE)
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
}
@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
return ProviderEvaluation.<Integer>builder()
.errorMessage(TestConstants.BROKEN_MESSAGE)
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
}
@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
return ProviderEvaluation.<Double>builder()
.errorMessage(TestConstants.BROKEN_MESSAGE)
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext invocationContext) {
return ProviderEvaluation.<Value>builder()
.errorMessage(TestConstants.BROKEN_MESSAGE)
.errorCode(ErrorCode.FLAG_NOT_FOUND)
.build();
}
}

View File

@ -2,13 +2,13 @@ package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
public class AlwaysBrokenProvider implements FeatureProvider {
public class AlwaysBrokenWithExceptionProvider implements FeatureProvider {
private final String name = "always broken";
@Override
public Metadata getMetadata() {
return () -> {
throw new FlagNotFoundError(TestConstants.BROKEN_MESSAGE);
};
return () -> name;
}
@Override
@ -32,7 +32,8 @@ public class AlwaysBrokenProvider implements FeatureProvider {
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext invocationContext) {
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext invocationContext) {
throw new FlagNotFoundError(TestConstants.BROKEN_MESSAGE);
}
}

View File

@ -0,0 +1,75 @@
package dev.openfeature.sdk;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
@Timeout(value = 5, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
class AwaitableTest {
@Test
void waitingForFinishedIsANoOp() {
var startTime = System.currentTimeMillis();
Awaitable.FINISHED.await();
var endTime = System.currentTimeMillis();
assertTrue(endTime - startTime < 10);
}
@Test
void waitingForNotFinishedWaitsEvenWhenInterrupted() throws InterruptedException {
var awaitable = new Awaitable();
var mayProceed = new AtomicBoolean(false);
var thread = new Thread(() -> {
awaitable.await();
if (!mayProceed.get()) {
fail();
}
});
thread.start();
var startTime = System.currentTimeMillis();
do {
thread.interrupt();
} while (startTime + 1000 > System.currentTimeMillis());
mayProceed.set(true);
awaitable.wakeup();
thread.join();
}
@Test
void callingWakeUpWakesUpAllWaitingThreads() throws InterruptedException {
var awaitable = new Awaitable();
var isRunning = new AtomicInteger();
Runnable runnable = () -> {
isRunning.incrementAndGet();
var start = System.currentTimeMillis();
awaitable.await();
var end = System.currentTimeMillis();
if (end - start > 10) {
fail();
}
};
var numThreads = 2;
var threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
threads[i] = new Thread(runnable);
threads[i].start();
}
await().atMost(1, TimeUnit.SECONDS).until(() -> isRunning.get() == numThreads);
awaitable.wakeup();
for (int i = 0; i < numThreads; i++) {
threads[i].join();
}
}
}

View File

@ -1,18 +1,17 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.testutils.FeatureProviderTestUtils;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class ClientProviderMappingTest {
@Test
void clientProviderTest() {
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
OpenFeatureAPI api = new OpenFeatureAPI();
FeatureProviderTestUtils.setFeatureProvider("client1", new DoSomethingProvider());
FeatureProviderTestUtils.setFeatureProvider("client2", new NoOpProvider());
api.setProviderAndWait("client1", new DoSomethingProvider());
api.setProviderAndWait("client2", new NoOpProvider());
Client c1 = api.getClient("client1");
Client c2 = api.getClient("client2");

View File

@ -1,57 +1,67 @@
package dev.openfeature.sdk;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import dev.openfeature.sdk.fixtures.HookFixtures;
import dev.openfeature.sdk.testutils.TestEventsProvider;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import dev.openfeature.sdk.testutils.FeatureProviderTestUtils;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import dev.openfeature.sdk.fixtures.HookFixtures;
class DeveloperExperienceTest implements HookFixtures {
transient String flagKey = "mykey";
private OpenFeatureAPI api;
@Test void simpleBooleanFlag() {
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProvider(new NoOpProvider());
@BeforeEach
public void setUp() throws Exception {
api = new OpenFeatureAPI();
}
@Test
void simpleBooleanFlag() {
api.setProviderAndWait(new TestEventsProvider());
Client client = api.getClient();
Boolean retval = client.getBooleanValue(flagKey, false);
assertFalse(retval);
}
@Test void clientHooks() {
@Test
void clientHooks() {
Hook<Boolean> exampleHook = mockBooleanHook();
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProvider(new NoOpProvider());
api.setProviderAndWait(new TestEventsProvider());
Client client = api.getClient();
client.addHooks(exampleHook);
Boolean retval = client.getBooleanValue(flagKey, false);
verify(exampleHook, times(1)).finallyAfter(any(), any());
verify(exampleHook, times(1)).finallyAfter(any(), any(), any());
assertFalse(retval);
}
@Test void evalHooks() {
@Test
void evalHooks() {
Hook<Boolean> clientHook = mockBooleanHook();
Hook<Boolean> evalHook = mockBooleanHook();
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProvider(new NoOpProvider());
api.setProviderAndWait(new TestEventsProvider());
Client client = api.getClient();
client.addHooks(clientHook);
Boolean retval = client.getBooleanValue(flagKey, false, null,
Boolean retval = client.getBooleanValue(
flagKey,
false,
null,
FlagEvaluationOptions.builder().hook(evalHook).build());
verify(clientHook, times(1)).finallyAfter(any(), any());
verify(evalHook, times(1)).finallyAfter(any(), any());
verify(clientHook, times(1)).finallyAfter(any(), any(), any());
verify(evalHook, times(1)).finallyAfter(any(), any(), any());
assertFalse(retval);
}
@ -59,10 +69,10 @@ class DeveloperExperienceTest implements HookFixtures {
* As an application author, you probably know special things about your users. You can communicate these to the
* provider via {@link MutableContext}
*/
@Test void providingContext() {
@Test
void providingContext() {
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProvider(new NoOpProvider());
api.setProviderAndWait(new TestEventsProvider());
Client client = api.getClient();
Map<String, Value> attributes = new HashMap<>();
List<Value> values = Arrays.asList(new Value(2), new Value(4));
@ -76,9 +86,9 @@ class DeveloperExperienceTest implements HookFixtures {
assertFalse(retval);
}
@Test void brokenProvider() {
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider());
@Test
void brokenProvider() {
api.setProviderAndWait(new AlwaysBrokenWithExceptionProvider());
Client client = api.getClient();
FlagEvaluationDetails<Boolean> retval = client.getBooleanDetails(flagKey, false);
assertEquals(ErrorCode.FLAG_NOT_FOUND, retval.getErrorCode());
@ -90,20 +100,24 @@ class DeveloperExperienceTest implements HookFixtures {
@Test
void providerLockedPerTransaction() {
final String defaultValue = "string-value";
final OpenFeatureAPI api = new OpenFeatureAPI();
class MutatingHook implements Hook {
@Override
@SneakyThrows
// change the provider during a before hook - this should not impact the evaluation in progress
public Optional before(HookContext ctx, Map hints) {
FeatureProviderTestUtils.setFeatureProvider(new NoOpProvider());
api.setProviderAndWait(TestEventsProvider.newInitializedTestEventsProvider());
return Optional.empty();
}
}
final String defaultValue = "string-value";
final OpenFeatureAPI api = OpenFeatureAPI.getInstance();
final Client client = api.getClient();
FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider());
api.setProviderAndWait(new DoSomethingProvider());
api.addHooks(new MutatingHook());
// if provider is changed during an evaluation transaction it should proceed with the original provider
@ -111,9 +125,64 @@ class DeveloperExperienceTest implements HookFixtures {
assertEquals(new StringBuilder(defaultValue).reverse().toString(), doSomethingValue);
api.clearHooks();
// subsequent evaluations should now use new provider set by hook
String noOpValue = client.getStringValue("val", defaultValue);
assertEquals(noOpValue, defaultValue);
}
@Test
void setProviderAndWaitShouldPutTheProviderInReadyState() {
String domain = "domain";
api.setProviderAndWait(domain, new TestEventsProvider());
Client client = api.getClient(domain);
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
}
@Specification(
number = "5.3.5",
text =
"If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
@Test
void shouldPutTheProviderInStateErrorAfterEmittingErrorEvent() {
String domain = "domain";
TestEventsProvider provider = new TestEventsProvider();
api.setProviderAndWait(domain, provider);
Client client = api.getClient(domain);
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
provider.emitProviderError(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.ERROR);
}
@Specification(
number = "5.3.5",
text =
"If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
@Test
void shouldPutTheProviderInStateStaleAfterEmittingStaleEvent() {
String domain = "domain";
TestEventsProvider provider = new TestEventsProvider();
api.setProviderAndWait(domain, provider);
Client client = api.getClient(domain);
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
provider.emitProviderStale(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
}
@Specification(
number = "5.3.5",
text =
"If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
@Test
void shouldPutTheProviderInStateReadyAfterEmittingReadyEvent() {
String domain = "domain";
TestEventsProvider provider = new TestEventsProvider();
api.setProviderAndWait(domain, provider);
Client client = api.getClient(domain);
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
provider.emitProviderStale(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
provider.emitProviderReady(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
}
}

View File

@ -4,7 +4,8 @@ class DoSomethingProvider implements FeatureProvider {
static final String name = "Something";
// Flag evaluation metadata
static final ImmutableMetadata DEFAULT_METADATA = ImmutableMetadata.builder().build();
static final ImmutableMetadata DEFAULT_METADATA =
ImmutableMetadata.builder().build();
private ImmutableMetadata flagMetadata;
public DoSomethingProvider() {
@ -53,7 +54,8 @@ class DoSomethingProvider implements FeatureProvider {
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext invocationContext) {
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext invocationContext) {
return ProviderEvaluation.<Value>builder()
.value(null)
.flagMetadata(flagMetadata)

View File

@ -1,6 +1,7 @@
package dev.openfeature.sdk;
import org.junit.jupiter.api.Test;
import static dev.openfeature.sdk.EvaluationContext.TARGETING_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@ -8,23 +9,26 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static dev.openfeature.sdk.EvaluationContext.TARGETING_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class EvalContextTest {
@Specification(number="3.1.1",
text="The `evaluation context` structure **MUST** define an optional `targeting key` field of " +
"type string, identifying the subject of the flag evaluation.")
@Test void requires_targeting_key() {
@Specification(
number = "3.1.1",
text = "The `evaluation context` structure **MUST** define an optional `targeting key` field of "
+ "type string, identifying the subject of the flag evaluation.")
@Test
void requires_targeting_key() {
EvaluationContext ec = new ImmutableContext("targeting-key", new HashMap<>());
assertEquals("targeting-key", ec.getTargetingKey());
}
@Specification(number="3.1.2", text= "The evaluation context MUST support the inclusion of " +
"custom fields, having keys of type `string`, and " +
"values of type `boolean | string | number | datetime | structure`.")
@Test void eval_context() {
@Specification(
number = "3.1.2",
text = "The evaluation context MUST support the inclusion of "
+ "custom fields, having keys of type `string`, and "
+ "values of type `boolean | string | number | datetime | structure`.")
@Test
void eval_context() {
Map<String, Value> attributes = new HashMap<>();
Instant dt = Instant.now().truncatedTo(ChronoUnit.MILLIS);
attributes.put("str", new Value("test"));
@ -42,16 +46,21 @@ public class EvalContextTest {
assertEquals(dt, ec.getValue("dt").asInstant().truncatedTo(ChronoUnit.MILLIS));
}
@Specification(number="3.1.2", text="The evaluation context MUST support the inclusion of " +
"custom fields, having keys of type `string`, and " +
"values of type `boolean | string | number | datetime | structure`.")
@Test void eval_context_structure_array() {
@Specification(
number = "3.1.2",
text = "The evaluation context MUST support the inclusion of "
+ "custom fields, having keys of type `string`, and "
+ "values of type `boolean | string | number | datetime | structure`.")
@Test
void eval_context_structure_array() {
Map<String, Value> attributes = new HashMap<>();
attributes.put("obj", new Value(new MutableStructure().add("val1", 1).add("val2", "2")));
List<Value> values = new ArrayList<Value>(){{
add(new Value("one"));
add(new Value("two"));
}};
List<Value> values = new ArrayList<Value>() {
{
add(new Value("one"));
add(new Value("two"));
}
};
attributes.put("arr", new Value(values));
EvaluationContext ec = new ImmutableContext(attributes);
@ -64,11 +73,16 @@ public class EvalContextTest {
assertEquals("two", arr.get(1).asString());
}
@Specification(number="3.1.3", text="The evaluation context MUST support fetching the custom fields by key and also fetching all key value pairs.")
@Test void fetch_all() {
Map<String, Value> attributes = new HashMap<>();
@Specification(
number = "3.1.3",
text =
"The evaluation context MUST support fetching the custom fields by key and also fetching all key value pairs.")
@Test
void fetch_all() {
Map<String, Value> attributes = new HashMap<>();
Instant dt = Instant.now();
MutableStructure mutableStructure = new MutableStructure().add("val1", 1).add("val2", "2");
MutableStructure mutableStructure =
new MutableStructure().add("val1", 1).add("val2", "2");
attributes.put("str", new Value("test"));
attributes.put("str2", new Value("test2"));
attributes.put("bool", new Value(true));
@ -96,8 +110,9 @@ public class EvalContextTest {
assertEquals("2", foundObj.getValue("val2").asString());
}
@Specification(number="3.1.4", text="The evaluation context fields MUST have an unique key.")
@Test void unique_key_across_types() {
@Specification(number = "3.1.4", text = "The evaluation context fields MUST have an unique key.")
@Test
void unique_key_across_types() {
MutableContext ec = new MutableContext();
ec.add("key", "val");
ec.add("key", "val2");
@ -107,8 +122,9 @@ public class EvalContextTest {
assertEquals(3, ec.getValue("key").asInteger());
}
@Test void unique_key_across_types_immutableContext() {
HashMap<String, Value> attributes = new HashMap<>();
@Test
void unique_key_across_types_immutableContext() {
HashMap<String, Value> attributes = new HashMap<>();
attributes.put("key", new Value("val"));
attributes.put("key", new Value("val2"));
attributes.put("key", new Value(3));
@ -117,23 +133,23 @@ public class EvalContextTest {
assertEquals(3, ec.getValue("key").asInteger());
}
@Test void can_chain_attribute_addition() {
@Test
void can_chain_attribute_addition() {
MutableContext ec = new MutableContext();
MutableContext out = ec.add("str", "test")
.add("int", 4)
.add("bool", false)
.add("str", new MutableStructure());
MutableContext out =
ec.add("str", "test").add("int", 4).add("bool", false).add("str", new MutableStructure());
assertEquals(MutableContext.class, out.getClass());
}
@Test void can_add_key_with_null() {
@Test
void can_add_key_with_null() {
MutableContext ec = new MutableContext()
.add("Boolean", (Boolean)null)
.add("String", (String)null)
.add("Double", (Double)null)
.add("Structure", (MutableStructure)null)
.add("List", (List<Value>)null)
.add("Instant", (Instant)null);
.add("Boolean", (Boolean) null)
.add("String", (String) null)
.add("Double", (Double) null)
.add("Structure", (MutableStructure) null)
.add("List", (List<Value>) null)
.add("Instant", (Instant) null);
assertEquals(6, ec.asMap().size());
assertEquals(null, ec.getValue("Boolean").asBoolean());
assertEquals(null, ec.getValue("String").asString());
@ -143,7 +159,8 @@ public class EvalContextTest {
assertEquals(null, ec.getValue("Instant").asString());
}
@Test void Immutable_context_merge_targeting_key() {
@Test
void Immutable_context_merge_targeting_key() {
String key1 = "key1";
EvaluationContext ctx1 = new ImmutableContext(key1, new HashMap<>());
EvaluationContext ctx2 = new ImmutableContext(new HashMap<>());
@ -156,19 +173,21 @@ public class EvalContextTest {
ctxMerged = ctx1.merge(ctx2);
assertEquals(key2, ctxMerged.getTargetingKey());
ctx2 = new ImmutableContext(" ",new HashMap<>());
ctx2 = new ImmutableContext(" ", new HashMap<>());
ctxMerged = ctx1.merge(ctx2);
assertEquals(key1, ctxMerged.getTargetingKey());
}
@Test void merge_null_returns_value() {
@Test
void merge_null_returns_value() {
MutableContext ctx1 = new MutableContext("key");
ctx1.add("mything", "value");
EvaluationContext result = ctx1.merge(null);
assertEquals(ctx1, result);
}
@Test void merge_targeting_key() {
@Test
void merge_targeting_key() {
String key1 = "key1";
MutableContext ctx1 = new MutableContext(key1);
MutableContext ctx2 = new MutableContext();
@ -186,14 +205,15 @@ public class EvalContextTest {
assertEquals(key2, ctxMerged.getTargetingKey());
}
@Test void asObjectMap() {
@Test
void asObjectMap() {
String key1 = "key1";
MutableContext ctx = new MutableContext(key1);
ctx.add("stringItem", "stringValue");
ctx.add("boolItem", false);
ctx.add("integerItem", 1);
ctx.add("doubleItem", 1.2);
ctx.add("instantItem", Instant.ofEpochSecond(1663331342));
ctx.add("instantItem", Instant.ofEpochSecond(1663331342));
List<Value> listItem = new ArrayList<>();
listItem.add(new Value("item1"));
listItem.add(new Value("item2"));
@ -207,18 +227,17 @@ public class EvalContextTest {
structureValue.put("structBoolItem", new Value(false));
structureValue.put("structIntegerItem", new Value(1));
structureValue.put("structDoubleItem", new Value(1.2));
structureValue.put("structInstantItem", new Value(Instant.ofEpochSecond(1663331342)));
structureValue.put("structInstantItem", new Value(Instant.ofEpochSecond(1663331342)));
Structure structure = new MutableStructure(structureValue);
ctx.add("structureItem", structure);
Map<String, Object> want = new HashMap<>();
want.put(TARGETING_KEY, key1);
want.put("stringItem", "stringValue");
want.put("boolItem", false);
want.put("integerItem", 1);
want.put("doubleItem", 1.2);
want.put("instantItem", Instant.ofEpochSecond(1663331342));
want.put("instantItem", Instant.ofEpochSecond(1663331342));
List<String> wantListItem = new ArrayList<>();
wantListItem.add("item1");
wantListItem.add("item2");
@ -232,9 +251,9 @@ public class EvalContextTest {
wantStructureValue.put("structBoolItem", false);
wantStructureValue.put("structIntegerItem", 1);
wantStructureValue.put("structDoubleItem", 1.2);
wantStructureValue.put("structInstantItem", Instant.ofEpochSecond(1663331342));
want.put("structureItem",wantStructureValue);
wantStructureValue.put("structInstantItem", Instant.ofEpochSecond(1663331342));
want.put("structureItem", wantStructureValue);
assertEquals(want,ctx.asObjectMap());
assertEquals(want, ctx.asObjectMap());
}
}

View File

@ -2,22 +2,39 @@ package dev.openfeature.sdk;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import dev.openfeature.sdk.internal.TriConsumer;
import dev.openfeature.sdk.testutils.TestStackedEmitCallsProvider;
import io.cucumber.java.AfterAll;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
class EventProviderTest {
private static final int TIMEOUT = 300;
private TestEventProvider eventProvider;
@BeforeEach
@SneakyThrows
void setup() {
eventProvider = new TestEventProvider();
eventProvider.initialize(null);
}
@AfterAll
public static void resetDefaultProvider() {
new OpenFeatureAPI().setProviderAndWait(new NoOpProvider());
}
@Test
@Timeout(value = 2, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@DisplayName("should run attached onEmit with emitters")
void emitsEventsWhenAttached() {
TestEventProvider eventProvider = new TestEventProvider();
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit = mockOnEmit();
eventProvider.attach(onEmit);
@ -28,17 +45,15 @@ class EventProviderTest {
eventProvider.emitProviderStale(details);
eventProvider.emitProviderError(details);
verify(onEmit, times(2)).accept(eventProvider, ProviderEvent.PROVIDER_READY, details);
verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_STALE, details);
verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_ERROR, details);
verify(onEmit, timeout(TIMEOUT).times(2)).accept(eventProvider, ProviderEvent.PROVIDER_READY, details);
verify(onEmit, timeout(TIMEOUT)).accept(eventProvider, ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
verify(onEmit, timeout(TIMEOUT)).accept(eventProvider, ProviderEvent.PROVIDER_STALE, details);
verify(onEmit, timeout(TIMEOUT)).accept(eventProvider, ProviderEvent.PROVIDER_ERROR, details);
}
@Test
@DisplayName("should do nothing with emitters if no onEmit attached")
void doesNotEmitsEventsWhenNotAttached() {
TestEventProvider eventProvider = new TestEventProvider();
// don't attach this emitter
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit = mockOnEmit();
@ -56,26 +71,31 @@ class EventProviderTest {
@Test
@DisplayName("should throw if second different onEmit attached")
void throwsWhenOnEmitDifferent() {
TestEventProvider eventProvider = new TestEventProvider();
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit1 = mockOnEmit();
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit2 = mockOnEmit();
eventProvider.attach(onEmit1);
assertThrows(IllegalStateException.class, () -> eventProvider.attach(onEmit2));
}
@Test
@DisplayName("should not throw if second same onEmit attached")
void doesNotThrowWhenOnEmitSame() {
TestEventProvider eventProvider = new TestEventProvider();
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit1 = mockOnEmit();
TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit2 = onEmit1;
eventProvider.attach(onEmit1);
eventProvider.attach(onEmit2); // should not throw, same instance. noop
}
@Test
@SneakyThrows
@Timeout(value = 2, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@DisplayName("should not deadlock on emit called during emit")
void doesNotDeadlockOnEmitStackedCalls() {
TestStackedEmitCallsProvider provider = new TestStackedEmitCallsProvider();
new OpenFeatureAPI().setProviderAndWait(provider);
}
class TestEventProvider extends EventProvider {
static class TestEventProvider extends EventProvider {
private static final String NAME = "TestEventProvider";
@ -85,48 +105,40 @@ class EventProviderTest {
}
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue,
EvaluationContext ctx) {
// TODO Auto-generated method stub
public ProviderEvaluation<Boolean> getBooleanEvaluation(
String key, Boolean defaultValue, EvaluationContext ctx) {
throw new UnsupportedOperationException("Unimplemented method 'getBooleanEvaluation'");
}
@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue,
EvaluationContext ctx) {
// TODO Auto-generated method stub
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
throw new UnsupportedOperationException("Unimplemented method 'getStringEvaluation'");
}
@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue,
EvaluationContext ctx) {
// TODO Auto-generated method stub
public ProviderEvaluation<Integer> getIntegerEvaluation(
String key, Integer defaultValue, EvaluationContext ctx) {
throw new UnsupportedOperationException("Unimplemented method 'getIntegerEvaluation'");
}
@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue,
EvaluationContext ctx) {
// TODO Auto-generated method stub
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
throw new UnsupportedOperationException("Unimplemented method 'getDoubleEvaluation'");
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue,
EvaluationContext ctx) {
// TODO Auto-generated method stub
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
throw new UnsupportedOperationException("Unimplemented method 'getObjectEvaluation'");
}
@Override
public ProviderState getState() {
return ProviderState.READY;
public void attach(TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit) {
super.attach(onEmit);
}
}
@SuppressWarnings("unchecked")
private TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> mockOnEmit() {
return (TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails>)mock(TriConsumer.class);
return (TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails>) mock(TriConsumer.class);
}
}
}

View File

@ -1,35 +1,31 @@
package dev.openfeature.sdk;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.*;
import dev.openfeature.sdk.testutils.TestEventsProvider;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatcher;
import dev.openfeature.sdk.testutils.TestEventsProvider;
import io.cucumber.java.AfterAll;
class EventsTest {
private static final int TIMEOUT = 300;
private static final int TIMEOUT = 500;
private static final int INIT_DELAY = TIMEOUT / 2;
private OpenFeatureAPI api;
@AfterAll
public static void resetDefaultProvider() {
OpenFeatureAPI.getInstance().setProvider(new NoOpProvider());
@BeforeEach
void setUp() {
api = new OpenFeatureAPI();
}
@Nested
@ -45,31 +41,34 @@ class EventsTest {
@Test
@DisplayName("should fire initial READY event when provider init succeeds")
@Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally," +
" PROVIDER_READY handlers MUST run.")
@Specification(
number = "5.3.1",
text = "If the provider's initialize function terminates normally,"
+ " PROVIDER_READY handlers MUST run.")
void apiInitReady() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "apiInitReady";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().onProviderReady(handler);
OpenFeatureAPI.getInstance().setProvider(name, provider);
verify(handler, timeout(TIMEOUT).atLeastOnce())
.accept(any());
api.onProviderReady(handler);
api.setProviderAndWait(name, provider);
verify(handler, timeout(TIMEOUT).atLeastOnce()).accept(any());
}
@Test
@DisplayName("should fire initial ERROR event when provider init errors")
@Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally," +
" PROVIDER_ERROR handlers MUST run.")
@Specification(
number = "5.3.2",
text = "If the provider's initialize function terminates abnormally,"
+ " PROVIDER_ERROR handlers MUST run.")
void apiInitError() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "apiInitError";
final String errMessage = "oh no!";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage);
OpenFeatureAPI.getInstance().onProviderError(handler);
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.onProviderError(handler);
api.setProvider(name, provider);
verify(handler, timeout(TIMEOUT)).accept(argThat(details -> {
return errMessage.equals(details.getMessage());
}));
@ -82,29 +81,36 @@ class EventsTest {
@Test
@DisplayName("should propagate events")
@Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, "
+
"the associated client and API event handlers MUST run.")
@Specification(
number = "5.1.2",
text = "When a provider signals the occurrence of a particular event, "
+ "the associated client and API event handlers MUST run.")
void apiShouldPropagateEvents() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "apiShouldPropagateEvents";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler);
api.setProviderAndWait(name, provider);
api.onProviderConfigurationChanged(handler);
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build());
provider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
EventDetails.builder().build());
verify(handler, timeout(TIMEOUT)).accept(any());
}
@Test
@DisplayName("should support all event types")
@Specification(number = "5.1.1", text = "The provider MAY define a mechanism for signaling the occurrence "
+ "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, "
+ "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.")
@Specification(number = "5.2.2", text = "The API MUST provide a function for associating handler functions"
+
" with a particular provider event type.")
@Specification(
number = "5.1.1",
text =
"The provider MAY define a mechanism for signaling the occurrence "
+ "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, "
+ "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.")
@Specification(
number = "5.2.2",
text = "The API MUST provide a function for associating handler functions"
+ " with a particular provider event type.")
void apiShouldSupportAllEventTypes() {
final String name = "apiShouldSupportAllEventTypes";
final Consumer<EventDetails> handler1 = mockHandler();
@ -113,15 +119,16 @@ class EventsTest {
final Consumer<EventDetails> handler4 = mockHandler();
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.setProviderAndWait(name, provider);
OpenFeatureAPI.getInstance().onProviderReady(handler1);
OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler2);
OpenFeatureAPI.getInstance().onProviderStale(handler3);
OpenFeatureAPI.getInstance().onProviderError(handler4);
api.onProviderReady(handler1);
api.onProviderConfigurationChanged(handler2);
api.onProviderStale(handler3);
api.onProviderError(handler4);
Arrays.asList(ProviderEvent.values()).stream().forEach(eventType -> {
provider.mockEvent(eventType, ProviderEventDetails.builder().build());
provider.mockEvent(
eventType, ProviderEventDetails.builder().build());
});
verify(handler1, timeout(TIMEOUT).atLeastOnce()).accept(any());
@ -147,34 +154,42 @@ class EventsTest {
@Test
@DisplayName("should propagate events for default provider and anonymous client")
@Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
@Specification(
number = "5.1.2",
text =
"When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
void shouldPropagateDefaultAndAnon() {
final Consumer<EventDetails> handler = mockHandler();
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
// set provider before getting a client
OpenFeatureAPI.getInstance().setProvider(provider);
Client client = OpenFeatureAPI.getInstance().getClient();
api.setProviderAndWait(provider);
Client client = api.getClient();
client.onProviderStale(handler);
provider.mockEvent(ProviderEvent.PROVIDER_STALE, EventDetails.builder().build());
provider.mockEvent(
ProviderEvent.PROVIDER_STALE, EventDetails.builder().build());
verify(handler, timeout(TIMEOUT)).accept(any());
}
@Test
@DisplayName("should propagate events for default provider and named client")
@Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
@Specification(
number = "5.1.2",
text =
"When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
void shouldPropagateDefaultAndNamed() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "shouldPropagateDefaultAndNamed";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
// set provider before getting a client
OpenFeatureAPI.getInstance().setProvider(provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(provider);
Client client = api.getClient(name);
client.onProviderStale(handler);
provider.mockEvent(ProviderEvent.PROVIDER_STALE, EventDetails.builder().build());
provider.mockEvent(
ProviderEvent.PROVIDER_STALE, EventDetails.builder().build());
verify(handler, timeout(TIMEOUT)).accept(any());
}
}
@ -190,31 +205,37 @@ class EventsTest {
class Initialization {
@Test
@DisplayName("should fire initial READY event when provider init succeeds after client retrieved")
@Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.")
@Specification(
number = "5.3.1",
text =
"If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.")
void initReadyProviderBefore() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "initReadyProviderBefore";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderReady(handler);
// set provider after getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.setProviderAndWait(name, provider);
verify(handler, timeout(TIMEOUT).atLeastOnce())
.accept(argThat(details -> details.getDomain().equals(name)));
}
@Test
@DisplayName("should fire initial READY event when provider init succeeds before client retrieved")
@Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.")
@Specification(
number = "5.3.1",
text =
"If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.")
void initReadyProviderAfter() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "initReadyProviderAfter";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
// set provider before getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider);
Client client = api.getClient(name);
client.onProviderReady(handler);
verify(handler, timeout(TIMEOUT).atLeastOnce())
.accept(argThat(details -> details.getDomain().equals(name)));
@ -222,26 +243,31 @@ class EventsTest {
@Test
@DisplayName("should fire initial ERROR event when provider init errors after client retrieved")
@Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.")
@Specification(
number = "5.3.2",
text =
"If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.")
void initErrorProviderAfter() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "initErrorProviderAfter";
final String errMessage = "oh no!";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage);
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderError(handler);
// set provider after getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.setProvider(name, provider);
verify(handler, timeout(TIMEOUT)).accept(argThat(details -> {
return name.equals(details.getDomain())
&& errMessage.equals(details.getMessage());
return name.equals(details.getDomain()) && errMessage.equals(details.getMessage());
}));
}
@Test
@DisplayName("should fire initial ERROR event when provider init errors before client retrieved")
@Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.")
@Specification(
number = "5.3.2",
text =
"If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.")
void initErrorProviderBefore() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "initErrorProviderBefore";
@ -249,12 +275,11 @@ class EventsTest {
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage);
// set provider after getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProvider(name, provider);
Client client = api.getClient(name);
client.onProviderError(handler);
verify(handler, timeout(TIMEOUT)).accept(argThat(details -> {
return name.equals(details.getDomain())
&& errMessage.equals(details.getMessage());
return name.equals(details.getDomain()) && errMessage.equals(details.getMessage());
}));
}
}
@ -265,47 +290,63 @@ class EventsTest {
@Test
@DisplayName("should propagate events when provider set before client retrieved")
@Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
@Specification(
number = "5.1.2",
text =
"When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
void shouldPropagateBefore() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "shouldPropagateBefore";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
// set provider before getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider);
Client client = api.getClient(name);
client.onProviderConfigurationChanged(handler);
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build());
verify(handler, timeout(TIMEOUT)).accept(argThat(details -> details.getDomain().equals(name)));
provider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
EventDetails.builder().build());
verify(handler, timeout(TIMEOUT))
.accept(argThat(details -> details.getDomain().equals(name)));
}
@Test
@DisplayName("should propagate events when provider set after client retrieved")
@Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
@Specification(
number = "5.1.2",
text =
"When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.")
void shouldPropagateAfter() {
final Consumer<EventDetails> handler = mockHandler();
final String name = "shouldPropagateAfter";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderConfigurationChanged(handler);
// set provider after getting a client
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.setProviderAndWait(name, provider);
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build());
verify(handler, timeout(TIMEOUT)).accept(argThat(details -> details.getDomain().equals(name)));
provider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
EventDetails.builder().build());
verify(handler, timeout(TIMEOUT))
.accept(argThat(details -> details.getDomain().equals(name)));
}
@Test
@DisplayName("should support all event types")
@Specification(number = "5.1.1", text = "The provider MAY define a mechanism for signaling the occurrence "
+ "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, "
+ "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.")
@Specification(number = "5.2.1", text = "The client MUST provide a function for associating handler functions"
+
" with a particular provider event type.")
@Specification(
number = "5.1.1",
text =
"The provider MAY define a mechanism for signaling the occurrence "
+ "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, "
+ "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.")
@Specification(
number = "5.2.1",
text = "The client MUST provide a function for associating handler functions"
+ " with a particular provider event type.")
void shouldSupportAllEventTypes() {
final String name = "shouldSupportAllEventTypes";
final Consumer<EventDetails> handler1 = mockHandler();
@ -314,8 +355,8 @@ class EventsTest {
final Consumer<EventDetails> handler4 = mockHandler();
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider);
Client client = api.getClient(name);
client.onProviderReady(handler1);
client.onProviderConfigurationChanged(handler2);
@ -325,8 +366,8 @@ class EventsTest {
Arrays.asList(ProviderEvent.values()).stream().forEach(eventType -> {
provider.mockEvent(eventType, ProviderEventDetails.builder().build());
});
ArgumentMatcher<EventDetails> nameMatches = (EventDetails details) -> details.getDomain()
.equals(name);
ArgumentMatcher<EventDetails> nameMatches =
(EventDetails details) -> details.getDomain().equals(name);
verify(handler1, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches));
verify(handler2, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches));
verify(handler3, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches));
@ -337,27 +378,29 @@ class EventsTest {
@Test
@DisplayName("shutdown provider should not run handlers")
void shouldNotRunHandlers() {
void shouldNotRunHandlers() {
final Consumer<EventDetails> handler1 = mockHandler();
final Consumer<EventDetails> handler2 = mockHandler();
final String name = "shouldNotRunHandlers";
TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY);
TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider1);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider1);
Client client = api.getClient(name);
// attached handlers
OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler1);
api.onProviderConfigurationChanged(handler1);
client.onProviderConfigurationChanged(handler2);
OpenFeatureAPI.getInstance().setProvider(name, provider2);
api.setProviderAndWait(name, provider2);
// wait for the new provider to be ready and make sure things are cleaned up.
await().until(() -> provider1.isShutDown());
// fire old event
provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build());
provider1.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
EventDetails.builder().build());
// a bit of waiting here, but we want to make sure these are indeed never
// called.
@ -367,8 +410,10 @@ class EventsTest {
@Test
@DisplayName("other client handlers should not run")
@Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " +
"event handlers on clients which are not associated with that provider MUST NOT run.")
@Specification(
number = "5.1.3",
text = "When a provider signals the occurrence of a particular event, "
+ "event handlers on clients which are not associated with that provider MUST NOT run.")
void otherClientHandlersShouldNotRun() {
final String name1 = "otherClientHandlersShouldNotRun1";
final String name2 = "otherClientHandlersShouldNotRun2";
@ -377,16 +422,18 @@ class EventsTest {
TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY);
TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name1, provider1);
OpenFeatureAPI.getInstance().setProvider(name2, provider2);
api.setProviderAndWait(name1, provider1);
api.setProviderAndWait(name2, provider2);
Client client1 = OpenFeatureAPI.getInstance().getClient(name1);
Client client2 = OpenFeatureAPI.getInstance().getClient(name2);
Client client1 = api.getClient(name1);
Client client2 = api.getClient(name2);
client1.onProviderConfigurationChanged(handlerToRun);
client2.onProviderConfigurationChanged(handlerNotToRun);
provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
provider1.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
verify(handlerToRun, timeout(TIMEOUT)).accept(any());
verify(handlerNotToRun, never()).accept(any());
@ -394,57 +441,67 @@ class EventsTest {
@Test
@DisplayName("bound named client handlers should not run with default")
@Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " +
"event handlers on clients which are not associated with that provider MUST NOT run.")
@Specification(
number = "5.1.3",
text = "When a provider signals the occurrence of a particular event, "
+ "event handlers on clients which are not associated with that provider MUST NOT run.")
void boundShouldNotRunWithDefault() {
final String name = "boundShouldNotRunWithDefault";
final Consumer<EventDetails> handlerNotToRun = mockHandler();
TestEventsProvider namedProvider = new TestEventsProvider(INIT_DELAY);
TestEventsProvider defaultProvider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(defaultProvider);
api.setProviderAndWait(defaultProvider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderConfigurationChanged(handlerNotToRun);
OpenFeatureAPI.getInstance().setProvider(name, namedProvider);
api.setProviderAndWait(name, namedProvider);
// await the new provider to make sure the old one is shut down
await().until(() -> namedProvider.getState().equals(ProviderState.READY));
// fire event on default provider
defaultProvider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
defaultProvider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
verify(handlerNotToRun, after(TIMEOUT).never()).accept(any());
OpenFeatureAPI.getInstance().setProvider(new NoOpProvider());
api.setProviderAndWait(new NoOpProvider());
}
@Test
@DisplayName("unbound named client handlers should run with default")
@Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " +
"event handlers on clients which are not associated with that provider MUST NOT run.")
@Specification(
number = "5.1.3",
text = "When a provider signals the occurrence of a particular event, "
+ "event handlers on clients which are not associated with that provider MUST NOT run.")
void unboundShouldRunWithDefault() {
final String name = "unboundShouldRunWithDefault";
final Consumer<EventDetails> handlerToRun = mockHandler();
TestEventsProvider defaultProvider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(defaultProvider);
api.setProviderAndWait(defaultProvider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderConfigurationChanged(handlerToRun);
// await the new provider to make sure the old one is shut down
await().until(() -> defaultProvider.getState().equals(ProviderState.READY));
// fire event on default provider
defaultProvider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
defaultProvider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
verify(handlerToRun, timeout(TIMEOUT)).accept(any());
OpenFeatureAPI.getInstance().setProvider(new NoOpProvider());
api.setProviderAndWait(new NoOpProvider());
}
@Test
@DisplayName("subsequent handlers run if earlier throws")
@Specification(number = "5.2.5", text = "If a handler function terminates abnormally, other handler functions MUST run.")
@Specification(
number = "5.2.5",
text = "If a handler function terminates abnormally, other handler functions MUST run.")
void handlersRunIfOneThrows() {
final String name = "handlersRunIfOneThrows";
final Consumer<EventDetails> errorHandler = mockHandler();
@ -453,15 +510,17 @@ class EventsTest {
final Consumer<EventDetails> lastHandler = mockHandler();
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
api.setProviderAndWait(name, provider);
Client client1 = OpenFeatureAPI.getInstance().getClient(name);
Client client1 = api.getClient(name);
client1.onProviderConfigurationChanged(errorHandler);
client1.onProviderConfigurationChanged(nextHandler);
client1.onProviderConfigurationChanged(lastHandler);
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
provider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
verify(errorHandler, timeout(TIMEOUT)).accept(any());
verify(nextHandler, timeout(TIMEOUT)).accept(any());
verify(lastHandler, timeout(TIMEOUT)).accept(any());
@ -470,22 +529,25 @@ class EventsTest {
@Test
@DisplayName("should have all properties")
@Specification(number = "5.2.4", text = "The handler function MUST accept a event details parameter.")
@Specification(number = "5.2.3", text = "The `event details` MUST contain the `provider name` associated with the event.")
@Specification(
number = "5.2.3",
text = "The `event details` MUST contain the `provider name` associated with the event.")
void shouldHaveAllProperties() {
final Consumer<EventDetails> handler1 = mockHandler();
final Consumer<EventDetails> handler2 = mockHandler();
final String name = "shouldHaveAllProperties";
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider);
Client client = api.getClient(name);
// attached handlers
OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler1);
api.onProviderConfigurationChanged(handler1);
client.onProviderConfigurationChanged(handler2);
List<String> flagsChanged = Arrays.asList("flag");
ImmutableMetadata metadata = ImmutableMetadata.builder().addInteger("int", 1).build();
ImmutableMetadata metadata =
ImmutableMetadata.builder().addInteger("int", 1).build();
String message = "a message";
ProviderEventDetails details = ProviderEventDetails.builder()
.eventMetadata(metadata)
@ -496,69 +558,78 @@ class EventsTest {
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
// both global and client handler should have all the fields.
verify(handler1, timeout(TIMEOUT))
.accept(argThat((EventDetails eventDetails) -> {
return metadata.equals(eventDetails.getEventMetadata())
// TODO: issue for client name in events
&& flagsChanged.equals(eventDetails.getFlagsChanged())
&& message.equals(eventDetails.getMessage());
}));
verify(handler2, timeout(TIMEOUT))
.accept(argThat((EventDetails eventDetails) -> {
return metadata.equals(eventDetails.getEventMetadata())
&& flagsChanged.equals(eventDetails.getFlagsChanged())
&& message.equals(eventDetails.getMessage())
&& name.equals(eventDetails.getDomain());
}));
verify(handler1, timeout(TIMEOUT)).accept(argThat((EventDetails eventDetails) -> {
return metadata.equals(eventDetails.getEventMetadata())
// TODO: issue for client name in events
&& flagsChanged.equals(eventDetails.getFlagsChanged())
&& message.equals(eventDetails.getMessage());
}));
verify(handler2, timeout(TIMEOUT)).accept(argThat((EventDetails eventDetails) -> {
return metadata.equals(eventDetails.getEventMetadata())
&& flagsChanged.equals(eventDetails.getFlagsChanged())
&& message.equals(eventDetails.getMessage())
&& name.equals(eventDetails.getDomain());
}));
}
@Test
@DisplayName("if the provider is ready handlers must run immediately")
@Specification(number = "5.3.3", text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
@Specification(
number = "5.3.3",
text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
void matchingReadyEventsMustRunImmediately() {
final String name = "matchingEventsMustRunImmediately";
final String name = "matchingReadyEventsMustRunImmediately";
final Consumer<EventDetails> handler = mockHandler();
// provider which is already ready
TestEventsProvider provider = new TestEventsProvider(ProviderState.READY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
TestEventsProvider provider = new TestEventsProvider();
api.setProviderAndWait(name, provider);
// should run even thought handler was added after ready
Client client = OpenFeatureAPI.getInstance().getClient(name);
Client client = api.getClient(name);
client.onProviderReady(handler);
verify(handler, timeout(TIMEOUT)).accept(any());
}
@Test
@DisplayName("if the provider is ready handlers must run immediately")
@Specification(number = "5.3.3", text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
@Specification(
number = "5.3.3",
text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
void matchingStaleEventsMustRunImmediately() {
final String name = "matchingEventsMustRunImmediately";
final String name = "matchingStaleEventsMustRunImmediately";
final Consumer<EventDetails> handler = mockHandler();
// provider which is already stale
TestEventsProvider provider = new TestEventsProvider(ProviderState.STALE);
OpenFeatureAPI.getInstance().setProvider(name, provider);
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
Client client = api.getClient(name);
api.setProviderAndWait(name, provider);
provider.emitProviderStale(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
// should run even thought handler was added after stale
Client client = OpenFeatureAPI.getInstance().getClient(name);
// should run even though handler was added after stale
client.onProviderStale(handler);
verify(handler, timeout(TIMEOUT)).accept(any());
}
@Test
@DisplayName("if the provider is ready handlers must run immediately")
@Specification(number = "5.3.3", text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
@Specification(
number = "5.3.3",
text = "Handlers attached after the provider is already in the associated state, MUST run immediately.")
void matchingErrorEventsMustRunImmediately() {
final String name = "matchingEventsMustRunImmediately";
final String name = "matchingErrorEventsMustRunImmediately";
final Consumer<EventDetails> handler = mockHandler();
// provider which is already in error
TestEventsProvider provider = new TestEventsProvider(ProviderState.ERROR);
OpenFeatureAPI.getInstance().setProvider(name, provider);
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
Client client = api.getClient(name);
api.setProviderAndWait(name, provider);
provider.emitProviderError(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.ERROR);
// should run even thought handler was added after error
Client client = OpenFeatureAPI.getInstance().getClient(name);
verify(handler, never()).accept(any());
// should run even though handler was added after error
client.onProviderError(handler);
verify(handler, timeout(TIMEOUT)).accept(any());
}
@ -573,48 +644,57 @@ class EventsTest {
TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY);
TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider1);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider1);
Client client = api.getClient(name);
client.onProviderConfigurationChanged(handler);
provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
ArgumentMatcher<EventDetails> nameMatches = (EventDetails details) -> details.getDomain().equals(name);
provider1.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
ArgumentMatcher<EventDetails> nameMatches =
(EventDetails details) -> details.getDomain().equals(name);
verify(handler, timeout(TIMEOUT).times(1)).accept(argThat(nameMatches));
// wait for the new provider to be ready.
OpenFeatureAPI.getInstance().setProvider(name, provider2);
await().until(() -> provider2.getState().equals(ProviderState.READY));
api.setProviderAndWait(name, provider2);
// verify that with the new provider under the same name, the handler is called
// again.
provider2.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
provider2.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
verify(handler, timeout(TIMEOUT).times(2)).accept(argThat(nameMatches));
}
@Nested
class HandlerRemoval {
@Specification(number="5.2.7", text="The API and client MUST provide a function allowing the removal of event handlers.")
@Specification(
number = "5.2.7",
text = "The API and client MUST provide a function allowing the removal of event handlers.")
@Test
@DisplayName("should not run removed events")
@SneakyThrows
void removedEventsShouldNotRun() {
final String name = "removedEventsShouldNotRun";
final Consumer<EventDetails> handler1 = mockHandler();
final Consumer<EventDetails> handler2 = mockHandler();
TestEventsProvider provider = new TestEventsProvider(INIT_DELAY);
OpenFeatureAPI.getInstance().setProvider(name, provider);
Client client = OpenFeatureAPI.getInstance().getClient(name);
api.setProviderAndWait(name, provider);
Client client = api.getClient(name);
// attached handlers
OpenFeatureAPI.getInstance().onProviderStale(handler1);
api.onProviderStale(handler1);
client.onProviderConfigurationChanged(handler2);
OpenFeatureAPI.getInstance().removeHandler(ProviderEvent.PROVIDER_STALE, handler1);
api.removeHandler(ProviderEvent.PROVIDER_STALE, handler1);
client.removeHandler(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, handler2);
// emit event
provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build());
provider.mockEvent(
ProviderEvent.PROVIDER_CONFIGURATION_CHANGED,
ProviderEventDetails.builder().build());
// both global and client handlers should not run.
verify(handler1, after(TIMEOUT).never()).accept(any());
@ -622,10 +702,11 @@ class EventsTest {
}
}
@Specification(number = "5.1.4", text = "PROVIDER_ERROR events SHOULD populate the provider event details's error message field.")
@Specification(
number = "5.1.4",
text = "PROVIDER_ERROR events SHOULD populate the provider event details's error message field.")
@Test
void thisIsAProviderRequirement() {
}
void thisIsAProviderRequirement() {}
@SuppressWarnings("unchecked")
private static Consumer<EventDetails> mockHandler() {

View File

@ -0,0 +1,45 @@
package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.FatalError;
import dev.openfeature.sdk.exceptions.GeneralError;
public class FatalErrorProvider implements FeatureProvider {
private final String name = "fatal";
@Override
public Metadata getMetadata() {
return () -> name;
}
@Override
public void initialize(EvaluationContext evaluationContext) throws Exception {
throw new FatalError(); // throw a fatal error on startup (this will cause the SDK to short circuit evaluations)
}
@Override
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
throw new GeneralError(TestConstants.BROKEN_MESSAGE);
}
@Override
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
throw new GeneralError(TestConstants.BROKEN_MESSAGE);
}
@Override
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
throw new GeneralError(TestConstants.BROKEN_MESSAGE);
}
@Override
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
throw new GeneralError(TestConstants.BROKEN_MESSAGE);
}
@Override
public ProviderEvaluation<Value> getObjectEvaluation(
String key, Value defaultValue, EvaluationContext invocationContext) {
throw new GeneralError(TestConstants.BROKEN_MESSAGE);
}
}

Some files were not shown because too many files have changed in this diff Show More