Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exercise 2 - Sending Signals Client #2

Merged
merged 5 commits into from
Apr 29, 2024
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
1 change: 1 addition & 0 deletions .bash_aliases
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ alias ex2s="cd ${GITPOD_REPO_ROOT}/exercises/querying-workflows/solution"
alias ex2w="mvn exec:java -Dexec.mainClass='queryingworkflows.QueryingWorkflowsWorker'"
alias ex2st="mvn exec:java -Dexec.mainClass='queryingworkflows.Starter'"
alias ex2sg="mvn exec:java -Dexec.mainClass='queryingworkflows.SignalClient'"
alias ex2q="mvn exec:java -Dexec.mainClass='queryingworkflows.QueryClient'"


alias ex3="cd ${GITPOD_REPO_ROOT}/exercises/async-activity-completion/practice"
Expand Down
66 changes: 66 additions & 0 deletions exercises/sending-signals-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Exercise #2: Sending a Signal from the Client

This exercise shows how to send a Signal from just the Client and not from another Workflow.

During this exercise, you will:

- Retrieve a stub on a running Workflow to Signal
- Send a Signal from the Client

In this part of the exercise, we have removed the `FulfillOrderWorkflow` Workflow from the previous exercise, since this exercise is just for sending a Signal from a Client, and not from another Workflow.

We will skip the defining and handling of `FulfillOrderSignal` that were handled in `src/main/java/sendingsignalsclient/orderpizza`. This exercise will solely focus on the Client file.

### GitPod Environment Shortcuts

If you are executing the exercises in the provided GitPod environment, you
can take advantage of certain aliases to aid in navigation and execution of
the code.

| Command | Action |
| :------ | :--------------------------------------------------------------------------------------------------------------------------------- |
| `ex2` | Change to Exercise 1 Practice Directory |
| `ex2s` | Change to Exercise 1 Solution Directory |
| `ex2w` | Execute the Exercise 1 Worker. Must be within the appropriate directory for this to succeed. (either `practice` or `solution`) |
| `ex2st` | Execute the Exercise 1 Starter. Must be within the appropriate directory for this to succeed. (either `practice` or `solution`) |
| `ex2sg` | Send the Exercise 1 Signal. Must be within the appropriate directory for this to succeed. (either `practice` or `solution`) |


## Part A: Create a Stub on the Pizza Workflow

In this part of the exercise, you will create a stub on the Workflow that you wish to Signal, which is `PizzaWorkflow`.

1. Recall that the Workflow ID for this Workflow is `pizza-workflow-order-XD001`.
1. Edit the `SignalClient.java` in the `src/main/java/sendingsignalsclient` subdirectory and modify the `newWorkflowStub()` method to get a stub of a running workflow.
1. Change the Workflow ID from `CHANGE_ME` to the Workflow ID of the running Workflow.
1. Save the file.

## Part B: Sending a Signal to the Pizza Workflow

Now that you have a stub on the Workflow you wish to Signal (`PizzaWorkflow`), we will now send `fulfillOrderSignal`.

1. Continue editing the `SignalClient.java` in the `src/main/java/sendingsignalsclient` subdirectory.
1. Using the stub defined above, send the signal by calling the `fulfillOrderSignal()` method, passing `true` as a parameter.
1. Save the file.


## Part C: Run the Workflow

To run the Workflow:

1. In all terminals, change directories to the Exercise 2 directory.
1. If you're in the GitPod environment, you can run `ex2`
1. In one terminal, start the Worker by running `mvn exec:java -Dexec.mainClass="sendingsignalsclient.SendSignalClientWorker"`.
1. If you're in the GitPod environment, you can instead run `ex2w` to start the worker
1. In another terminal, start the Workflow by running `mvn exec:java -Dexec.mainClass="sendingsignalsclient.Starter"`. This will start the Workflow, which you will see waiting for a Signal.
1. If you're in the GitPod environment, you can instead run `ex2st` to start the Workflow
1. In another terminal, send the signal by running `mvn exec:java -Dexec.mainClass="sendingsignalsclient.SignalClient"`
1. If you're in the GitPod environment, you can instead run `ex2sg` to send the Signal
1. You should see the following output in the terminal where you ran the Starter:

```bash
09:41:34.326 INFO - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=127.0.0.1:7233}}
Workflow result: OrderConfirmation{orderNumber='XD001', status='SUCCESS', confirmationNumber='P24601', billingTimestamp=1712500897, amount=3500}
```

### This is the end of the exercise.
109 changes: 109 additions & 0 deletions exercises/sending-signals-client/practice/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.temporal.learn</groupId>
<artifactId>sending-signals-client</artifactId>
<version>1.0.0-SNAPSHOT</version>

