diff --git a/Makefile b/Makefile
index b889d85..b05df5c 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ help:
@echo " test-integration - Run all integration tests"
@echo " test-integration-csharp - Run C# integration tests"
@echo " test-integration-go - Run Go integration tests"
+ @echo " test-integration-java - Run Java integration tests"
@echo " test-integration-nodejs - Run NodeJS integration tests"
@echo " generate - Generate all code (API clients, docs, schema)"
@echo " generate-api - Generate API clients from OpenAPI specs"
@@ -67,6 +68,11 @@ test-integration-angular:
@echo "Running Angular integration test with Dagger..."
@go run ./test/integration/cmd/angular/run.go
+.PHONY: test-integration-java
+test-integration-java:
+ @echo "Running Java integration test with Dagger..."
+ @go run ./test/integration/cmd/java/run.go
+
.PHONY: test-integration
test-integration:
@echo "Running all integration tests with Dagger..."
diff --git a/test/integration/cmd/java/run.go b/test/integration/cmd/java/run.go
new file mode 100644
index 0000000..c80eaf9
--- /dev/null
+++ b/test/integration/cmd/java/run.go
@@ -0,0 +1,99 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "dagger.io/dagger"
+ "github.com/open-feature/cli/test/integration"
+)
+
+// Test implements the integration test for the Java generator
+type Test struct {
+ // ProjectDir is the absolute path to the root of the project
+ ProjectDir string
+ // TestDir is the absolute path to the test directory
+ TestDir string
+}
+
+// New creates a new Test
+func New(projectDir, testDir string) *Test {
+ return &Test{
+ ProjectDir: projectDir,
+ TestDir: testDir,
+ }
+}
+
+// Run executes the Java integration test using Dagger
+func (t *Test) Run(ctx context.Context, client *dagger.Client) (*dagger.Container, error) {
+ // Source code container
+ source := client.Host().Directory(t.ProjectDir)
+ testFiles := client.Host().Directory(t.TestDir, dagger.HostDirectoryOpts{
+ Include: []string{"pom.xml", "src/**/*.java"},
+ })
+
+ // Build the CLI
+ cli := client.Container().
+ From("golang:1.24-alpine").
+ WithExec([]string{"apk", "add", "--no-cache", "git"}).
+ WithDirectory("/src", source).
+ WithWorkdir("/src").
+ WithExec([]string{"go", "mod", "tidy"}).
+ WithExec([]string{"go", "mod", "download"}).
+ WithExec([]string{"go", "build", "-o", "cli", "./cmd/openfeature"})
+
+ // Generate Java client
+ generated := cli.WithExec([]string{
+ "./cli", "generate", "java",
+ "--manifest=/src/sample/sample_manifest.json",
+ "--output=/tmp/generated",
+ "--package-name=dev.openfeature.generated",
+ })
+
+ // Get generated files
+ generatedFiles := generated.Directory("/tmp/generated")
+
+ // Test Java compilation with the generated files
+ javaContainer := client.Container().
+ From("maven:3.9-eclipse-temurin-21-alpine").
+ WithWorkdir("/app").
+ WithDirectory("/app", testFiles).
+ WithDirectory("/app/src/main/java/dev/openfeature/generated", generatedFiles).
+ WithExec([]string{"mvn", "clean", "compile", "-B", "-q"}).
+ WithExec([]string{"mvn", "exec:java", "-Dexec.mainClass=dev.openfeature.Main", "-q"})
+
+ return javaContainer, nil
+}
+
+// Name returns the name of the integration test
+func (t *Test) Name() string {
+ return "java"
+}
+
+func main() {
+ ctx := context.Background()
+
+ // Get project root
+ projectDir, err := os.Getwd()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to get project dir: %v\n", err)
+ os.Exit(1)
+ }
+
+ // Get test directory
+ testDir, err := filepath.Abs(filepath.Join(projectDir, "test/java-integration"))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to get test dir: %v\n", err)
+ os.Exit(1)
+ }
+
+ // Create and run the Java integration test
+ test := New(projectDir, testDir)
+
+ if err := integration.RunTest(ctx, test); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/test/integration/cmd/run.go b/test/integration/cmd/run.go
index 5923c26..3c8ac8e 100644
--- a/test/integration/cmd/run.go
+++ b/test/integration/cmd/run.go
@@ -7,45 +7,29 @@ import (
)
func main() {
- // Run the language-specific tests
fmt.Println("=== Running all integration tests ===")
- // Run the C# integration test
- csharpCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/csharp")
- csharpCmd.Stdout = os.Stdout
- csharpCmd.Stderr = os.Stderr
- if err := csharpCmd.Run(); err != nil {
- fmt.Fprintf(os.Stderr, "Error running C# integration test: %v\n", err)
- os.Exit(1)
+ tests := []struct {
+ name string
+ path string
+ }{
+ {"C#", "github.com/open-feature/cli/test/integration/cmd/csharp"},
+ {"Go", "github.com/open-feature/cli/test/integration/cmd/go"},
+ {"NodeJS", "github.com/open-feature/cli/test/integration/cmd/nodejs"},
+ {"Angular", "github.com/open-feature/cli/test/integration/cmd/angular"},
+ {"Java", "github.com/open-feature/cli/test/integration/cmd/java"},
}
- // Run the Go integration test
- goCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/go")
- goCmd.Stdout = os.Stdout
- goCmd.Stderr = os.Stderr
- if err := goCmd.Run(); err != nil {
- fmt.Fprintf(os.Stderr, "Error running Go integration test: %v\n", err)
- os.Exit(1)
+ for _, test := range tests {
+ fmt.Printf("--- Running %s integration test ---\n", test.name)
+ cmd := exec.Command("go", "run", test.path)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Fprintf(os.Stderr, "Error running %s integration test: %v\n", test.name, err)
+ os.Exit(1)
+ }
}
- // Run the nodejs test
- nodeCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/nodejs")
- nodeCmd.Stdout = os.Stdout
- nodeCmd.Stderr = os.Stderr
- if err := nodeCmd.Run(); err != nil {
- fmt.Fprintf(os.Stderr, "Error running nodejs integration test: %v\n", err)
- os.Exit(1)
- }
-
- // Run the Angular integration test
- angularCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/angular")
- angularCmd.Stdout = os.Stdout
- angularCmd.Stderr = os.Stderr
- if err := angularCmd.Run(); err != nil {
- fmt.Fprintf(os.Stderr, "Error running Angular integration test: %v\n", err)
- os.Exit(1)
- }
-
- // Add more tests here as they are available
fmt.Println("=== All integration tests passed successfully ===")
}
diff --git a/test/java-integration/pom.xml b/test/java-integration/pom.xml
new file mode 100644
index 0000000..0bb7be4
--- /dev/null
+++ b/test/java-integration/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ dev.openfeature
+ cli-java-integration-test
+ 1.0-SNAPSHOT
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+
+ dev.openfeature
+ sdk
+ 1.14.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+ 21
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+ dev.openfeature.Main
+
+
+
+
+
diff --git a/test/java-integration/src/main/java/dev/openfeature/Main.java b/test/java-integration/src/main/java/dev/openfeature/Main.java
new file mode 100644
index 0000000..7fb10a2
--- /dev/null
+++ b/test/java-integration/src/main/java/dev/openfeature/Main.java
@@ -0,0 +1,103 @@
+package dev.openfeature;
+
+import dev.openfeature.generated.*;
+import dev.openfeature.sdk.*;
+import dev.openfeature.sdk.providers.memory.Flag;
+import dev.openfeature.sdk.providers.memory.InMemoryProvider;
+
+import java.util.Map;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ run();
+ System.out.println("Generated Java code compiles successfully!");
+ } catch (Exception e) {
+ System.err.println("Error: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void run() throws Exception {
+ // Set up the in-memory provider with test flags
+ Map themeConfig = Map.of(
+ "primaryColor", "#007bff",
+ "secondaryColor", "#6c757d"
+ );
+
+ Map> flags = Map.of(
+ "discountPercentage", Flag.builder()
+ .variant("default", 0.15)
+ .defaultVariant("default")
+ .build(),
+ "enableFeatureA", Flag.builder()
+ .variant("default", false)
+ .defaultVariant("default")
+ .build(),
+ "greetingMessage", Flag.builder()
+ .variant("default", "Hello there!")
+ .defaultVariant("default")
+ .build(),
+ "usernameMaxLength", Flag.builder()
+ .variant("default", 50)
+ .defaultVariant("default")
+ .build(),
+ "themeCustomization", Flag.builder()
+ .variant("default", new Value(themeConfig))
+ .defaultVariant("default")
+ .build()
+ );
+
+ InMemoryProvider provider = new InMemoryProvider(flags);
+
+ // Set the provider
+ OpenFeatureAPI.getInstance().setProviderAndWait(provider);
+
+ Client client = OpenFeatureAPI.getInstance().getClient();
+ MutableContext evalContext = new MutableContext();
+
+ // Use the generated code for all flag evaluations
+ Boolean enableFeatureA = EnableFeatureA.value(client, evalContext);
+ System.out.println("enableFeatureA: " + enableFeatureA);
+ FlagEvaluationDetails enableFeatureADetails = EnableFeatureA.valueWithDetails(client, evalContext);
+ if (enableFeatureADetails.getErrorCode() != null) {
+ throw new Exception("Error evaluating boolean flag");
+ }
+
+ Double discount = DiscountPercentage.value(client, evalContext);
+ System.out.printf("Discount Percentage: %.2f%n", discount);
+ FlagEvaluationDetails discountDetails = DiscountPercentage.valueWithDetails(client, evalContext);
+ if (discountDetails.getErrorCode() != null) {
+ throw new Exception("Failed to get discount");
+ }
+
+ String greetingMessage = GreetingMessage.value(client, evalContext);
+ System.out.println("greetingMessage: " + greetingMessage);
+ FlagEvaluationDetails greetingDetails = GreetingMessage.valueWithDetails(client, evalContext);
+ if (greetingDetails.getErrorCode() != null) {
+ throw new Exception("Error evaluating string flag");
+ }
+
+ Integer usernameMaxLength = UsernameMaxLength.value(client, evalContext);
+ System.out.println("usernameMaxLength: " + usernameMaxLength);
+ FlagEvaluationDetails usernameDetails = UsernameMaxLength.valueWithDetails(client, evalContext);
+ if (usernameDetails.getErrorCode() != null) {
+ throw new Exception("Error evaluating int flag");
+ }
+
+ Value themeCustomization = ThemeCustomization.value(client, evalContext);
+ FlagEvaluationDetails themeDetails = ThemeCustomization.valueWithDetails(client, evalContext);
+ if (themeDetails.getErrorCode() != null) {
+ throw new Exception("Error evaluating object flag");
+ }
+ System.out.println("themeCustomization: " + themeCustomization);
+
+ // Test the getKey() method functionality for all flags
+ System.out.println("enableFeatureA flag key: " + EnableFeatureA.getKey());
+ System.out.println("discountPercentage flag key: " + DiscountPercentage.getKey());
+ System.out.println("greetingMessage flag key: " + GreetingMessage.getKey());
+ System.out.println("usernameMaxLength flag key: " + UsernameMaxLength.getKey());
+ System.out.println("themeCustomization flag key: " + ThemeCustomization.getKey());
+ }
+}