간단한 Amazon SWF 애플리케이션 구축 - AWS SDK for Java 1.x

곧 출시될 end-of-support AWS SDK for Java (v1) 버전을 발표했습니다. AWS SDK for Java V2로 마이그레이션하실 것을 권장합니다. 마이그레이션 날짜, 추가 세부 정보 및 방법에 대한 자세한 내용은 링크된 공지 사항을 참조하세요.

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

간단한 Amazon SWF 애플리케이션 구축

이 항목에서는 AWS SDK for Java를 사용하여 Amazon SWF 애플리케이션을 프로그래밍하는 방법을 소개하고 그 과정에서 몇 가지 중요한 개념을 설명합니다.

예제 소개

예제 프로젝트에서는 AWS 클라우드를 통해 전달된 워크플로 데이터(HelloWorld 식으로는 인사할 사람의 이름임)를 수락한 다음 응답으로 인사말을 출력하는 단일 활동으로 워크플로를 생성합니다.

이 동작을 수행하는 Amazon SWF 애플리케이션은 표면적으로는 매우 간단해 보이지만, 함께 작동하는 여러 부분으로 이루어집니다.

  • 도메인 - 워크플로 실행 데이터의 논리적 컨테이너로 사용됩니다.

  • 하나 이상의 워크플로 - 워크플로의 활동 및 하위 워크플로의 논리적 실행 순서를 정의하는 코드 구성 요소를 나타냅니다.

  • 워크플로 작업자 - 결정자라고도 하며, 결정 작업에 대해 폴링을 수행하거나 응답으로 수행되는 활동이나 하위 워크플로를 예약합니다.

  • 하나 이상의 활동 - 각 활동은 워크플로 내 작업 단위를 나타냅니다.

  • 활동 작업자 - 활동 작업을 폴링하고 응답으로 활동 메서드를 실행합니다.

  • 하나 이상의 작업 목록 - Amazon SWF에서 유지 관리되며 워크플로 및 활동 작업자에 대한 요청을 발행하는 데 사용되는 대기열입니다. 워크플로 작업자에 대한 작업 목록의 작업을 결정 작업이라고 합니다. 활동 작업자에 대한 작업 목록의 작업을 활동 작업이라고 합니다.

  • 워크플로 시작자 - 워크플로 실행을 시작합니다.

보이지는 않지만 Amazon SWF는 뒤에서 이러한 구성 요소의 작동을 조정하고, AWS 클라우드로부터의 흐름을 조정하고, 구성 요소 간에 데이터를 전달하고, 시간 초과 및 하트비트 알림을 처리하고, 워크플로 실행 기록을 기록합니다.

필수 조건

개발 환경

이 자습서에 사용되는 개발 환경은 다음으로 구성됩니다.

  • AWS SDK for Java.

  • Apache Maven(3.3.1)

  • JDK 1.7 이상. 이 자습서는 JDK 1.8.0을 사용해 개발 및 테스트하였습니다.

  • 적합한 Java 텍스트 편집기(개발자 선택)

참고

Maven과 다른 빌드 시스템을 사용하는 경우에도 환경에 적합한 단계를 사용하여 프로젝트를 생성하고 여기에 제공된 개념을 사용하여 따라갈 수 있습니다. 다양한 빌드 시스템에서 AWS SDK for Java 사용 및 구성에 대한 자세한 내용은 시작하기에 나와 있습니다.

마찬가지로, Amazon SWF를 지원하는 AWS SDK를 사용하여 여기에 표시된 단계를 구현할 수도 있습니다. 단, 이 경우에는 좀 더 많은 노력이 요구됩니다.

필요한 외부 종속성이 모두 AWS SDK for Java와 함께 포함되어 있으므로 추가로 다운로드할 필요가 없습니다.

AWS 액세스

이 자습서를 성공적으로 마치려면 이 가이드의 기본 설정 단원에 설명된 대로 AWS 액세스 포털에 액세스할 수 있어야 합니다.

지침에서는 로컬 공유 credentials 파일에 복사하여 붙여넣는 임시 자격 증명에 액세스하는 방법을 설명합니다. 붙여넣는 임시 자격 증명은 Amazon SWF에 액세스할 권한이 있는 AWS IAM Identity Center의 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 파일을 편집하고 <dependencies> 블록 내에 해당 모듈에 대한 종속성을 추가하여 aws-java-sdk-simpleworkflow 모듈을 추가합니다.

    <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-simpleworkflow</artifactId> <version>1.11.1000</version> </dependency> </dependencies>
  3. Maven에서 JDK 1.7+가 지원되는 프로젝트가 빌드되는지 확인합니다. pom.xml에서 프로젝트(<dependencies> 블록 앞 또는 뒤)에 다음을 추가합니다.

    <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. String 선언 뒤에 AmazonSimpleWorkflowClient 클래스의 인스턴스를 생성합니다. 이 인스턴스는 AWS 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이 발생합니다. 도메인이 생성된 경우에는 관련이 없으므로 이 예외를 무시해도 됩니다.

    참고

    이 코드는 AWS 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제한 시간 유형을 참조하세요.

