构建简单 Amazon SWF 应用程序 - Amazon SDK for Java 1.x
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

我们宣布了即将推出 end-of-support 的 Amazon SDK for Java (v1)。建议您迁移到 Amazon SDK for Java v2。有关日期、其他详细信息以及如何迁移的信息,请参阅链接的公告。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

构建简单 Amazon SWF 应用程序

此主题探讨如何使用Amazon SDK for Java 编写 Amazon SWF 应用程序,并在此过程中介绍了一些重要概念。

关于示例

示例项目将创建带有一个活动的工作流,接受通过 Amazon Cloud 传递的工作流数据(在 HelloWorld 的传统中,这应该是要问候的某个人的名字)并在响应中打印问候语。

虽然表面上看起来这非常简单,不过 Amazon SWF 应用程序由多个协同工作的部件组成:

  • 一个,用作工作流执行数据的逻辑容器。

  • 一个或多个工作流程,它们表示代码组件,这些组件定义工作流程的活动和子工作流程执行的逻辑顺序。

  • 一个工作流工作线程,也称为决策程序,轮询决策任务并在响应中计划活动或子工作流。

  • 一个或多个活动,每个活动表示工作流中的一个工作单元。

  • 一个活动工作线程,轮询活动任务并在响应中运行活动方法。

  • 一个或多个任务列表,这是由 Amazon SWF 维护的队列,用于发布请求到工作流和活动工作线程。任务列表上用于工作流工作线程的任务称为决策任务。用于活动工作线程的任务称为活动任务

  • 一个工作流启动程序,用于开始工作流的执行。

在后台,Amazon SWF 协调这些组件的操作,协调从 Amazon Cloud 的传输,在它们之间传递数据,处理超时和检测信号通知,以及记录工作流执行历史记录。

先决条件

开发环境

此教程中使用的开发环境包括:

  • Amazon SDK for Java

  • Apache Maven (3.3.1)。

  • JDK 1.7 或更高版本。本教程使用 JDK 1.8.0 开发和测试。

  • 一个适用的 Java 文本编辑器 (由您选择)。

注意

如果您使用的构建系统不是 Maven,则仍可以使用适用于您环境的相应步骤创建项目,并在这个过程中使用此处提供的概念。Amazon SDK for Java入门中提供了在不同编译系统中配置和使用 的更多信息。

与此类似,但需要更多工作,此处列出的步骤也可以使用支持 Amazon SWF 的任意 Amazon SDK 实施。

所有必需的外部依赖项包括在 Amazon SDK for Java 中,因此无需下载其他内容。

Amazon 访问

要成功完成本教程,您必须有权访问 Amazon 访问门户,如本指南的基本设置部分所述

这些说明描述了如何访问您复制并粘贴到本地共享 credentials 文件中的临时凭证。您粘贴的临时凭证必须与 Amazon IAM Identity Center 中有权访问 Amazon SWF 的 IAM 角色关联。粘贴临时凭证后,您的 credentials 文件将类似于以下内容。

[default] aws_access_key_id=AKIAIOSFODNN7EXAMPLE aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY aws_session_token=IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

这些临时凭证与 default 配置文件相关联。

创建 SWF 项目

  1. 使用 Maven 启动新项目:

    mvn archetype:generate -DartifactId=helloswf \ -DgroupId=aws.example.helloswf -DinteractiveMode=false

    这将创建具有标准 maven 项目结构的新项目:

    helloswf ├── pom.xml └── src ├── main │   └── java │   └── aws │   └── example │   └── helloswf │   └── App.java └── test └── ...

    您可以忽略或删除 test 目录及其中包含的所有内容,我们不会将其用于此教程。您还可以删除 App.java,因为我们将使用新类来替换它。

  2. 编辑项目的 pom.xml 文件,通过将 aws-java-sdk-simpleworkflow 模块的依赖项添加到 <dependencies> 块中来添加该模块。

    <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-simpleworkflow</artifactId> <version>1.11.1000</version> </dependency> </dependencies>
  3. 确保 Maven 使用 JDK 1.7+ 支持构建您的项目。将以下内容添加到您项目 (在 <dependencies> 块之前或之后) 的 pom.xml 中:

    <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>

编码项目

