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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ See the README.md file in each main sample directory for cut/paste Gradle comman
- [**HelloSignalWithTimer**](/core/src/main/java/io/temporal/samples/hello/HelloSignalWithTimer.java): Demonstrates how to use collect signals for certain amount of time and then process last one.
- [**HelloWorkflowTimer**](/core/src/main/java/io/temporal/samples/hello/HelloWorkflowTimer.java): Demonstrates how we can use workflow timer to restrict duration of workflow execution instead of workflow run/execution timeouts.
- [**Auto-Heartbeating**](/core/src/main/java/io/temporal/samples/autoheartbeat/): Demonstrates use of Auto-heartbeating utility via activity interceptor.

- [**HelloSignalWithStartAndWorkflowInit**](/core/src/main/java/io/temporal/samples/hello/HelloSignalWithStartAndWorkflowInit.java): Demonstrates how WorkflowInit can be useful with SignalWithStart to initialize workflow variables.

#### Scenario-based samples

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package io.temporal.samples.hello;

import io.temporal.activity.ActivityInterface;
import io.temporal.activity.ActivityOptions;
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowFailedException;
import io.temporal.client.WorkflowOptions;
import io.temporal.client.WorkflowStub;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.worker.Worker;
import io.temporal.worker.WorkerFactory;
import io.temporal.worker.WorkflowImplementationOptions;
import io.temporal.workflow.*;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;

/**
* Sample Temporal workflow that demonstrates how to use WorkflowInit with clients starting
* execution using SignalWithStart
*/
public class HelloSignalWithStartAndWorkflowInit {
static final String TASK_QUEUE = "HelloWithInitTaskQueue";

public interface MyWorkflow {
@WorkflowMethod
String greet(Person person);

@SignalMethod
void addGreeting(Person person);
}

@WorkflowInterface
public interface MyWorkflowWithInit extends MyWorkflow {}

@WorkflowInterface
public interface MyWorkflowNoInit extends MyWorkflow {}

public static class WithInitMyWorkflowImpl implements MyWorkflowWithInit {
// We dont initialize peopleToGreet on purpose
private List<Person> peopleToGreet;
private MyGreetingActivities activities =
Workflow.newActivityStub(
MyGreetingActivities.class,
ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(2)).build());

@WorkflowInit
public WithInitMyWorkflowImpl(Person person) {
peopleToGreet = new ArrayList<>();
}

@Override
public String greet(Person person) {
peopleToGreet.add(person);
List<String> greetings = new ArrayList<>();

while (!peopleToGreet.isEmpty()) {
// run activity...
greetings.add(activities.greet(peopleToGreet.get(0)));
peopleToGreet.remove(0);
}
return StringUtils.join(greetings, ",");
}

@Override
public void addGreeting(Person person) {
peopleToGreet.add(person);
}
}

public static class WithoutInitMyWorkflowImpl implements MyWorkflowNoInit {
// We dont initialize peopleToGreet on purpose
private List<Person> peopleToGreet;
private MyGreetingActivities activities =
Workflow.newActivityStub(
MyGreetingActivities.class,
ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(2)).build());

@Override
public String greet(Person person) {
peopleToGreet.add(person);
List<String> greetings = new ArrayList<>();

while (!peopleToGreet.isEmpty()) {
// run activity...
greetings.add(activities.greet(peopleToGreet.get(0)));
peopleToGreet.remove(0);
}
return StringUtils.join(greetings, ",");
}

@Override
public void addGreeting(Person person) {
peopleToGreet.add(person);
}
}

@ActivityInterface
public interface MyGreetingActivities {
public String greet(Person person);
}

public static class MyGreetingActivitiesImpl implements MyGreetingActivities {
@Override
public String greet(Person person) {
return "Hello " + person.firstName + " " + person.lastName;
}
}

