Skip to content

Commit c16651d

Browse files
aepfliclaude
andcommitted
Refactor OpenFeature Java SDK to separate API from implementation
- Created multi-module Maven structure with openfeature-api and openfeature-sdk modules - Moved core interfaces and data types to API module for clean separation - Implemented ServiceLoader pattern for automatic SDK discovery and loading - Created focused interfaces replacing monolithic OpenFeatureAdvanced: * OpenFeatureCore - basic operations * OpenFeatureHooks - hook management * OpenFeatureContext - evaluation context * OpenFeatureEventHandling - provider events * OpenFeatureTransactionContext - transaction context * OpenFeatureLifecycle - shutdown operations - Moved NoOp implementations to internal.noop package for better encapsulation - Created EventProvider interface in API with abstract class in SDK for backward compatibility - Updated HookContext initialization to use builder pattern throughout tests - Migrated tests to appropriate modules (API vs SDK concerns) - Fixed classpath and dependency issues for proper module separation - Updated imports and references to use API interfaces where appropriate 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Simon Schrottner <[email protected]>
1 parent 21dbef0 commit c16651d

File tree

95 files changed

+1860
-495
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+1860
-495
lines changed

benchmark.txt

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
[INFO] Scanning for projects...
2-
[INFO]
2+
[INFO]
33
[INFO] ------------------------< dev.openfeature:sdk >-------------------------
44
[INFO] Building OpenFeature Java SDK 1.12.1
55
[INFO] from pom.xml
66
[INFO] --------------------------------[ jar ]---------------------------------
77
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
88
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
99
[WARNING] Parameter 'encoding' is unknown for plugin 'maven-checkstyle-plugin:3.5.0:check (validate)'
10-
[INFO]
10+
[INFO]
1111
[INFO] --- clean:3.2.0:clean (default-clean) @ sdk ---
1212
[INFO] Deleting /home/todd/git/java-sdk/target
13-
[INFO]
13+
[INFO]
1414
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
1515
[INFO] Starting audit...
1616
Audit done.
1717
[INFO] You have 0 Checkstyle violations.
18-
[INFO]
18+
[INFO]
1919
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
2020
[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
21-
[INFO]
21+
[INFO]
2222
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
2323
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
24-
[INFO]
24+
[INFO]
2525
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
2626
[INFO] Recompiling the module because of changed source code.
2727
[INFO] Compiling 65 source files with javac [debug target 1.8] to target/classes
@@ -44,24 +44,24 @@ Audit done.
4444
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/NoOpProvider.java: Recompile with -Xlint:deprecation for details.
4545
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java: Some input files use unchecked or unsafe operations.
4646
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java: Recompile with -Xlint:unchecked for details.
47-
[INFO]
47+
[INFO]
4848
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
4949
[INFO] Starting audit...
5050
Audit done.
5151
[INFO] You have 0 Checkstyle violations.
52-
[INFO]
52+
[INFO]
5353
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
5454
[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
55-
[INFO]
55+
[INFO]
5656
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
5757
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
58-
[INFO]
58+
[INFO]
5959
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
6060
[INFO] Nothing to compile - all classes are up to date.
61-
[INFO]
61+
[INFO]
6262
[INFO] --- resources:3.3.1:testResources (default-testResources) @ sdk ---
6363
[INFO] Copying 2 resources from src/test/resources to target/test-classes
64-
[INFO]
64+
[INFO]
6565
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ sdk ---
6666
[INFO] Recompiling the module because of changed dependency.
6767
[INFO] Compiling 52 source files with javac [debug target 1.8] to target/test-classes
@@ -80,29 +80,29 @@ Audit done.
8080
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/EventsTest.java: Recompile with -Xlint:deprecation for details.
8181
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/HookSpecTest.java: Some input files use unchecked or unsafe operations.
8282
[INFO] /home/todd/git/java-sdk/src/test/java/dev/openfeature/sdk/HookSpecTest.java: Recompile with -Xlint:unchecked for details.
83-
[INFO]
83+
[INFO]
8484
[INFO] >>> jmh:0.2.2:benchmark (default-cli) > process-test-resources @ sdk >>>
85-
[INFO]
85+
[INFO]
8686
[INFO] --- checkstyle:3.5.0:check (validate) @ sdk ---
8787
[INFO] Starting audit...
8888
Audit done.
8989
[INFO] You have 0 Checkstyle violations.
90-
[INFO]
90+
[INFO]
9191
[INFO] --- jacoco:0.8.12:prepare-agent (prepare-agent) @ sdk ---
9292
[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
93-
[INFO]
93+
[INFO]
9494
[INFO] --- resources:3.3.1:resources (default-resources) @ sdk ---
9595
[INFO] skip non existing resourceDirectory /home/todd/git/java-sdk/src/main/resources
96-
[INFO]
96+
[INFO]
9797
[INFO] --- compiler:3.13.0:compile (default-compile) @ sdk ---
9898
[INFO] Nothing to compile - all classes are up to date.
99-
[INFO]
99+
[INFO]
100100
[INFO] --- resources:3.3.1:testResources (default-testResources) @ sdk ---
101101
[INFO] Copying 2 resources from src/test/resources to target/test-classes
102-
[INFO]
102+
[INFO]
103103
[INFO] <<< jmh:0.2.2:benchmark (default-cli) < process-test-resources @ sdk <<<
104-
[INFO]
105-
[INFO]
104+
[INFO]
105+
[INFO]
106106
[INFO] --- jmh:0.2.2:benchmark (default-cli) @ sdk ---
107107
[INFO] Changes detected - recompiling the module!
108108
[INFO] Compiling 52 source files to /home/todd/git/java-sdk/target/test-classes
@@ -150,7 +150,7 @@ Iteration 1: num #instances #bytes class name (module)
150150
19: 149 1884376 [Ljdk.internal.vm.FillerElement; ([email protected])
151151
20: 56476 1807232 java.util.ArrayList$Itr ([email protected])
152152
21: 37481 1799088 dev.openfeature.sdk.FlagEvaluationDetails$FlagEvaluationDetailsBuilder
153-
22: 100001 1600016 dev.openfeature.sdk.NoOpProvider$$Lambda/0x000076e79c02fa78
153+
22: 100001 1600016 dev.openfeature.api.NoOpProvider$$Lambda/0x000076e79c02fa78
154154
23: 50000 1600000 [Ldev.openfeature.sdk.EvaluationContext;
155155
24: 50000 1600000 [Ljava.util.List; ([email protected])
156156
25: 100000 1600000 dev.openfeature.sdk.OpenFeatureClient$$Lambda/0x000076e79c082800

openfeature-api/pom.xml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<version>4.8.6</version>
4343
<scope>provided</scope>
4444
</dependency>
45-
45+
4646
<!-- Test dependencies -->
4747
<dependency>
4848
<groupId>org.junit.jupiter</groupId>
@@ -77,7 +77,39 @@
7777
</archive>
7878
</configuration>
7979
</plugin>
80+
<plugin>
81+
<groupId>org.jacoco</groupId>
82+
<artifactId>jacoco-maven-plugin</artifactId>
83+
<version>0.8.13</version>
84+
<executions>
85+
<execution>
86+
<id>jacoco-check</id>
87+
<goals>
88+
<goal>check</goal>
89+
</goals>
90+
<configuration>
91+
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
92+
<excludes>
93+
<exclude>dev/openfeature/api/exceptions/**</exclude>
94+
<exclude>dev/openfeature/api/internal/**</exclude>
95+
</excludes>
96+
<rules>
97+
<rule>
98+
<element>PACKAGE</element>
99+
<limits>
100+
<limit>
101+
<counter>LINE</counter>
102+
<value>COVEREDRATIO</value>
103+
<minimum>0.3</minimum>
104+
</limit>
105+
</limits>
106+
</rule>
107+
</rules>
108+
</configuration>
109+
</execution>
110+
</executions>
111+
</plugin>
80112
</plugins>
81113
</build>
82114

83-
</project>
115+
</project>

openfeature-api/src/lombok.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lombok.addLombokGeneratedAnnotation = true
2+
lombok.extern.findbugs.addSuppressFBWarnings = true

openfeature-sdk/src/main/java/dev/openfeature/sdk/Awaitable.java renamed to openfeature-api/src/main/java/dev/openfeature/api/Awaitable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.openfeature.sdk;
1+
package dev.openfeature.api;
22

33
/**
44
* A class to help with synchronization by allowing the optional awaiting of the associated action.

openfeature-api/src/main/java/dev/openfeature/api/EvaluationContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
public interface EvaluationContext extends Structure {
1313

1414
String TARGETING_KEY = "targetingKey";
15-
15+
1616
/**
1717
* Empty evaluation context for use as a default.
1818
*/

openfeature-sdk/src/main/java/dev/openfeature/sdk/EvaluationEvent.java renamed to openfeature-api/src/main/java/dev/openfeature/api/EvaluationEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.openfeature.sdk;
1+
package dev.openfeature.api;
22

33
import java.util.HashMap;
44
import java.util.Map;

openfeature-api/src/main/java/dev/openfeature/api/EventDetails.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,32 @@
1111
@Data
1212
@SuperBuilder(toBuilder = true)
1313
public class EventDetails extends ProviderEventDetails {
14+
/** The domain associated with this event. */
1415
private String domain;
16+
17+
/** The name of the provider that generated this event. */
1518
private String providerName;
1619

17-
public static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails, String providerName) {
20+
/**
21+
* Create EventDetails from ProviderEventDetails with provider name.
22+
*
23+
* @param providerEventDetails the provider event details
24+
* @param providerName the name of the provider
25+
* @return EventDetails instance
26+
*/
27+
public static EventDetails fromProviderEventDetails(
28+
ProviderEventDetails providerEventDetails, String providerName) {
1829
return fromProviderEventDetails(providerEventDetails, providerName, null);
1930
}
2031

32+
/**
33+
* Create EventDetails from ProviderEventDetails with provider name and domain.
34+
*
35+
* @param providerEventDetails the provider event details
36+
* @param providerName the name of the provider
37+
* @param domain the domain associated with the event
38+
* @return EventDetails instance
39+
*/
2140
public static EventDetails fromProviderEventDetails(
2241
ProviderEventDetails providerEventDetails, String providerName, String domain) {
2342
return builder()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dev.openfeature.api;
2+
3+
/**
4+
* Interface for feature providers that support real-time events.
5+
* Providers can implement this interface to emit events about flag changes,
6+
* provider state changes, and other configuration updates.
7+
*
8+
* @see FeatureProvider
9+
*/
10+
public interface EventProvider extends FeatureProvider {
11+
12+
/**
13+
* Emit the specified {@link ProviderEvent}.
14+
*
15+
* @param event The event type
16+
* @param details The details of the event
17+
* @return An {@link Awaitable} that can be used to wait for event processing completion
18+
*/
19+
Awaitable emit(ProviderEvent event, ProviderEventDetails details);
20+
21+
/**
22+
* Emit a {@link ProviderEvent#PROVIDER_READY} event.
23+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
24+
*
25+
* @param details The details of the event
26+
* @return An {@link Awaitable} that can be used to wait for event processing completion
27+
*/
28+
default Awaitable emitProviderReady(ProviderEventDetails details) {
29+
return emit(ProviderEvent.PROVIDER_READY, details);
30+
}
31+
32+
/**
33+
* Emit a {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} event.
34+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
35+
*
36+
* @param details The details of the event
37+
* @return An {@link Awaitable} that can be used to wait for event processing completion
38+
*/
39+
default Awaitable emitProviderConfigurationChanged(ProviderEventDetails details) {
40+
return emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
41+
}
42+
43+
/**
44+
* Emit a {@link ProviderEvent#PROVIDER_STALE} event.
45+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
46+
*
47+
* @param details The details of the event
48+
* @return An {@link Awaitable} that can be used to wait for event processing completion
49+
*/
50+
default Awaitable emitProviderStale(ProviderEventDetails details) {
51+
return emit(ProviderEvent.PROVIDER_STALE, details);
52+
}
53+
54+
/**
55+
* Emit a {@link ProviderEvent#PROVIDER_ERROR} event.
56+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
57+
*
58+
* @param details The details of the event
59+
* @return An {@link Awaitable} that can be used to wait for event processing completion
60+
*/
61+
default Awaitable emitProviderError(ProviderEventDetails details) {
62+
return emit(ProviderEvent.PROVIDER_ERROR, details);
63+
}
64+
}

openfeature-api/src/main/java/dev/openfeature/api/FeatureProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/**
77
* The interface implemented by upstream flag providers to resolve flags for
88
* their service. If you want to support realtime events with your provider, you
9-
* should extend the EventProvider class from the SDK module
9+
* should implement {@link EventProvider}
1010
*/
1111
public interface FeatureProvider {
1212
Metadata getMetadata();

openfeature-api/src/main/java/dev/openfeature/api/NoOpOpenFeatureAPI.java

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)