示例项目包括四个独立的应用程序,我们将逐个查看:

  • HelloTypes.java -- 包含项目的域、活动和工作流类型数据,与其他组件共享。它还处理这些类型在 SWF 中的注册。

  • ActivityWorker.java -- 包含活动工作线程,将轮询活动任务并在响应中运行活动。

  • WorkflowWorker.java -- 包含工作流工作线程(决策程序),将轮询决策任务并计划新活动。

  • WorkflowStarter.java -- 包含工作流启动程序,将启动新的工作流执行,这将导致 SWF 开始生成决策和工作流任务供工作线程使用。

所有源文件的常见步骤

您创建的用于托管 Java 类的所有文件都有几个共同点。出于时间考虑,这些步骤在每次添加新文件到项目时是隐含的

  1. 在项目的 src/main/java/aws/example/helloswf/ 目录中创建文件。

  2. 添加 package 声明到每个文件的开头用于声明其命名空间。示例项目使用:

    package aws.example.helloswf;
  3. AmazonSimpleWorkflowClient 类和 com.amazonaws.services.simpleworkflow.model 命名空间中的多个类添加 import 声明。为了简化操作,我们使用:

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*;

注册域、工作流程和活动类型

我们将从创建新的可执行类 HelloTypes.java 开始。此文件将包含共享数据,您的工作流中的不同部分需要这些数据,例如活动的名称和版本以及工作流类型,域名和任务列表名称。

  1. 打开文本编辑器并创建文件 HelloTypes.java,添加程序包声明并根据通用步骤导入。

  2. 声明 HelloTypes 类并向其提供值,以供注册的活动和工作流类型使用:

    public static final String DOMAIN = "HelloDomain"; public static final String TASKLIST = "HelloTasklist"; public static final String WORKFLOW = "HelloWorkflow"; public static final String WORKFLOW_VERSION = "1.0"; public static final String ACTIVITY = "HelloActivity"; public static final String ACTIVITY_VERSION = "1.0";

    这些值将在代码中使用。

  3. 在字符串声明之后,创建 AmazonSimpleWorkflowClient 类的实例。这是由Amazon SDK for Java向 Amazon SWF 方法提供的基本接口。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();

    前面的代码片段假设临时凭证与 default 配置文件相关联。如果您使用其他配置文件,请按如下方式修改上面的代码,然后将 profile_name 替换为实际配置文件的名称。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder .standard() .withCredentials(new ProfileCredentialsProvider("profile_name")) .withRegion(Regions.DEFAULT_REGION) .build();
  4. 添加新函数以注册到 SWF 域。 是多种相关 SWF 活动和工作流类型的逻辑容器。SWF 组件只有在位于同一个域中时才能彼此通信。

    try { System.out.println("** Registering the domain '" + DOMAIN + "'."); swf.registerDomain(new RegisterDomainRequest() .withName(DOMAIN) .withWorkflowExecutionRetentionPeriodInDays("1")); } catch (DomainAlreadyExistsException e) { System.out.println("** Domain already exists!"); }

    在注册域时,您需要提供名称(不含 :/|、控制字符或文本字符串“arn”的 1 至 256 个字符组合)以及保留期,这是在工作流执行完成后,Amazon SWF 保留工作流执行历史记录数据的天数。最长的工作流执行保留期为 90 天。有关更多信息,请参阅 RegisterDomainRequest

    如果具有该名称的域已存在,则将引发 DomainAlreadyExistsException。因为我们并不关注是否已经创建了域,因此可以忽略此异常。

    注意

    此代码演示了使用Amazon SDK for Java方法时的一个通用模式,方法的数据由 simpleworkflow.model 命名空间中的类提供,该命名空间使用可链接的 –0—with* 方法实例化和填充。

  5. 添加函数以注册新活动类型。活动 表示工作流中的一个工作单元。

    try { System.out.println("** Registering the activity type '" + ACTIVITY + "-" + ACTIVITY_VERSION + "'."); swf.registerActivityType(new RegisterActivityTypeRequest() .withDomain(DOMAIN) .withName(ACTIVITY) .withVersion(ACTIVITY_VERSION) .withDefaultTaskList(new TaskList().withName(TASKLIST)) .withDefaultTaskScheduleToStartTimeout("30") .withDefaultTaskStartToCloseTimeout("600") .withDefaultTaskScheduleToCloseTimeout("630") .withDefaultTaskHeartbeatTimeout("10")); } catch (TypeAlreadyExistsException e) { System.out.println("** Activity type already exists!"); }

    活动类型由名称版本标识,它们在所注册到的域中用于将活动与任何其他活动区分开。活动还包含多种可选参数,例如用于从 SWF 接收任务和数据的默认任务列表,以及您可用来对活动各个部分执行所用时长施加限制的不同超时。有关更多信息,请参阅 RegisterActivityTypeRequest

    注意

    所有超时值以 为单位指定。有关超时如何影响工作流执行的完整说明,请参阅 Amazon SWF Timeout Types

