Skip to content

Latest commit

 

History

History
240 lines (185 loc) · 8.92 KB

File metadata and controls

240 lines (185 loc) · 8.92 KB

Temporal Spring Boot

The following Readme assumes that you use Spring Boot yml configuration files (application.yml). It should be trivial to adjust if your application uses .properties configuration. Your application should be a @SpringBootApplication and have io.temporal:temporal-spring-boot-starter-alpha:${temporalVersion} added as a dependency.

Samples

The Java SDK samples repo contains a number of Spring Boot samples that use this module.

Connection setup

The following configuration connects to a locally started Temporal Server (see Temporal Docker Compose or Temporalite)

spring.temporal:
  connection:
    target: local # you can specify a host:port here for a remote connection
    # specifying local is equivalent to WorkflowServiceStubs.newLocalServiceStubs() so all other connection options are ignored. 
    # enable-https: true
  # namespace: default # you can specify a custom namespace that you are using

This will be enough to be able to autowire a WorkflowClient in your SpringBoot app:

@SpringBootApplication
class App {
  @Autowire
  private WorkflowClient workflowClient;
}

If you are working with schedules, you can also autowire ScheduleClient in your SpringBoot app:

@SpringBootApplication
class App {
  @Autowire
  private ScheduleClient scheduleClient;
}

mTLS

Generate PKCS8 or PKCS12 files. Add the following to your application.yml file:

spring.temporal:
  connection:
    mtls:
      key-file: /path/to/key.key
      cert-chain-file: /path/to/cert.pem # If you use PKCS12 (.pkcs12, .pfx or .p12), you don't need to set it because certificates chain is bundled into the key file
      # key-password: <password_for_the_key>
      # insecure-trust-manager: true # or add ca.pem to java default truststore
      # server-name: <server_name_override> # optional server name overrider, used as authority of ManagedChannelBuilder

Alternatively with PKCS8 you can pass the content of the key and certificates chain as strings, which allows to pass them from the environment variable for example:

spring.temporal:
  connection:
    mtls:
      key: <raw content of the key PEM file>
      cert-chain: <raw content of the cert chain PEM file>
      # key-password: <password_for_the_key>
      # insecure-trust-manager: true # or add ca.pem to java default truststore

Data Converter

Define a bean of type io.temporal.common.converter.DataConverter in Spring context to be used as a custom data converter. If Spring context has several beans of the DataConverter type, the context will fail to start. You need to name one of them mainDataConverter to resolve ambiguity.

Workers configuration

There are two ways of configuring workers. Auto-discovery and an explicit configuration.

Explicit configuration

Follow the pattern to explicitly configure the workers:

spring.temporal:
  workers:
    - task-queue: your-task-queue-name
      name: your-worker-name # unique name of the Worker. If not specified, Task Queue is used as the Worker name.
      workflow-classes:
        - your.package.YouWorkflowImpl
      activity-beans:
        - activity-bean-name1
Extended Workers configuration example
spring.temporal:
  workers:
    - task-queue: your-task-queue-name
      # name: your-worker-name # unique name of the Worker. If not specified, Task Queue is used as the Worker name.
      workflow-classes:
        - your.package.YouWorkflowImpl
      activity-beans:
        - activity-bean-name1
      # capacity:
        # max-concurrent-workflow-task-executors: 200
        # max-concurrent-activity-executors: 200
        # max-concurrent-local-activity-executors: 200
        # max-concurrent-workflow-task-pollers: 5
        # max-concurrent-activity-task-pollers: 5
      # rate-limits:
        # max-worker-activities-per-second: 5.0
        # max-task-queue-activities-per-second: 5.0
      # build-id:
        # worker-build-id: "1.0.0"
  # workflow-cache:
    # max-instances: 600
    # max-threads: 600
  # start-workers: false # disable auto-start of WorkersFactory and Workers if you want to make any custom changes before the start

Auto-discovery

Allows to skip specifying Workflow classes and Activity beans explicitly in the config by referencing Worker Task Queue names or Worker Names on Workflow and Activity implementations. Auto-discovery is applied after and on top of an explicit configuration.

Add the following to your application.yml to auto-discover workflows and activities from your classpath.

spring.temporal:
  workers-auto-discovery:
    packages:
      - your.package # enumerate all the packages that contain your workflow and activity implementations

What is auto-discovered:

  • Workflows implementation classes annotated with io.temporal.spring.boot.WorkflowImpl
  • Activity beans present Spring context whose implementations are annotated with io.temporal.spring.boot.ActivityImpl
  • Workers if a Task Queue is referenced by the annotations but not explicitly configured. Default configuration will be used.

Auto-discovered workflow implementation classes and activity beans will be registered with the configured workers if not already registered.

Referencing Worker names vs Task Queues

Application that incorporates Task Queue based Versioning strategy may choose to use explicit Worker names to reference because it adds a level of indirection. This way Task Queue name is specified only once in the config and can be easily changed when needed, while all the auto-discovery annotations reference the Worker by its static name.

An application whose lifecycle doesn't involve changing task queue names may prefer to reference Task Queue names directly for simplicity.

Note: Worker whose name is not explicitly specified is named after it's Task Queue.

Customization of *Options

To provide freedom in customization of *Options instances that are created by this module, beans that implement io.temporal.spring.boot.TemporalOptionsCustomizer<OptionsBuilderType> interface may be added to the Spring context.

Where OptionsType may be one of:

  • WorkflowServiceStubsOptions.Builder
  • WorkflowClientOption.Builder
  • WorkerFactoryOptions.Builder
  • WorkerOptions.Builder
  • WorkflowImplementationOptions.Builder
  • TestEnvironmentOptions.Builder

io.temporal.spring.boot.WorkerOptionsCustomizer may be used instead of TemporalOptionsCustomizer<WorkerOptions.Builder> if WorkerOptions needs to be modified differently depending on the Task Queue or Worker name.

Integrations

Metrics

You can set up built-in Spring Boot Metrics using Spring Boot Actuator following one of the manuals. This module will pick up the MeterRegistry bean configured this way and use to report Temporal Metrics.

Alternatively, you can define a custom io.micrometer.core.instrument.MeterRegistry bean in the application context.

Tracing

You can set up Spring Cloud Sleuth with OpenTelemetry export following one of the manuals. This module will pick up the OpenTelemetry bean configured by spring-cloud-sleuth-otel-autoconfigure and use it for Temporal Traces.

Alternatively, you can define a custom

  • io.opentelemetry.api.OpenTelemetry for OpenTelemetry or
  • io.opentracing.Tracer for Opentracing bean in the application context.

Testing

Add the following to your application.yml to reconfigure the assembly to work through io.temporal.testing.TestWorkflowEnvironment that uses in-memory Java Test Server:

spring.temporal:
  test-server:
    enabled: true

When spring.temporal.test-server.enabled:true is added, spring.temporal.connection section is ignored. This allows to wire TestWorkflowEnvironment bean in your unit tests:

@SpringBootTest(classes = Test.Configuration.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class Test {
  @Autowired ConfigurableApplicationContext applicationContext;
  @Autowired TestWorkflowEnvironment testWorkflowEnvironment;
  @Autowired WorkflowClient workflowClient;

  @BeforeEach
  void setUp() {
    applicationContext.start();
  }

  @Test
  @Timeout(value = 10)
  public void test() {
    # ...
  }

  @ComponentScan # to discover activity beans annotated with @Component
  # @EnableAutoConfiguration # can be used to load only AutoConfigurations if usage of @ComponentScan is not desired 
  public static class Configuration {}
}