Files
wehub-resource-sync a9cd7750f4
CI / unit-test (push) Has been cancelled
CI / detect-changes (push) Has been cancelled
CI / build (push) Has been cancelled
Publish docs via GitHub Pages / Deploy docs (push) Has been cancelled
CI / test-harness (push) Has been cancelled
CI / generate-e2e-matrix (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / build-ui (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
UI v2 Integration CI / E2E (Integration) (push) Has been cancelled
UI v2 CI / Lint, Format & Test (push) Has been cancelled
UI v2 CI / E2E (Mocked) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:37:56 +08:00

619 lines
25 KiB
Markdown

---
description: "Build Conductor workers in Java with automated polling, thread management, and Spring Boot integration."
---
# Java SDK
!!! info "Source"
GitHub: [conductor-oss/java-sdk](https://github.com/conductor-oss/java-sdk) | Report issues and contribute on GitHub.
## Start Conductor server
If you don't already have a Conductor server running, pick one:
**Docker (recommended, includes UI):**
```shell
docker run -p 8080:8080 conductoross/conductor:latest
```
The UI will be available at `http://localhost:8080` and the API at `http://localhost:8080/api`
**MacOS / Linux (one-liner):** (If you don't want to use docker, you can install and run the binary directly)
```shell
curl -sSL https://raw.githubusercontent.com/conductor-oss/conductor/main/conductor_server.sh | sh
```
**Conductor CLI**
```shell
# Installs conductor cli
npm install -g @conductor-oss/conductor-cli
# Start the open source conductor server
conductor server start
# see conductor server --help for all the available commands
```
## Install the SDK
The SDK requires Java 17+. Add the following dependency to your project:
**For Gradle:**
```gradle
dependencies {
implementation 'org.conductoross:conductor-client:5.0.1'
// Optionally, you can also add spring module for auto configuration
// implementation 'org.conductoross:conductor-client-spring:5.0.1'
}
```
**For Maven:**
```xml
<dependency>
<groupId>org.conductoross</groupId>
<artifactId>conductor-client</artifactId>
<version>5.0.1</version>
</dependency>
```
*Optionally, you can also add spring module for auto configuration*
```xml
<dependency>
<groupId>org.conductoross</groupId>
<artifactId>conductor-client-spring</artifactId>
<version>5.0.1</version>
</dependency>
```
## 60-Second Quickstart
**Step 1: Write a worker**
Workers are Java classes that implement the `Worker` interface and poll Conductor for tasks to execute.
```java
public class GreetWorker implements Worker {
@Override
public String getTaskDefName() {
return "greet";
}
@Override
public TaskResult execute(Task task) {
String name = (String) task.getInputData().get("name");
TaskResult result = new TaskResult(task);
result.setStatus(TaskResult.Status.COMPLETED);
result.addOutputData("greeting", "Hello, " + name + "!");
return result;
}
}
```
**Step 2: Run your first workflow app**
Create a `Main.java` with the following:
```java
import io.orkes.conductor.client.ApiClient;
import io.orkes.conductor.client.OrkesClients;
import com.netflix.conductor.client.automator.TaskRunnerConfigurer;
import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest;
import com.netflix.conductor.sdk.workflow.def.ConductorWorkflow;
import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask;
import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// Configure the SDK via ApiClient (enterprise-compatible path)
ApiClient apiClient = ApiClient.builder().build();
OrkesClients clients = new OrkesClients(apiClient);
// Create workflow executor
WorkflowExecutor executor = new WorkflowExecutor(apiClient, 100);
// Build and register the workflow
ConductorWorkflow<Map> workflow = new ConductorWorkflow<>(executor);
workflow.setName("greetings");
workflow.setVersion(1);
SimpleTask greetTask = new SimpleTask("greet", "greet_ref");
greetTask.input("name", "${workflow.input.name}");
workflow.add(greetTask);
workflow.registerWorkflow(true, true);
// Start polling for tasks using OrkesTaskClient
TaskRunnerConfigurer configurer = new TaskRunnerConfigurer.Builder(
clients.getTaskClient(),
List.of(new GreetWorker())
).withThreadCount(10).build();
configurer.init();
// Run the workflow using OrkesWorkflowClient
StartWorkflowRequest request = new StartWorkflowRequest();
request.setName("greetings");
request.setVersion(1);
request.setInput(Map.of("name", "Conductor"));
String workflowId = clients.getWorkflowClient().startWorkflow(request);
System.out.println("Started workflow: " + workflowId);
System.out.println("View execution at: " + apiClient.getBasePath().replace("/api", "") + "/execution/" + workflowId);
}
}
```
Run it:
```shell
./gradlew run
```
> ### Using Orkes Conductor / Remote Server?
> Export your authentication credentials as well:
>
> ```shell
> export CONDUCTOR_SERVER_URL="https://your-cluster.orkesconductor.io/api"
>
> # If using Orkes Conductor that requires auth key/secret
> export CONDUCTOR_AUTH_KEY="your-key"
> export CONDUCTOR_AUTH_SECRET="your-secret"
> ```
That's it -- you just defined a worker, built a workflow, and executed it. Open the Conductor UI (default:
[http://localhost:8080](http://localhost:8080)) to see the execution.
## Comprehensive worker example
See [examples/basics/hello-world/](https://github.com/conductor-oss/java-sdk/tree/main/examples/basics/hello-world) for a complete working example with:
- Workflow definition using the SDK
- Worker implementation with annotations
- Workflow execution and monitoring
---
## Workers
Workers are Java classes that execute Conductor tasks. Implement the `Worker` interface or use the `@WorkerTask` annotation:
**Using Worker interface:**
```java
public class MyWorker implements Worker {
@Override
public String getTaskDefName() {
return "my_task";
}
@Override
public TaskResult execute(Task task) {
// Your business logic here
TaskResult result = new TaskResult(task);
result.setStatus(TaskResult.Status.COMPLETED);
result.addOutputData("result", "Task completed successfully");
return result;
}
}
```
**Using @WorkerTask annotation:**
```java
public class Workers {
@WorkerTask("greet")
public String greet(@InputParam("name") String name) {
return "Hello, " + name + "!";
}
@WorkerTask("process_data")
public Map<String, Object> processData(@InputParam("data") Map<String, Object> data) {
// Process and return data
return Map.of("processed", true, "result", data);
}
}
```
**Start workers** with `TaskRunnerConfigurer` or `WorkflowExecutor`:
```java
// Option 1: Using TaskRunnerConfigurer
ApiClient apiClient = ApiClient.builder().build();
OrkesClients clients = new OrkesClients(apiClient);
TaskRunnerConfigurer configurer = new TaskRunnerConfigurer.Builder(
clients.getTaskClient(),
List.of(new MyWorker(), new AnotherWorker())
)
.withThreadCount(10)
.build();
configurer.init();
// Option 2: Using WorkflowExecutor (auto-discovers @WorkerTask annotations)
WorkflowExecutor executor = new WorkflowExecutor(apiClient, 10);
executor.initWorkers("com.mycompany.workers"); // Package to scan for @WorkerTask
```
**Worker Design Principles:**
- Workers should be stateless and idempotent
- Handle failure scenarios gracefully
- Report status back to Conductor
- Complete execution quickly (or use polling for long-running tasks)
**Worker vs. HTTP Endpoints:**
| Feature | Worker | HTTP Endpoint |
|---------|--------|---------------|
| Deployment | Embedded in application | Separate service |
| Scalability | Horizontal (add more instances) | Horizontal (add more instances) |
| Latency | Lower (direct polling) | Higher (network overhead) |
| Complexity | Simple | Complex (service mesh, load balancer) |
**Learn more:**
- [Worker SDK Guide](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/worker_sdk.md) — Complete worker framework documentation
- [Worker Examples](https://github.com/conductor-oss/java-sdk/blob/main/examples/) — Sample worker implementations
## Monitoring Workers
Enable metrics collection for monitoring workers:
```java
// Using conductor-client-metrics module
dependencies {
implementation 'org.conductoross:conductor-client-metrics:5.0.1'
}
```
```java
// Configure metrics with Prometheus
TaskRunnerConfigurer configurer = new TaskRunnerConfigurer.Builder(taskClient, workers)
.withThreadCount(10)
.withMetricsCollector(new PrometheusMetricsCollector())
.build();
```
See [conductor-client-metrics/README.md](https://github.com/conductor-oss/java-sdk/blob/main/conductor-client-metrics/README.md) for full metrics documentation.
## Workflows
Define workflows in Java using the `ConductorWorkflow` builder:
```java
ConductorWorkflow<MyInput> workflow = new ConductorWorkflow<>(executor);
workflow.setName("my_workflow");
workflow.setVersion(1);
workflow.setOwnerEmail("team@example.com");
// Add tasks
SimpleTask task1 = new SimpleTask("task1", "task1_ref");
SimpleTask task2 = new SimpleTask("task2", "task2_ref");
workflow.add(task1);
workflow.add(task2);
// Register the workflow
workflow.registerWorkflow(true, true);
```
**Execute workflows:**
```java
ApiClient apiClient = ApiClient.builder().build();
OrkesClients clients = new OrkesClients(apiClient);
WorkflowClient workflowClient = clients.getWorkflowClient();
// Synchronous (start and poll for completion)
CompletableFuture<Workflow> future = workflow.execute(input);
Workflow result = future.get(30, TimeUnit.SECONDS);
System.out.println("Output: " + result.getOutput());
// Asynchronous (returns workflow ID immediately)
StartWorkflowRequest request = new StartWorkflowRequest();
request.setName("my_workflow");
request.setVersion(1);
request.setInput(Map.of("key", "value"));
String workflowId = workflowClient.startWorkflow(request);
// Dynamic execution (sends workflow definition with request)
CompletableFuture<Workflow> dynamicRun = workflow.executeDynamic(input);
```
**Manage running workflows:**
```java
// Get workflow status
Workflow wf = workflowClient.getWorkflow(workflowId, true);
System.out.println("Status: " + wf.getStatus());
// Pause, resume, terminate
workflowClient.pauseWorkflow(workflowId);
workflowClient.resumeWorkflow(workflowId);
workflowClient.terminateWorkflow(workflowId, "No longer needed");
// Retry and restart failed workflows
workflowClient.retryWorkflow(workflowId);
workflowClient.restartWorkflow(workflowId, false);
```
**Learn more:**
- [Workflow SDK Guide](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/workflow_sdk.md) — Workflow-as-code documentation
- [Workflow Testing](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/testing_framework.md) — Unit testing workflows
## Troubleshooting
**Worker stops polling or crashes:**
- Check network connectivity to Conductor server
- Verify `CONDUCTOR_SERVER_URL` is set correctly
- Ensure sufficient thread pool size for your workload
- Monitor JVM memory and GC pauses
**Connection refused errors:**
- Verify Conductor server is running: `curl http://localhost:8080/health`
- Check firewall rules if connecting to remote server
- For Orkes Conductor, verify auth credentials are correct
**Tasks stuck in SCHEDULED state:**
- Ensure workers are polling for the correct task type
- Check that `getTaskDefName()` matches the task name in workflow
- Verify worker thread count is sufficient
**Workflow execution timeout:**
- Increase workflow timeout in definition
- Check if tasks are completing within expected time
- Monitor Conductor server logs for errors
**Authentication errors with Orkes Conductor:**
- Verify `CONDUCTOR_AUTH_KEY` and `CONDUCTOR_AUTH_SECRET` are set
- Ensure the application has required permissions
- Check that credentials haven't expired
---
## File handling
For workflows that move binary file payloads, the SDK exposes `FileHandler` — a worker-facing reference to a file in the configured backend. Pass it as a worker input/output and the runtime handles upload, download, and the metadata roundtrip transparently. See [File Storage](../advanced/file-storage.md) for the operator-side configuration and [File API](../api/files.md) for the underlying REST surface.
The relevant types in `org.conductoross.conductor.sdk.file`:
| Type | Use |
|---|---|
| `FileHandler` | Worker parameter type for files. Static `fromLocalFile(Path)` / `fromLocalFile(Path, contentType)` create a handle for a local file the worker is producing. |
| `FileUploader` | Explicit upload API; obtained from `task.getFileUploader()` inside a `Worker` impl, or from `WorkflowFileClient` outside one. |
| `FileUploadOptions` | Optional metadata: `contentType`, `fileName`, `taskId`, `multipart`. |
**Worker that consumes a file:**
```java
public class TranscodeInput {
public FileHandler primary_video;
public String resolution;
}
@WorkerTask("transcode_video")
public @OutputParam("output_file") FileHandler transcode(TranscodeInput input) throws IOException {
Path transcoded = Files.createTempFile("transcoded-", ".mp4");
try (InputStream in = input.primary_video.getInputStream()) {
Files.write(transcoded, in.readAllBytes());
}
return FileHandler.fromLocalFile(transcoded, "video/mp4");
}
```
`primary_video` is auto-resolved from the task input — the runtime downloads the file lazily on first read of `getInputStream()`. The returned `FileHandler` is auto-uploaded by the task runner before the task output is published, and the resulting `fileHandleId` is substituted into the output map so downstream tasks can consume it.
**Explicit upload inside a `Worker` implementation:**
```java
@Override
public TaskResult execute(Task task) {
Path output = renderReport(task);
FileHandler handle = task.getFileUploader().upload(
output,
new FileUploadOptions().setContentType("application/pdf").setMultipart(true));
TaskResult result = new TaskResult(task);
result.getOutputData().put("report", handle);
return result;
}
```
Use this form when you want to control upload timing (e.g., upload before the task's main work completes, or upload an `InputStream` that's not backed by a file). When `multipart=true` the SDK uses the multipart upload flow on backends that support it, falling back to single-shot otherwise.
---
## AI & LLM Workflows
Conductor supports AI-native workflows including agentic tool calling, RAG pipelines, and multi-agent orchestration.
**Agentic Workflows**
Build AI agents where LLMs dynamically select and call Java workers as tools. All agentic examples live in [`AgenticExamplesRunner.java`](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/agentic/AgenticExamplesRunner.java) — a single unified runner.
| Workflow | Description |
|----------|-------------|
| `llm_chat_workflow` | Automated multi-turn Q&A using `LLM_CHAT_COMPLETE` system task |
| `llm_chat_human_in_loop` | Interactive chat with WAIT task pauses for user input |
| `multiagent_chat_demo` | Multi-agent debate with moderator routing between two LLM panelists |
| `function_calling_workflow` | LLM picks which Java worker to call, returns JSON, dispatch worker executes it |
| `mcp_ai_agent` | AI agent using MCP tools (ListMcpTools → LLM plans → CallMcpTool → summarize) |
**LLM and RAG Workflows**
| Example | Description |
|---------|-------------|
| [RagWorkflowExample.java](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/agentic/RagWorkflowExample.java) | End-to-end RAG: document indexing, semantic search, answer generation |
| [VectorDbExample.java](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/agentic/VectorDbExample.java) | Vector database operations: text indexing, embedding generation, and semantic search |
**Using LLM Tasks in Workflows:**
```java
// Chat completion task (LLM_CHAT_COMPLETE system task)
LlmChatComplete chatTask = new LlmChatComplete("chat_assistant", "chat_ref")
.llmProvider("openai")
.model("gpt-4o-mini")
.messages(List.of(
Map.of("role", "system", "message", "You are a helpful assistant."),
Map.of("role", "user", "message", "${workflow.input.question}")
))
.temperature(0.7)
.maxTokens(500);
// Text completion task (LLM_TEXT_COMPLETE system task)
LlmTextComplete textTask = new LlmTextComplete("generate_text", "text_ref")
.llmProvider("openai")
.model("gpt-4o-mini")
.promptName("my-prompt-template")
.temperature(0.7);
// Document indexing for RAG (LLM_INDEX_DOCUMENT system task)
LlmIndexDocument indexTask = new LlmIndexDocument("index_doc", "index_ref")
.vectorDb("pinecone")
.namespace("my-docs")
.index("knowledge-base")
.embeddingModel("text-embedding-ada-002")
.text("${workflow.input.document}");
// Semantic search (LLM_SEARCH_INDEX system task)
LlmSearchIndex searchTask = new LlmSearchIndex("search_docs", "search_ref")
.vectorDb("pinecone")
.namespace("my-docs")
.index("knowledge-base")
.query("${workflow.input.question}")
.topK(5);
// MCP tool discovery (MCP_LIST_TOOLS system task — Orkes Conductor)
ListMcpTools listTools = new ListMcpTools("discover_tools", "tools_ref")
.mcpServer("http://localhost:3001/mcp");
// MCP tool execution (MCP_CALL_TOOL system task — Orkes Conductor)
CallMcpTool callTool = new CallMcpTool("execute_tool", "tool_ref")
.mcpServer("http://localhost:3001/mcp")
.method("${tools_ref.output.result.method}")
.arguments("${tools_ref.output.result.arguments}");
workflow.add(chatTask);
workflow.add(textTask);
workflow.add(indexTask);
```
Run all agentic examples:
```shell
export CONDUCTOR_SERVER_URL=http://localhost:8080/api
export OPENAI_API_KEY=your-key # or ANTHROPIC_API_KEY
# Run all examples end-to-end
./gradlew :examples:run --args="--all"
# Run specific workflow
./gradlew :examples:run --args="--menu"
```
## Examples
See the [Examples Guide](https://github.com/conductor-oss/java-sdk/blob/main/examples/README.md) for the full catalog. Key examples:
| Example | Description | Run |
|---------|-------------|-----|
| [Hello World](https://github.com/conductor-oss/java-sdk/tree/main/examples/basics/hello-world) | Minimal workflow with worker | `./gradlew :examples:run -PmainClass=com.netflix.conductor.sdk.examples.helloworld.Main` |
| [Workflow Operations](https://github.com/conductor-oss/java-sdk/tree/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/workflowops) | Pause, resume, terminate workflows | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.workflowops.Main` |
| [Shipment Workflow](https://github.com/conductor-oss/java-sdk/tree/main/examples/old/src/main/java/com/netflix/conductor/sdk/examples/shipment) | Real-world order processing | `./gradlew :examples:run -PmainClass=com.netflix.conductor.sdk.examples.shipment.Main` |
| [Events](https://github.com/conductor-oss/java-sdk/tree/main/examples/old/src/main/java/com/netflix/conductor/sdk/examples/events) | Event-driven workflows | `./gradlew :examples:run -PmainClass=com.netflix.conductor.sdk.examples.events.EventHandlerExample` |
| [All AI examples](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/agentic/AgenticExamplesRunner.java) | All agentic/LLM workflows | `./gradlew :examples:run --args="--all"` |
| [RAG Workflow](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/agentic/RagWorkflowExample.java) | RAG pipeline (index → search → answer) | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.agentic.RagWorkflowExample` |
| [Media Transcoder](https://github.com/conductor-oss/file-storage-java-sdk/tree/main/examples/file-storage/media-transcoder) | File-handling pipeline: upload video → transcode → thumbnail → manifest | `mvn -f examples/file-storage/media-transcoder/pom.xml exec:java` |
## API Journey Examples
End-to-end examples covering all APIs for each domain:
| Example | APIs | Run |
|---------|------|-----|
| [Metadata Management](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/MetadataManagement.java) | Task & workflow definitions | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.MetadataManagement` |
| [Workflow Management](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/WorkflowManagement.java) | Start, monitor, control workflows | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.WorkflowManagement` |
| [Authorization Management](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/AuthorizationManagement.java) | Users, groups, permissions | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.AuthorizationManagement` |
| [Scheduler Management](https://github.com/conductor-oss/java-sdk/blob/main/examples/old/src/main/java/io/orkes/conductor/sdk/examples/SchedulerManagement.java) | Workflow scheduling | `./gradlew :examples:run -PmainClass=io.orkes.conductor.sdk.examples.SchedulerManagement` |
## Documentation
| Document | Description |
|----------|-------------|
| [Worker SDK](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/worker_sdk.md) | Complete worker framework guide |
| [Workflow SDK](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/workflow_sdk.md) | Workflow-as-code documentation |
| [Testing Framework](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/testing_framework.md) | Unit testing workflows and workers |
| [Conductor Client](https://github.com/conductor-oss/java-sdk/blob/main/conductor-client/README.md) | HTTP client library documentation |
| [Client Metrics](https://github.com/conductor-oss/java-sdk/blob/main/conductor-client-metrics/README.md) | Prometheus metrics collection |
| [Spring Integration](https://github.com/conductor-oss/java-sdk/blob/main/conductor-client-spring/README.md) | Spring Boot auto-configuration |
| [Examples](https://github.com/conductor-oss/java-sdk/blob/main/examples/README.md) | Complete examples catalog |
## Support
- [Open an issue (SDK)](https://github.com/conductor-oss/conductor-java-sdk/issues) for SDK bugs, questions, and feature requests
- [Open an issue (Conductor server)](https://github.com/conductor-oss/conductor/issues) for Conductor OSS server issues
- [Join the Conductor Slack](https://join.slack.com/t/orkes-conductor/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA) for community discussion and help
- [Orkes Community Forum](https://community.orkes.io/) for Q&A
## Frequently Asked Questions
**Is this the same as Netflix Conductor?**
Yes. Conductor OSS is the continuation of the original [Netflix Conductor](https://github.com/Netflix/conductor) repository after Netflix contributed the project to the open-source foundation.
**Is this project actively maintained?**
Yes. [Orkes](https://orkes.io) is the primary maintainer and offers an enterprise SaaS platform for Conductor across all major cloud providers.
**Can Conductor scale to handle my workload?**
Conductor was built at Netflix to handle massive scale and has been battle-tested in production environments processing millions of workflows. It scales horizontally to meet virtually any demand.
**Does Conductor support durable code execution?**
Yes. Conductor ensures workflows complete reliably even in the face of infrastructure failures, process crashes, or network issues.
**Are workflows always asynchronous?**
No. While Conductor excels at asynchronous orchestration, it also supports synchronous workflow execution when immediate results are required.
**Do I need to use a Conductor-specific framework?**
No. Conductor is language and framework agnostic. Use your preferred language and framework -- the [SDKs](https://github.com/conductor-oss/conductor#conductor-sdks) provide native integration for Python, Java, JavaScript, Go, C#, and more.
**Can I mix workers written in different languages?**
Yes. A single workflow can have workers written in Python, Java, Go, or any other supported language. Workers communicate through the Conductor server, not directly with each other.
**What Java versions are supported?**
Java 17 and above.
**Should I use Worker interface or @WorkerTask annotation?**
Use `@WorkerTask` annotation for simpler, cleaner code -- input parameters are automatically mapped and return values become task output. Use the `Worker` interface when you need full control over task execution, access to task metadata, or custom error handling.
**How do I run workers in production?**
Workers are standard Java applications. Deploy them as you would any Java application -- in containers, VMs, or bare metal. Workers poll the Conductor server for tasks, so no inbound ports need to be opened.
**How do I test workflows without running a full Conductor server?**
The SDK provides a test framework that uses Conductor's `POST /api/workflow/test` endpoint to evaluate workflows with mock task outputs. See [Testing Framework](https://github.com/conductor-oss/java-sdk/blob/main/java-sdk/testing_framework.md) for details.
## License
Apache 2.0
## Examples
Browse all examples on GitHub: [conductor-oss/java-sdk/examples](https://github.com/conductor-oss/java-sdk/tree/main/examples)
| Example | Type |
|---|---|
| [Readme](https://github.com/conductor-oss/java-sdk/blob/main/examples/README.md) | file |
| [Examples](https://github.com/conductor-oss/java-sdk/tree/main/examples) | directory |