如果您尝试注册的活动类型已存在,则将引发 TypeAlreadyExistsException。添加函数以注册新工作流类型。工作流程 也称为决策程序,表示工作流程执行的逻辑。

+

try { System.out.println("** Registering the workflow type '" + WORKFLOW + "-" + WORKFLOW_VERSION + "'."); swf.registerWorkflowType(new RegisterWorkflowTypeRequest() .withDomain(DOMAIN) .withName(WORKFLOW) .withVersion(WORKFLOW_VERSION) .withDefaultChildPolicy(ChildPolicy.TERMINATE) .withDefaultTaskList(new TaskList().withName(TASKLIST)) .withDefaultTaskStartToCloseTimeout("30")); } catch (TypeAlreadyExistsException e) { System.out.println("** Workflow type already exists!"); }

+

与活动类型类似,工作流类型由名称版本 标识,也具有可配置的超时。有关更多信息,请参阅 RegisterWorkflowTypeRequest

+

如果您尝试注册的工作流类型已存在,则将引发 TypeAlreadyExistsException。最后,请通过向类提供 main 方法确保其可执行,这反过来会注册域、活动类型和工作流类型:

+

registerDomain(); registerWorkflowType(); registerActivityType();

现在,您可以编译运行应用程序来运行注册脚本,或者继续对活动和工作流工作线程编写代码。注册了域、工作流和活动之后,您无需重新运行此步骤,这些内容将保留,直至您自行弃用它们。

实施活动工作线程

活动 是工作流中的基本工作单元。工作流提供逻辑、要运行的计划活动 (或要采取的其他操作) 来响应决策任务。典型的工作流通常包含多种活动,可以同步、异步或者以两种方式结合运行。

活动工作线程 是一段代码,轮询由 Amazon SWF 生成的活动任务来响应工作流决策。在收到活动任务时,它将运行对应的活动并将成功/失败响应返回到工作流。

我们将实施驱动单个活动的简单活动工作线程。

  1. 打开文本编辑器并创建文件 ActivityWorker.java,添加程序包声明并根据通用步骤导入。

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*;
  2. 向文件中添加 ActivityWorker 类,并向其提供数据成员以保存用来与 Amazon SWF 交互的 SWF 客户端:

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
  3. 添加将用作活动的方法:

    private static String sayHello(String input) throws Throwable { return "Hello, " + input + "!"; }

    该活动就是获取字符串,将其组合到问候语中,然后返回结果。虽然此活动有很小的可能性会引发异常,但最好的做法是将活动设计为在出现问题时会引发错误。

  4. 添加我们将用作活动任务轮询方法的 main 方法。我们首先添加一些代码来轮询任务列表中的活动任务:

    System.out.println("Polling for an activity task from the tasklist '" + HelloTypes.TASKLIST + "' in the domain '" + HelloTypes.DOMAIN + "'."); ActivityTask task = swf.pollForActivityTask( new PollForActivityTaskRequest() .withDomain(HelloTypes.DOMAIN) .withTaskList( new TaskList().withName(HelloTypes.TASKLIST))); String task_token = task.getTaskToken();

    活动通过调用 Amazon SWF 客户端的 pollForActivityTask 方法从 SWF 接收任务,指定在传入的 PollForActivityTaskRequest 中使用的域和任务列表。

    一旦收到任务,我们将通过调用任务的 getTaskToken 方法来检索它的唯一标识符。

  5. 接下来,写入一些代码来处理传入的任务。将以下内容添加到您的 main 方法,就在轮询任务和检索其任务令牌代码的后方。

    if (task_token != null) { String result = null; Throwable error = null; try { System.out.println("Executing the activity task with input '" + task.getInput() + "'."); result = sayHello(task.getInput()); } catch (Throwable th) { error = th; } if (error == null) { System.out.println("The activity task succeeded with result '" + result + "'."); swf.respondActivityTaskCompleted( new RespondActivityTaskCompletedRequest() .withTaskToken(task_token) .withResult(result)); } else { System.out.println("The activity task failed with the error '" + error.getClass().getSimpleName() + "'."); swf.respondActivityTaskFailed( new RespondActivityTaskFailedRequest() .withTaskToken(task_token) .withReason(error.getClass().getSimpleName()) .withDetails(error.getMessage())); } }

    如果任务令牌不是 null,则我们可以开始运行活动方法 (sayHello),只要它具有随任务发送的输入数据。

    如果任务成功(未生成任何错误),则 worker 通过调用 SWF 客户端的 respondActivityTaskCompleted 方法来响应 SWF,该方法使用包含任务令牌和活动结果数据的 RespondActivityTaskCompletedRequest 对象。

    另一方面,如果任务失败,则我们通过调用带有 RespondActivityTaskFailedRequest 对象的 respondActivityTaskFailed 方法进行响应,向其传递任务令牌和有关错误的信息。

