Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ target
.classpath
.project
.settings/
bin/
bin/
core/.vscode/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ See the README.md file in each main sample directory for cut/paste Gradle comman

- [**Configure WorkflowClient to use mTLS**](/core/src/main/java/io/temporal/samples/ssl): Demonstrates how to configure WorkflowClient when using mTLS.

- [**Configure WorkflowClient to use API Key**](/core/src/main/java/io/temporal/samples/apikey): Demonstrates how to configure WorkflowClient when using API Keys.

- [**Payload Codec**](/core/src/main/java/io/temporal/samples/encodefailures): Demonstrates how to use simple codec to encode/decode failure messages.

- [**Exclude Workflow/ActivityTypes from Interceptors**](/core/src/main/java/io/temporal/samples/excludefrominterceptor): Demonstrates how to exclude certain workflow / activity types from interceptors.
Expand Down
67 changes: 67 additions & 0 deletions core/src/main/java/io/temporal/samples/apikey/ApiKeyWorker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.temporal.samples.apikey;

import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import io.temporal.worker.Worker;
import io.temporal.worker.WorkerFactory;

public class ApiKeyWorker {
static final String TASK_QUEUE = "MyTaskQueue";

public static void main(String[] args) throws Exception {
// For temporal cloud this would be ${cloud-region}.{cloud}.api.temporal.io:7233
// Example us-east-1.aws.api.temporal.io:7233
String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT");
// Your registered namespace.
String namespace = System.getenv("TEMPORAL_NAMESPACE");
// Your API Key
String apiKey = System.getenv("TEMPORAL_API_KEY");

if (targetEndpoint == null || namespace == null || apiKey == null) {
throw new IllegalArgumentException(
"TEMPORAL_ENDPOINT, TEMPORAL_NAMESPACE, and TEMPORAL_API_KEY environment variables must be set");
}

// Create API Key enabled client
WorkflowServiceStubs service =
WorkflowServiceStubs.newServiceStubs(
WorkflowServiceStubsOptions.newBuilder()
.setTarget(targetEndpoint)
.setEnableHttps(true)
.addApiKey(() -> apiKey)
.build());

// Now setup and start workflow worker
WorkflowClient client =
WorkflowClient.newInstance(
service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());

// worker factory that can be used to create workers for specific task queues
WorkerFactory factory = WorkerFactory.newInstance(client);

/*
* Define the workflow worker. Workflow workers listen to a defined task queue and process
* workflows and activities.
*/
Worker worker = factory.newWorker(TASK_QUEUE);

/*
* Register our workflow implementation with the worker.
* Workflow implementations must be known to the worker at runtime in
* order to dispatch workflow tasks.
*/
worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);

/*
* Start all the workers registered for a specific task queue.
* The started workers then start polling for workflows and activities.
*/
factory.start();

System.out.println("Worker started. Press Ctrl+C to exit.");
// Keep the worker running
Thread.currentThread().join();
}
}
10 changes: 10 additions & 0 deletions core/src/main/java/io/temporal/samples/apikey/MyWorkflow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.temporal.samples.apikey;

import io.temporal.workflow.WorkflowInterface;
import io.temporal.workflow.WorkflowMethod;

@WorkflowInterface
public interface MyWorkflow {
@WorkflowMethod
String execute();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.temporal.samples.apikey;

public class MyWorkflowImpl implements MyWorkflow {
@Override
public String execute() {
return "done";
}
}
83 changes: 83 additions & 0 deletions core/src/main/java/io/temporal/samples/apikey/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Workflow execution with API Key

This example shows how to secure your Temporal application with API Key authentication.
This is required to connect with Temporal Cloud or any production Temporal deployment that uses API Key authentication.

## Prerequisites

1. A Temporal Cloud account
2. A namespace in Temporal Cloud
3. An API Key for your namespace

## Getting your API Key

1. Log in to your Temporal Cloud account
2. Navigate to your namespace
3. Go to Namespace Settings > API Keys
4. Click "Create API Key"
5. Give your API Key a name and select the appropriate permissions
6. Copy the API Key value (you won't be able to see it again)

## Export env variables

Before running the example you need to export the following env variables:

```bash
# Your Temporal Cloud endpoint (e.g., us-east-1.aws.api.temporal.io:7233)
export TEMPORAL_ENDPOINT="us-east-1.aws.api.temporal.io:7233"

# Your Temporal Cloud namespace
export TEMPORAL_NAMESPACE="your-namespace"

# Your API Key from Temporal Cloud
export TEMPORAL_API_KEY="your-api-key"
```

## Running this sample

This sample consists of two components that need to be run in separate terminals:

1. First, start the worker:
```bash
./gradlew -q execute -PmainClass=io.temporal.samples.apikey.ApiKeyWorker
```

2. Then, in a new terminal, run the starter:
```bash
./gradlew -q execute -PmainClass=io.temporal.samples.apikey.Starter
```

## Expected result

When running the worker, you should see:
```text
[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=us-east-1.aws.api.temporal.io:7233}}
[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="your-namespace"}
Worker started. Press Ctrl+C to exit.
```

When running the starter, you should see:
```text
[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=us-east-1.aws.api.temporal.io:7233}}
[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="your-namespace"}
done
```

## Troubleshooting

If you encounter any issues:

1. Verify your environment variables are set correctly:
```bash
echo $TEMPORAL_ENDPOINT
echo $TEMPORAL_NAMESPACE
echo $TEMPORAL_API_KEY
```

2. Check that your API Key has the correct permissions for your namespace

3. Ensure your namespace is active and accessible

4. If you get connection errors, verify your endpoint is correct and accessible from your network

5. Make sure you're running the commands from the correct directory (where the `gradlew` script is located)
66 changes: 66 additions & 0 deletions core/src/main/java/io/temporal/samples/apikey/Starter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.temporal.samples.apikey;

import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.client.WorkflowOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import io.temporal.worker.Worker;
import io.temporal.worker.WorkerFactory;

public class Starter {

static final String TASK_QUEUE = "MyTaskQueue";
static final String WORKFLOW_ID = "HelloAPIKeyWorkflow";

public static void main(String[] args) throws Exception {
// For temporal cloud this would be ${cloud-region}.{cloud}.api.temporal.io:7233
// Example us-east-1.aws.api.temporal.io:7233
String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT");
// Your registered namespace.
String namespace = System.getenv("TEMPORAL_NAMESPACE");
// Your API Key
String apiKey = System.getenv("TEMPORAL_API_KEY");

if (targetEndpoint == null || namespace == null || apiKey == null) {
throw new IllegalArgumentException(
"TEMPORAL_ENDPOINT, TEMPORAL_NAMESPACE, and TEMPORAL_API_KEY environment variables must be set");
}

// Create API Key enabled client
WorkflowServiceStubs service =
WorkflowServiceStubs.newServiceStubs(
WorkflowServiceStubsOptions.newBuilder()
.setTarget(targetEndpoint)
.setEnableHttps(true)
.addApiKey(() -> apiKey)
.build());

WorkflowClient client =
WorkflowClient.newInstance(
service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());

WorkerFactory factory = WorkerFactory.newInstance(client);

Worker worker = factory.newWorker(TASK_QUEUE);

worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);

factory.start();

// Create the workflow client stub. It is used to start our workflow execution.
MyWorkflow workflow =
client.newWorkflowStub(
MyWorkflow.class,
WorkflowOptions.newBuilder()
.setWorkflowId(WORKFLOW_ID)
.setTaskQueue(TASK_QUEUE)
.build());

String greeting = workflow.execute();

// Display workflow execution results
System.out.println(greeting);
System.exit(0);
}
}
Loading