등록하려고 하는 활동 유형이 이미 있는 경우 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();

    활동은 SWF 클라이언트의 pollForActivityTask 메서드를 호출하고 전달된 PollForActivityTaskRequest에서 사용할 도메인과 작업 목록을 지정하여 Amazon SWF에서 작업을 받습니다.

    작업이 수신되고 나면 작업의 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)의 실행을 시작할 수 있습니다.

    작업이 성공하면(오류가 생성되지 않은 경우) 작업자는 작업 토큰과 활동의 결과 데이터가 포함된 RespondActivityTaskCompletedRequest 객체를 사용하여 SWF 클라이언트의 respondActivityTaskCompleted 메서드를 호출하여 SWF에 응답합니다.

    반면, 작업이 실패하면 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. 작업 토큰(String)과 HistoryEvent 목록을 사용하는 executeDecisionTask 메서드를 추가합니다.

    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;

    또한 다음과 같은 항목을 추적하기 위해 데이터 멤버를 설정할 수도 있습니다.

    • 작업 처리 결과를 보고하는 데 사용되는 Decision 객체 목록

    • "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 결정을 내려 응답합니다. 이 결정은 Amazon SWF에서 다음 일정을 잡아야 하는 활동에 대한 ScheduleActivityTaskDecisionAttributes 구조로 된 정보와 Amazon SWF가 활동으로 전송해야 하는 모든 데이터를 포함합니다.

    • 활동이 완료된 경우 전체 워크플로가 완료된 것으로 간주하고 CompleteWorkExecutionDecisionAttributes 구조를 작성하여 완료된 워크플로에 대한 세부 정보를 제공하여 CompletedWorkflowExecution 의사 결정에 응답합니다. 이 경우 활동의 결과를 반환합니다.

    어느 경우든, 결정 정보는 메서드 맨 위에 선언된 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 클라이언트 메서드인 startWorkflowExecutionStartWorkflowExecutionRequest 객체를 입력으로 사용합니다. 여기서는 실행할 워크플로 유형과 도메인을 지정하는 것 외에, 다음을 제공합니다.

    • 사람이 읽을 수 있는 워크플로 실행 이름

    • 워크플로 입력 데이터(여기 예제에서는 명령줄을 통해 제공됨)

    • 전체 워크플로를 실행하는 데 걸릴 시간(초)을 나타내는 제한 시간 값

    startWorkflowExecution가 반환하는 Run 객체는 워크플로 실행에 대한 Amazon SWF의 기록에서 해당 특정 워크플로 실행을 식별하는 데 사용할 수 있는 값인 실행 ID를 제공합니다.

    + 참조: 실행 ID는 Amazon SWF에서 생성하며 워크플로 실행 시작 시 전달하는 워크플로 실행 이름과 동일하지 않습니다.

예제 빌드

Maven을 사용하여 예제 프로젝트를 빌드하려면 helloswf 디렉터리 및 유형으로 이동합니다.

mvn package

결과적으로 helloswf-1.0.jartarget 디렉터리에 생성됩니다.

예제 실행

이 예제는 서로 독립적으로 실행되는 네 가지 개별 실행 가능 클래스로 구성되어 있습니다.

참고

Linux, macOS 또는 Unix 시스템을 사용 중인 경우 단일 터미널 창에서 이들 클래스 모드를 차례로 하나씩 실행할 수 있습니다. Windows를 실행 중이면 추가 명령줄 인스턴스 두 개를 열어서 각각 helloswf 디렉터리로 이동해야 합니다.

Java classpath 설정

Maven에서 개발자를 대신하여 종속성을 처리했더라도 이 예제를 실행하려면 AWS SDK 라이브러리와 Java 클래스 경로에 대한 관련 종속성을 제공해야 합니다. CLASSPATH 환경 변수를 AWS 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 옵션을 사용하여 각 애플리케이션을 실행하는 동안 classpath를 설정할 수 있습니다.

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

사용할 스타일은 개발자 재량에 따라 선택할 수 있습니다. 코드 빌드 시에는 문제가 발생하지 않았지만 예제를 실행할 때 일련의 "NoClassDefFound" 오류가 발생하는 경우 이는 classpath가 올바르게 설정되지 않았기 때문일 가능성이 높습니다.

도메인, 워크플로 및 활동 유형 등록

작업자 및 워크플로 시작자를 실행하기 전에 도메인 및 워크플로와 활동 유형을 등록해야 합니다. 이 작업을 수행하는 코드가 도메인, 워크플로 및 활동 유형 등록에 구현되었습니다.

빌드 후 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 리포지토리에서 이 예제의 전체 소스를 찾아볼 수 있습니다.

자세한 정보