注意

如果终止,此活动不会正常关闭。虽然这超出了本教程的范围,不过在相关主题适当地关闭活动和工作流工作线程中提供了此活动工作线程的替代实施方法。

实施工作流工作线程

您的工作流逻辑位于称为工作流工作线程的代码块中。工作流工作线程在工作流类型注册到的默认任务列表上,轮询域中 Amazon SWF 发送的决策任务。

工作流工作线程接收任务时,它会做出某种类型的决策 (通常为是否计划新活动) 并采取相应操作 (例如计划活动)。

  1. 打开文本编辑器并创建文件 WorkflowWorker.java,添加程序包声明并根据通用步骤导入。

  2. 将一些额外的导入添加到文件中:

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*; import java.util.ArrayList; import java.util.List; import java.util.UUID;
  3. 声明 WorkflowWorker 类,创建用于访问 SWF 方法的 AmazonSimpleWorkflowClient 类的实例。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
  4. 添加 main 方法。该方法持续循环,使用 SWF 客户端的 pollForDecisionTask 方法轮询决策任务。PollForDecisionTaskRequest 提供详细信息。

    PollForDecisionTaskRequest task_request = new PollForDecisionTaskRequest() .withDomain(HelloTypes.DOMAIN) .withTaskList(new TaskList().withName(HelloTypes.TASKLIST)); while (true) { System.out.println( "Polling for a decision task from the tasklist '" + HelloTypes.TASKLIST + "' in the domain '" + HelloTypes.DOMAIN + "'."); DecisionTask task = swf.pollForDecisionTask(task_request); String taskToken = task.getTaskToken(); if (taskToken != null) { try { executeDecisionTask(taskToken, task.getEvents()); } catch (Throwable th) { th.printStackTrace(); } } }

    在收到任务之后,我们调用其 getTaskToken 方法,这会返回可用于标识任务的字符串。如果返回的令牌不是 null,则我们在 executeDecisionTask 方法中进一步处理它,向它传递随任务发送的任务令牌以及 HistoryEvent 对象的列表。

  5. 添加 executeDecisionTask 方法,获取任务令牌 (String) 和 HistoryEvent 列表。

    List<Decision> decisions = new ArrayList<Decision>(); String workflow_input = null; int scheduled_activities = 0; int open_activities = 0; boolean activity_completed = false; String result = null;

    我们还可以设置一些数据成员来跟踪内容,例如:

    • 用于报告任务处理结果的决策对象列表。

    • 用于保存由“WorkflowExecutionStarted”事件提供的工作流输入的字符串

    • 已计划和打开 (正在运行) 活动的计数,用于避免再次计划已经计划或者当前正在运行的相同活动。

    • 用于指示活动已完成的布尔值。

    • 用于保存活动结果的字符串,以将其作为我们的工作流结果返回。

  6. 接下来,添加一些代码到 executeDecisionTask,基于 HistoryEvent 方法报告的事件类型处理随任务发送的 getEventType 对象。

    System.out.println("Executing the decision task for the history events: ["); for (HistoryEvent event : events) { System.out.println(" " + event); switch(event.getEventType()) { case "WorkflowExecutionStarted": workflow_input = event.getWorkflowExecutionStartedEventAttributes() .getInput(); break; case "ActivityTaskScheduled": scheduled_activities++; break; case "ScheduleActivityTaskFailed": scheduled_activities--; break; case "ActivityTaskStarted": scheduled_activities--; open_activities++; break; case "ActivityTaskCompleted": open_activities--; activity_completed = true; result = event.getActivityTaskCompletedEventAttributes() .getResult(); break; case "ActivityTaskFailed": open_activities--; break; case "ActivityTaskTimedOut": open_activities--; break; } } System.out.println("]");

    对于我们的工作流,我们最感兴趣的是:

    • “WorkflowExecutionStarted”事件,这指示工作流执行已启动 (通常意味着您应该运行工作流中的第一个活动),并且这提供了初始输入 (提供到工作流中)。在这种情况下,这是我们问候语的名称部分,因此将其保存在字符串中以在计划活动运行时使用。

    • “ActivityTaskCompleted”事件在计划的活动完成后立即发送。事件数据还包括已完成活动的返回值。因为我们仅有一个活动,我们将使用该值作为整个工作流程的结果。

    其他事件类型在工作流需要时可以使用。有关各个事件类型的信息,请参阅 HistoryEvent 类说明。

    + 注意:switch 语句中的字符串在 Java 7 中引入。如果您使用的是 Java 的较早版本,则可以使用 EventType 类将 history_event.getType() 返回的 String 转换为枚举值,然后可在需要时将其转换回 String