<name>sending signals client</name>
<url>https://learn.temporal.io/</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>

<dependency>
<groupId>io.temporal</groupId>
<artifactId>temporal-sdk</artifactId>
<version>1.20.1</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.8</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>

<dependency>
<groupId>io.temporal</groupId>
<artifactId>temporal-testing</artifactId>
<version>1.20.1</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sendingsignalsclient;

public class Constants {

public static final String TASK_QUEUE_NAME = "pizza-tasks";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package sendingsignalsclient;

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

import sendingsignalsclient.orderpizza.PizzaActivitiesImpl;
import sendingsignalsclient.orderpizza.PizzaWorkflowImpl;

public class SendSignalClientWorker {
public static void main(String[] args) {

WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();
WorkflowClient client = WorkflowClient.newInstance(service);
WorkerFactory factory = WorkerFactory.newInstance(client);

Worker worker = factory.newWorker(Constants.TASK_QUEUE_NAME);

worker.registerWorkflowImplementationTypes(PizzaWorkflowImpl.class);

worker.registerActivitiesImplementations(new PizzaActivitiesImpl());

factory.start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package sendingsignalsclient;

import io.temporal.client.WorkflowClient;
import io.temporal.serviceclient.WorkflowServiceStubs;
import sendingsignalsclient.orderpizza.PizzaWorkflow;


public class SignalClient {
public static void main(String[] args) throws Exception {

WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();

WorkflowClient client = WorkflowClient.newInstance(service);

// TODO: PART A: Set Workflow ID
PizzaWorkflow workflow = client.newWorkflowStub(PizzaWorkflow.class, "CHANGE_ME");

// TODO: PART A: Call fulfillOrderSignal, passing `true`

System.exit(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package sendingsignalsclient;

import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowOptions;
import java.util.concurrent.CompletableFuture;
import io.temporal.serviceclient.WorkflowServiceStubs;

import sendingsignalsclient.model.PizzaOrder;
import sendingsignalsclient.model.Pizza;
import sendingsignalsclient.model.Customer;
import sendingsignalsclient.model.OrderConfirmation;
import sendingsignalsclient.model.Address;
import sendingsignalsclient.orderpizza.PizzaWorkflow;

import java.util.Arrays;
import java.util.List;

public class Starter {
public static void main(String[] args) throws Exception {

WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();

WorkflowClient client = WorkflowClient.newInstance(service);

PizzaOrder order = createPizzaOrder();

// Setup the Pizza Order Workflow Client
String pizzaWorkflowID = String.format("pizza-workflow-order-%s", order.getOrderNumber());

WorkflowOptions pizzaWorkflowOptions = WorkflowOptions.newBuilder()
.setWorkflowId(pizzaWorkflowID)
.setTaskQueue(Constants.TASK_QUEUE_NAME)
.build();

PizzaWorkflow pizzaWorkflow = client.newWorkflowStub(PizzaWorkflow.class, pizzaWorkflowOptions);

OrderConfirmation orderConfirmation = pizzaWorkflow.orderPizza(order);
//CompletableFuture<OrderConfirmation> orderConfirmation = WorkflowClient.execute(pizzaWorkflow::orderPizza, order);


System.out.printf("Workflow result: %s\n", orderConfirmation);
System.exit(0);
}

private static PizzaOrder createPizzaOrder() {
Customer customer = new Customer(8675309, "Lisa Anderson", "[email protected]", "555-555-0000");
Address address = new Address("742 Evergreen Terrace", "Apartment 221B", "Albuquerque", "NM", "87101");
Pizza pizza1 = new Pizza("Large, with mushrooms and onions", 1500);
Pizza pizza2 = new Pizza("Small, with pepperoni", 1200);
Pizza pizza3 = new Pizza("Medium, with extra cheese", 1300);

List<Pizza> orderList = Arrays.asList(pizza1, pizza2, pizza3);

PizzaOrder order = new PizzaOrder("XD001", customer, orderList, true, address);

return order;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package sendingsignalsclient.exceptions;

public class InvalidChargeAmountException extends Exception {

public InvalidChargeAmountException() {
super();
}

public InvalidChargeAmountException(String message) {
super(message);
}

public InvalidChargeAmountException(String message, Throwable cause) {
super(message, cause);
}

public InvalidChargeAmountException(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package sendingsignalsclient.exceptions;

public class OutOfServiceAreaException extends Exception {

public OutOfServiceAreaException() {
super();
}

public OutOfServiceAreaException(String message) {
super(message);
}

public OutOfServiceAreaException(String message, Throwable cause) {
super(message, cause);
}

public OutOfServiceAreaException(Throwable cause) {
super(cause);
}
}
Loading