Skip to main content
Temporal Java SDK

About this example

Free previewTemporal 101Java
  1. About this example
  2. Code walkthrough

In a previous exercise, you executed a Workflow with two Activities that each called a microservice to provide a customized message in Spanish. That exercise demonstrated many of the key concepts in this course. Now that you have first-hand experience developing and running applications on the Temporal Platform, you'll gain a deeper understanding by looking at what happens during Workflow Execution.

Actors in the scenario

Let's begin by identifying the actors in this scenario, which reiterates some important concepts.

First, the example includes a Worker, which executes the Workflow and Activity code and uses a Client to communicate with the Cluster.

Next, the Temporal Cluster orchestrates the execution of that code by coordinating with the Worker, using a shared Task Queue.

Finally, the program that starts the Workflow - referred to as a Client application because it requests Workflow Execution as well as the result from the Temporal Cluster - uses a Client to do this.

Screenshot showing actors in Workflow execution scenario

Workers and Task Queues

The assignment of work is indirect. The Temporal Cluster does not assign tasks to a Worker - in fact, the Temporal Cluster does not maintain a list of Workers.

Instead, Workers continually poll the Temporal Cluster's Task Queue and accept tasks when they have spare capacity to process them. There are several benefits to this approach, but one of them is that tasks will just sit in the queue if there aren't enough Workers, which means that you can increase throughput and scalability by adding more Workers.

Screenshot showing Workers and tasks

As you learned earlier, Temporal applications in production will typically have multiple Workers; however, this example uses a single Worker for the sake of simplicity.

Commands and recovery

Another thing that will help you understand Temporal is the role of Commands. When the Worker encounters certain API calls during Workflow Execution, such as a call to the Workflow's method to execute an Activity, it sends a Command to the Temporal Cluster. The Cluster acts on these Commands - for example, by creating an Activity Task - but also stores them in case of failure.

For example, if the Worker crashes, the Temporal Service sends the stored information to another Worker to recreate the state of the Workflow to what it was immediately before the crash, and the new Worker resumes progress from that point. This allows you, as a developer, to code as if this type of failure wasn't even a possibility.

Screenshot showing Commands

Activity Definitions

The application defines two Activities, greetInSpanish and farewellInSpanish, plus a utility method that both Activities use to call the translation service.

GreetingActivities.java
package farewellworkflow;

// non-Temporal imports omitted here for brevity
import io.temporal.activity.ActivityInterface;
import io.temporal.activity.Activity;

@ActivityInterface
public interface GreetingActivities {
String greetInSpanish(String name);

String farewellInSpanish(String name);
}

class GreetingActivitiesImpl implements GreetingActivities {

@Override
public String greetInSpanish(String name) {
return callService("get-spanish-greeting", name);
}

@Override
public String farewellInSpanish(String name) {
return callService("get-spanish-farewell", name);
}

String callService(String stem, String name) {
String baseUrl = "http://localhost:9999/%s?name=%s";

URL url = null;
try {
url = new URL(String.format(baseUrl, stem, URLEncoder.encode(name, "UTF-8")));
} catch (IOException e) {
throw Activity.wrap(e);
}
// code that uses this URL to call the service has been ommitted here
}
}

Workflow Definition

The Workflow Definition executes those two Activities and returns a String created from their output.

GreetingWorkflow.java
package farewellworkflow;

import io.temporal.workflow.WorkflowInterface;
import io.temporal.workflow.WorkflowMethod;
import io.temporal.activity.ActivityOptions;
import io.temporal.workflow.Workflow;

import java.time.Duration;

@WorkflowInterface
public interface GreetingWorkflow {

@WorkflowMethod
String greetSomeone(String name);

}

class GreetingWorkflowImpl implements GreetingWorkflow {

private final ActivityOptions options = ActivityOptions.newBuilder()
.setStartToCloseTimeout(Duration.ofSeconds(5))
.build();

private final GreetingActivities activities =
Workflow.newActivityStub(GreetingActivities.class, options);

@Override
public String greetSomeone(String name) {
String spanishGreeting = activities.greetInSpanish(name);
String spanishFarewell = activities.farewellInSpanish(name);

return "\n" + spanishGreeting + "\n" + spanishFarewell;
}
}

Worker initialization

And here's the Worker initialization code, which registers the Workflow and Activity Definitions.

GreetingWorker.java
package farewellworkflow;

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

public class GreetingWorker {

public static void main(String[] args) {

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

Worker worker = factory.newWorker("greeting-tasks");

worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);

worker.registerActivitiesImplementations(new GreetingActivitiesImpl());

factory.start();
}
}
What's next

In this course, you saw how the parts of a Temporal Application - a Worker, the Temporal Cluster, and the Client Application - work together during a Workflow Execution. In the next video, you'll see how all the parts work together via a code walkthrough.

Get notified when we launch new educational content

New courses, tutorials, and learning resources - straight to your inbox.

Subscribe
Feedback