EventType et = EventType.fromValue(event.getEventType());
  1. switch 语句之后,添加更多代码,根据所收到的任务采用合适的决策 进行响应。

    if (activity_completed) { decisions.add( new Decision() .withDecisionType(DecisionType.CompleteWorkflowExecution) .withCompleteWorkflowExecutionDecisionAttributes( new CompleteWorkflowExecutionDecisionAttributes() .withResult(result))); } else { if (open_activities == 0 && scheduled_activities == 0) { ScheduleActivityTaskDecisionAttributes attrs = new ScheduleActivityTaskDecisionAttributes() .withActivityType(new ActivityType() .withName(HelloTypes.ACTIVITY) .withVersion(HelloTypes.ACTIVITY_VERSION)) .withActivityId(UUID.randomUUID().toString()) .withInput(workflow_input); decisions.add( new Decision() .withDecisionType(DecisionType.ScheduleActivityTask) .withScheduleActivityTaskDecisionAttributes(attrs)); } else { // an instance of HelloActivity is already scheduled or running. Do nothing, another // task will be scheduled once the activity completes, fails or times out } } System.out.println("Exiting the decision task with the decisions " + decisions);
    • 如果尚未计划活动,我们使用 ScheduleActivityTask 决策进行响应,这在 ScheduleActivityTaskDecisionAttributes 结构中提供关于 Amazon SWF 接下来应计划的活动的信息,也包括 Amazon SWF 应发送到活动的任何数据。

    • 如果活动已完成,则我们将考虑完成的整个工作流,并使用 CompletedWorkflowExecution 决策进行响应,填入 CompleteWorkflowExecutionDecisionAttributes 结构以提供有关已完成工作流的详细信息。在这种情况下,我们将返回活动的结果。

    在任何一种情况下,决策信息将添加到在方法顶部声明的 Decision 列表。

  2. 返回在处理任务时收集的 Decision 对象列表来完成决策任务。在我们所编写的 executeDecisionTask 方法尾部添加此代码:

    swf.respondDecisionTaskCompleted( new RespondDecisionTaskCompletedRequest() .withTaskToken(taskToken) .withDecisions(decisions));

    SWF 客户端的 respondDecisionTaskCompleted 方法获取标识任务的任务令牌以及 Decision 对象列表。

实施工作流启动程序

最后,我们将编写一些代码用于启动工作流程执行。

  1. 打开文本编辑器并创建文件 WorkflowStarter.java,添加程序包声明并根据通用步骤导入。

  2. 添加 WorkflowStarter 类:

    package aws.example.helloswf; import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*; public class WorkflowStarter { private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build(); public static final String WORKFLOW_EXECUTION = "HelloWorldWorkflowExecution"; public static void main(String[] args) { String workflow_input = "{SWF}"; if (args.length > 0) { workflow_input = args[0]; } System.out.println("Starting the workflow execution '" + WORKFLOW_EXECUTION + "' with input '" + workflow_input + "'."); WorkflowType wf_type = new WorkflowType() .withName(HelloTypes.WORKFLOW) .withVersion(HelloTypes.WORKFLOW_VERSION); Run run = swf.startWorkflowExecution(new StartWorkflowExecutionRequest() .withDomain(HelloTypes.DOMAIN) .withWorkflowType(wf_type) .withWorkflowId(WORKFLOW_EXECUTION) .withInput(workflow_input) .withExecutionStartToCloseTimeout("90")); System.out.println("Workflow execution started with the run id '" + run.getRunId() + "'."); } }

    WorkflowStarter 类包含一个方法 main,它获取命令行上传递的可选参数作为工作流的输入数据。

    SWF 客户端方法 startWorkflowExecution,获取 StartWorkflowExecutionRequest 对象作为输入。此处,除了指定要运行的域和工作流类型之外,我们提供了:

    • 便于阅读的工作流执行名称

    • 工作流输入数据 (我们的示例中在命令行上提供)

    • 超时值,以秒为单位,表示整个工作流运行所应使用的时长。

    返回的运行startWorkflowExecution对象提供了运行 ID,这是用于在 Amazon SWF 的工作流执行历史记录中标识此特定工作流执行的值。

    + 注意:运行 ID 由 Amazon SWF 生成,不同于 您在启动工作流执行时传入的工作流执行名称。

编译示例

要使用 Maven 编译示例项目,请转到 helloswf 目录并键入:

mvn package

生成的 helloswf-1.0.jar 将在 target 目录中生成。

运行示例

示例包括四个独立的可执行类,彼此独立运行。

注意

如果您使用的是 Linux、macOS 或 Unix 系统,您可以在单个终端窗口中将它们全部逐个运行。如果您运行的是 Windows,则应该打开两个额外的命令行实例并分别导航到 helloswf 目录。

设置 Java 类路径

虽然 Maven 已经为您处理了依赖项来运行示例,您仍需要在 Java 类路径上提供 Amazon SDK 库及其依赖项。您可以将 CLASSPATH 环境变量设置为 Amazon SDK 库的位置,以及 SDK 中包括必要依赖项的 third-party/lib 目录:

export CLASSPATH='target/helloswf-1.0.jar:/path/to/sdk/lib/*:/path/to/sdk/third-party/lib/*' java example.swf.hello.HelloTypes

或者使用 java 命令的 -cp 选项在运行各个应用程序时设置类路径。

java -cp target/helloswf-1.0.jar:/path/to/sdk/lib/*:/path/to/sdk/third-party/lib/* \ example.swf.hello.HelloTypes

您使用的样式由您决定。如果您在编译代码时没有问题,但在尝试运行示例时遇到一系列“NoClassDefFound”错误,则可能是因为类路径设置不正确。

注册域、工作流程和活动类型

在运行工作线程和工作流程启动程序之前,您需要注册域以及工作流程和活动类型。执行此操作的代码在注册域、工作流和活动类型中实施。

在编译之后,如果您已设置 CLASSPATH,则可以通过执行以下命令运行注册代码:

echo 'Supply the name of one of the example classes as an argument.'

启动活动和工作流工作线程

现在类型已注册,您可以启动活动和工作流工作线程。它们将持续运行并轮询任务,直至终止,因此您应该在单独终端窗口中运行它们,或者,如果您在 Linux、macOS 或 Unix 上运行它们,则可以使用 & 运算符来使得它们中的每一个在运行时生成单独进程。

echo 'If there are arguments to the class, put them in quotes after the class name.' exit 1

如果您在单独窗口中运行这些命令,则忽略每一行最后的 & 运算符。

启动工作流执行

现在正在轮询您的活动和工作流工作线程,您可以启动工作流执行。此进程将运行直至工作流返回已完成状态。您应在新终端窗口中运行它 (除非您使用 & 运算符将工作线程作为新生成的进程运行)。

fi
注意

如果您要提供自己的输入数据 (这将首先传递到工作流,然后传递到活动),则将其添加到命令行中。例如:

echo "## Running $className..."

一旦开始工作流执行,您应该开始查看这两种工作线程以及工作流执行本身提供的输出。工作流最终完成之后,其输出将显示在屏幕上。

此示例的完整源代码

您可以在 Github 的 aws-java-developer-guide 存储库中浏览此示例的完整源代码

有关更多信息