public static class Person {
String firstName;
String lastName;
int age;

public Person() {}

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

public static void main(String[] args) {
WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();
WorkflowClient client = WorkflowClient.newInstance(service);
WorkerFactory factory = WorkerFactory.newInstance(client);
Worker worker = factory.newWorker(TASK_QUEUE);

worker.registerWorkflowImplementationTypes(WithInitMyWorkflowImpl.class);
// We explicitly want to fail this workflow on NPE as thats what we expect without WorkflowInit
// As we didnt initialize peopleToGreet on purpose
worker.registerWorkflowImplementationTypes(
WorkflowImplementationOptions.newBuilder()
.setFailWorkflowExceptionTypes(NullPointerException.class)
.build(),
WithoutInitMyWorkflowImpl.class);
worker.registerActivitiesImplementations(new MyGreetingActivitiesImpl());

factory.start();

MyWorkflowWithInit withInitStub =
client.newWorkflowStub(
MyWorkflowWithInit.class,
WorkflowOptions.newBuilder()
.setWorkflowId("with-init")
.setTaskQueue(TASK_QUEUE)
.build());
// Start with init workflow which is expected to succeed
// As WorkflowInit will initialize peopleToGreet before signal handler is invoked
WorkflowStub.fromTyped(withInitStub)
.signalWithStart(
"addGreeting",
new Object[] {new Person("Michael", "Jordan", 55)},
new Object[] {new Person("John", "Stockton", 57)});

String result = WorkflowStub.fromTyped(withInitStub).getResult(String.class);
System.out.println("Result: " + result);

// Start without init, this execution is expected to fail as we set
// NullPointerException as a workflow failure type
// NPE is caused because we did not initialize peopleToGreet array
MyWorkflowNoInit noInitStub =
client.newWorkflowStub(
MyWorkflowNoInit.class,
WorkflowOptions.newBuilder()
.setWorkflowId("without-init")
.setTaskQueue(TASK_QUEUE)
.build());
WorkflowStub.fromTyped(noInitStub)
.signalWithStart(
"addGreeting",
new Object[] {new Person("Michael", "Jordan", 55)},
new Object[] {new Person("John", "Stockton", 57)});
try {
WorkflowStub.fromTyped(noInitStub).getResult(String.class);
} catch (WorkflowFailedException e) {
System.out.println("Expected workflow failure: " + e.getMessage());
}

System.exit(0);
}
}
1 change: 1 addition & 0 deletions core/src/main/java/io/temporal/samples/hello/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ To run each hello world sample, use one of the following commands:
./gradlew -q execute -PmainClass=io.temporal.samples.hello.HelloSideEffect
./gradlew -q execute -PmainClass=io.temporal.samples.hello.HelloUpdate
./gradlew -q execute -PmainClass=io.temporal.samples.hello.HelloSignalWithTimer
./gradlew -q execute -PmainClass=io.temporal.samples.hello.HelloSignalWithStartAndWorkflowInit
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.temporal.samples.hello;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import io.temporal.client.WorkflowFailedException;
import io.temporal.client.WorkflowOptions;
import io.temporal.client.WorkflowStub;
import io.temporal.testing.TestWorkflowEnvironment;
import io.temporal.testing.TestWorkflowExtension;
import io.temporal.worker.Worker;
import io.temporal.worker.WorkflowImplementationOptions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class HelloSignalWithStartAndWorkflowInitTest {
@RegisterExtension
public static final TestWorkflowExtension testWorkflowExtension =
TestWorkflowExtension.newBuilder()
.registerWorkflowImplementationTypes(
HelloSignalWithStartAndWorkflowInit.WithInitMyWorkflowImpl.class)
.registerWorkflowImplementationTypes(
WorkflowImplementationOptions.newBuilder()
.setFailWorkflowExceptionTypes(NullPointerException.class)
.build(),
HelloSignalWithStartAndWorkflowInit.WithoutInitMyWorkflowImpl.class)
.setActivityImplementations(
new HelloSignalWithStartAndWorkflowInit.MyGreetingActivitiesImpl())
.build();

@Test
public void testWithInit(TestWorkflowEnvironment testEnv, Worker worker) {
HelloSignalWithStartAndWorkflowInit.MyWorkflowWithInit withInitStub =
testEnv
.getWorkflowClient()
.newWorkflowStub(
HelloSignalWithStartAndWorkflowInit.MyWorkflowWithInit.class,
WorkflowOptions.newBuilder()
.setWorkflowId("with-init")
.setTaskQueue(worker.getTaskQueue())
.build());
WorkflowStub.fromTyped(withInitStub)
.signalWithStart(
"addGreeting",
new Object[] {new HelloSignalWithStartAndWorkflowInit.Person("Michael", "Jordan", 55)},
new Object[] {new HelloSignalWithStartAndWorkflowInit.Person("John", "Stockton", 57)});
String result = WorkflowStub.fromTyped(withInitStub).getResult(String.class);
assertEquals("Hello Michael Jordan,Hello John Stockton", result);
}

@Test
public void testWithoutInit(TestWorkflowEnvironment testEnv, Worker worker) {
HelloSignalWithStartAndWorkflowInit.MyWorkflowNoInit noInitStub =
testEnv
.getWorkflowClient()
.newWorkflowStub(
HelloSignalWithStartAndWorkflowInit.MyWorkflowNoInit.class,
WorkflowOptions.newBuilder()
.setWorkflowId("without-init")
.setTaskQueue(worker.getTaskQueue())
.build());
WorkflowStub.fromTyped(noInitStub)
.signalWithStart(
"addGreeting",
new Object[] {new HelloSignalWithStartAndWorkflowInit.Person("Michael", "Jordan", 55)},
new Object[] {new HelloSignalWithStartAndWorkflowInit.Person("John", "Stockton", 57)});
try {
WorkflowStub.fromTyped(noInitStub).getResult(String.class);
fail("Workflow execution should have failed");
} catch (Exception e) {
if (!(e instanceof WorkflowFailedException)) {
fail("Workflow execution should have failed with WorkflowFailedException");
}
}
}
}
Loading