Skip to content

Commit 2c26d1c

Browse files
authored
Adds apikey example (temporalio#738)
* Adds apikey example
1 parent fd5bd1f commit 2c26d1c

File tree

7 files changed

+238
-1
lines changed

7 files changed

+238
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ target
1616
.classpath
1717
.project
1818
.settings/
19-
bin/
19+
bin/
20+
core/.vscode/

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ See the README.md file in each main sample directory for cut/paste Gradle comman
131131

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

134+
- [**Configure WorkflowClient to use API Key**](/core/src/main/java/io/temporal/samples/apikey): Demonstrates how to configure WorkflowClient when using API Keys.
135+
134136
- [**Payload Codec**](/core/src/main/java/io/temporal/samples/encodefailures): Demonstrates how to use simple codec to encode/decode failure messages.
135137

136138
- [**Exclude Workflow/ActivityTypes from Interceptors**](/core/src/main/java/io/temporal/samples/excludefrominterceptor): Demonstrates how to exclude certain workflow / activity types from interceptors.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.temporal.samples.apikey;
2+
3+
import io.temporal.client.WorkflowClient;
4+
import io.temporal.client.WorkflowClientOptions;
5+
import io.temporal.serviceclient.WorkflowServiceStubs;
6+
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
7+
import io.temporal.worker.Worker;
8+
import io.temporal.worker.WorkerFactory;
9+
10+
public class ApiKeyWorker {
11+
static final String TASK_QUEUE = "MyTaskQueue";
12+
13+
public static void main(String[] args) throws Exception {
14+
// For temporal cloud this would be ${cloud-region}.{cloud}.api.temporal.io:7233
15+
// Example us-east-1.aws.api.temporal.io:7233
16+
String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT");
17+
// Your registered namespace.
18+
String namespace = System.getenv("TEMPORAL_NAMESPACE");
19+
// Your API Key
20+
String apiKey = System.getenv("TEMPORAL_API_KEY");
21+
22+
if (targetEndpoint == null || namespace == null || apiKey == null) {
23+
throw new IllegalArgumentException(
24+
"TEMPORAL_ENDPOINT, TEMPORAL_NAMESPACE, and TEMPORAL_API_KEY environment variables must be set");
25+
}
26+
27+
// Create API Key enabled client
28+
WorkflowServiceStubs service =
29+
WorkflowServiceStubs.newServiceStubs(
30+
WorkflowServiceStubsOptions.newBuilder()
31+
.setTarget(targetEndpoint)
32+
.setEnableHttps(true)
33+
.addApiKey(() -> apiKey)
34+
.build());
35+
36+
// Now setup and start workflow worker
37+
WorkflowClient client =
38+
WorkflowClient.newInstance(
39+
service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());
40+
41+
// worker factory that can be used to create workers for specific task queues
42+
WorkerFactory factory = WorkerFactory.newInstance(client);
43+
44+
/*
45+
* Define the workflow worker. Workflow workers listen to a defined task queue and process
46+
* workflows and activities.
47+
*/
48+
Worker worker = factory.newWorker(TASK_QUEUE);
49+
50+
/*
51+
* Register our workflow implementation with the worker.
52+
* Workflow implementations must be known to the worker at runtime in
53+
* order to dispatch workflow tasks.
54+
*/
55+
worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);
56+
57+
/*
58+
* Start all the workers registered for a specific task queue.
59+
* The started workers then start polling for workflows and activities.
60+
*/
61+
factory.start();
62+
63+
System.out.println("Worker started. Press Ctrl+C to exit.");
64+
// Keep the worker running
65+
Thread.currentThread().join();
66+
}
67+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.temporal.samples.apikey;
2+
3+
import io.temporal.workflow.WorkflowInterface;
4+
import io.temporal.workflow.WorkflowMethod;
5+
6+
@WorkflowInterface
7+
public interface MyWorkflow {
8+
@WorkflowMethod
9+
String execute();
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.temporal.samples.apikey;
2+
3+
public class MyWorkflowImpl implements MyWorkflow {
4+
@Override
5+
public String execute() {
6+
return "done";
7+
}
8+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Workflow execution with API Key
2+
3+
This example shows how to secure your Temporal application with API Key authentication.
4+
This is required to connect with Temporal Cloud or any production Temporal deployment that uses API Key authentication.
5+
6+
## Prerequisites
7+
8+
1. A Temporal Cloud account
9+
2. A namespace in Temporal Cloud
10+
3. An API Key for your namespace
11+
12+
## Getting your API Key
13+
14+
1. Log in to your Temporal Cloud account
15+
2. Navigate to your namespace
16+
3. Go to Namespace Settings > API Keys
17+
4. Click "Create API Key"
18+
5. Give your API Key a name and select the appropriate permissions
19+
6. Copy the API Key value (you won't be able to see it again)
20+
21+
## Export env variables
22+
23+
Before running the example you need to export the following env variables:
24+
25+
```bash
26+
# Your Temporal Cloud endpoint (e.g., us-east-1.aws.api.temporal.io:7233)
27+
export TEMPORAL_ENDPOINT="us-east-1.aws.api.temporal.io:7233"
28+
29+
# Your Temporal Cloud namespace
30+
export TEMPORAL_NAMESPACE="your-namespace"
31+
32+
# Your API Key from Temporal Cloud
33+
export TEMPORAL_API_KEY="your-api-key"
34+
```
35+
36+
## Running this sample
37+
38+
This sample consists of two components that need to be run in separate terminals:
39+
40+
1. First, start the worker:
41+
```bash
42+
./gradlew -q execute -PmainClass=io.temporal.samples.apikey.ApiKeyWorker
43+
```
44+
45+
2. Then, in a new terminal, run the starter:
46+
```bash
47+
./gradlew -q execute -PmainClass=io.temporal.samples.apikey.Starter
48+
```
49+
50+
## Expected result
51+
52+
When running the worker, you should see:
53+
```text
54+
[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=us-east-1.aws.api.temporal.io:7233}}
55+
[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="your-namespace"}
56+
Worker started. Press Ctrl+C to exit.
57+
```
58+
59+
When running the starter, you should see:
60+
```text
61+
[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=us-east-1.aws.api.temporal.io:7233}}
62+
[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="your-namespace"}
63+
done
64+
```
65+
66+
## Troubleshooting
67+
68+
If you encounter any issues:
69+
70+
1. Verify your environment variables are set correctly:
71+
```bash
72+
echo $TEMPORAL_ENDPOINT
73+
echo $TEMPORAL_NAMESPACE
74+
echo $TEMPORAL_API_KEY
75+
```
76+
77+
2. Check that your API Key has the correct permissions for your namespace
78+
79+
3. Ensure your namespace is active and accessible
80+
81+
4. If you get connection errors, verify your endpoint is correct and accessible from your network
82+
83+
5. Make sure you're running the commands from the correct directory (where the `gradlew` script is located)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.temporal.samples.apikey;
2+
3+
import io.temporal.client.WorkflowClient;
4+
import io.temporal.client.WorkflowClientOptions;
5+
import io.temporal.client.WorkflowOptions;
6+
import io.temporal.serviceclient.WorkflowServiceStubs;
7+
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
8+
import io.temporal.worker.Worker;
9+
import io.temporal.worker.WorkerFactory;
10+
11+
public class Starter {
12+
13+
static final String TASK_QUEUE = "MyTaskQueue";
14+
static final String WORKFLOW_ID = "HelloAPIKeyWorkflow";
15+
16+
public static void main(String[] args) throws Exception {
17+
// For temporal cloud this would be ${cloud-region}.{cloud}.api.temporal.io:7233
18+
// Example us-east-1.aws.api.temporal.io:7233
19+
String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT");
20+
// Your registered namespace.
21+
String namespace = System.getenv("TEMPORAL_NAMESPACE");
22+
// Your API Key
23+
String apiKey = System.getenv("TEMPORAL_API_KEY");
24+
25+
if (targetEndpoint == null || namespace == null || apiKey == null) {
26+
throw new IllegalArgumentException(
27+
"TEMPORAL_ENDPOINT, TEMPORAL_NAMESPACE, and TEMPORAL_API_KEY environment variables must be set");
28+
}
29+
30+
// Create API Key enabled client
31+
WorkflowServiceStubs service =
32+
WorkflowServiceStubs.newServiceStubs(
33+
WorkflowServiceStubsOptions.newBuilder()
34+
.setTarget(targetEndpoint)
35+
.setEnableHttps(true)
36+
.addApiKey(() -> apiKey)
37+
.build());
38+
39+
WorkflowClient client =
40+
WorkflowClient.newInstance(
41+
service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());
42+
43+
WorkerFactory factory = WorkerFactory.newInstance(client);
44+
45+
Worker worker = factory.newWorker(TASK_QUEUE);
46+
47+
worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);
48+
49+
factory.start();
50+
51+
// Create the workflow client stub. It is used to start our workflow execution.
52+
MyWorkflow workflow =
53+
client.newWorkflowStub(
54+
MyWorkflow.class,
55+
WorkflowOptions.newBuilder()
56+
.setWorkflowId(WORKFLOW_ID)
57+
.setTaskQueue(TASK_QUEUE)
58+
.build());
59+
60+
String greeting = workflow.execute();
61+
62+
// Display workflow execution results
63+
System.out.println(greeting);
64+
System.exit(0);
65+
}
66+
}

0 commit comments

Comments
 (0)