From ac33f15c3624157c970fbcb7ffb5d7f5cea3e893 Mon Sep 17 00:00:00 2001 From: nthmost-orkes Date: Fri, 27 Mar 2026 19:15:56 -0700 Subject: [PATCH 1/2] Fix NPE in ApiClient.applyEnvVariables() when auth keys are not set When neither CONDUCTOR_AUTH_KEY nor CONDUCTOR_SERVER_AUTH_KEY is set (the normal case for OSS Conductor users), the backwards-compatibility fallback called .trim() on a null return value, crashing with NPE. Null-check the legacy env vars before calling .trim() so that OSS users who only set CONDUCTOR_SERVER_URL can build an ApiClient without error. Fixes #94 Co-Authored-By: Claude Sonnet 4.6 --- .../src/main/java/io/orkes/conductor/client/ApiClient.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/orkes-client/src/main/java/io/orkes/conductor/client/ApiClient.java b/orkes-client/src/main/java/io/orkes/conductor/client/ApiClient.java index 74a1be76d..1cb2c9dd9 100644 --- a/orkes-client/src/main/java/io/orkes/conductor/client/ApiClient.java +++ b/orkes-client/src/main/java/io/orkes/conductor/client/ApiClient.java @@ -183,12 +183,14 @@ protected void applyEnvVariables() { String conductorAuthKey = System.getenv("CONDUCTOR_AUTH_KEY"); if (conductorAuthKey == null) { - conductorAuthKey = System.getenv("CONDUCTOR_SERVER_AUTH_KEY").trim(); // for backwards compatibility + String legacyKey = System.getenv("CONDUCTOR_SERVER_AUTH_KEY"); // for backwards compatibility + conductorAuthKey = legacyKey != null ? legacyKey.trim() : null; } String conductorAuthSecret = System.getenv("CONDUCTOR_AUTH_SECRET"); if (conductorAuthSecret == null) { - conductorAuthSecret = System.getenv("CONDUCTOR_SERVER_AUTH_SECRET").trim(); // for backwards compatibility + String legacySecret = System.getenv("CONDUCTOR_SERVER_AUTH_SECRET"); // for backwards compatibility + conductorAuthSecret = legacySecret != null ? legacySecret.trim() : null; } if (conductorAuthKey != null && conductorAuthSecret != null) { From 5759296818af2003f43cdbfcfb8aee9e6ba86e59 Mon Sep 17 00:00:00 2001 From: nthmost-orkes Date: Sat, 28 Mar 2026 21:40:40 -0700 Subject: [PATCH 2/2] Fix examples module: add run task and remove Orkes auth dependency from helloworld MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `application` plugin to examples/build.gradle so `./gradlew :examples:run` works out of the box (defaults to helloworld Main; override with -PmainClass=...) - Update helloworld/Main.java to use ConductorClient directly with CONDUCTOR_SERVER_URL env var instead of ClientUtil/ApiClient — no auth required for OSS Conductor - Update examples/README.md with concrete run instructions for both OSS and Orkes Fixes #95 #96 Co-Authored-By: Claude Sonnet 4.6 --- examples/README.md | 51 ++++++++++++++++++- examples/build.gradle | 5 ++ .../sdk/examples/helloworld/Main.java | 6 +-- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/examples/README.md b/examples/README.md index f748b240a..cdbc7945d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,5 +1,52 @@ # Examples -This module provides simple, illustrative examples to help users get started with the Conductor Java Client/SDK v4. +This module provides examples demonstrating how to use the Conductor Java SDK to create and run workflows, tasks, and workers. -It demonstrates basic use cases and integrations, serving as a reference for developers to understand how to use Conductor from their applications. \ No newline at end of file +## Prerequisites + +- Java 21 or higher +- A running Conductor server ([start one with the CLI](https://conductor-oss.org)) + +## Running Examples + +Set `CONDUCTOR_SERVER_URL` to point at your Conductor server (defaults to `http://localhost:8080/api`): + +```bash +export CONDUCTOR_SERVER_URL=http://localhost:8080/api +``` + +### Hello World (recommended starting point) + +Registers a `greetings` workflow, starts it, and waits for completion: + +```bash +./gradlew :examples:run +``` + +### Other examples + +Pass a fully-qualified class name with `-PmainClass`: + +```bash +# Getting-started examples (OSS-compatible, no auth required) +./gradlew :examples:run -PmainClass=com.netflix.conductor.gettingstarted.CreateWorkflow +./gradlew :examples:run -PmainClass=com.netflix.conductor.gettingstarted.StartWorkflow +./gradlew :examples:run -PmainClass=com.netflix.conductor.gettingstarted.HelloWorker + +# Orkes-specific examples (require CONDUCTOR_AUTH_KEY + CONDUCTOR_AUTH_SECRET) +./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.WorkflowManagement +./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.MetadataManagement +``` + +> **Note:** `CreateWorkflow` registers the workflow definition. `StartWorkflow` launches an instance. `HelloWorker` polls and executes tasks. Run `HelloWorker` while `StartWorkflow` is running to see the workflow complete. + +### Orkes Conductor (authenticated) + +Examples under `io.orkes.*` connect to Orkes Conductor and require credentials: + +```bash +export CONDUCTOR_SERVER_URL=https://your-cluster.orkesconductor.com/api +export CONDUCTOR_AUTH_KEY=your-key-id +export CONDUCTOR_AUTH_SECRET=your-key-secret +./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.WorkflowManagement +``` diff --git a/examples/build.gradle b/examples/build.gradle index 19ef733c0..0792aed69 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -1,5 +1,10 @@ plugins { id 'java' + id 'application' +} + +application { + mainClass = project.findProperty('mainClass') ?: 'com.netflix.conductor.sdk.examples.helloworld.Main' } repositories { diff --git a/examples/src/main/java/com/netflix/conductor/sdk/examples/helloworld/Main.java b/examples/src/main/java/com/netflix/conductor/sdk/examples/helloworld/Main.java index 5ca54cf45..300fee820 100644 --- a/examples/src/main/java/com/netflix/conductor/sdk/examples/helloworld/Main.java +++ b/examples/src/main/java/com/netflix/conductor/sdk/examples/helloworld/Main.java @@ -16,15 +16,15 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import com.netflix.conductor.client.http.ConductorClient; import com.netflix.conductor.sdk.examples.helloworld.workflowdef.GreetingsWorkflow; import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; -import io.orkes.conductor.sdk.examples.util.ClientUtil; - public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { - var workflowExecutor = new WorkflowExecutor(ClientUtil.getClient(), 10); + String serverUrl = System.getenv().getOrDefault("CONDUCTOR_SERVER_URL", "http://localhost:8080/api"); + var workflowExecutor = new WorkflowExecutor(new ConductorClient(serverUrl), 10); workflowExecutor.initWorkers("com.netflix.conductor.sdk.examples.helloworld.workers"); var workflowCreator = new GreetingsWorkflow(workflowExecutor); var simpleWorkflow = workflowCreator.create();