com.amazonaws.services.simpleworkflow.flow.worker.SynchronousActivityTaskPoller.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.services.simpleworkflow.flow.worker.SynchronousActivityTaskPoller.java

Source

/*
 * Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.amazonaws.services.simpleworkflow.flow.worker;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.flow.ActivityExecutionContext;
import com.amazonaws.services.simpleworkflow.flow.ActivityFailureException;
import com.amazonaws.services.simpleworkflow.flow.common.WorkflowExecutionUtils;
import com.amazonaws.services.simpleworkflow.flow.generic.ActivityImplementation;
import com.amazonaws.services.simpleworkflow.flow.generic.ActivityImplementationFactory;
import com.amazonaws.services.simpleworkflow.model.ActivityTask;
import com.amazonaws.services.simpleworkflow.model.ActivityType;
import com.amazonaws.services.simpleworkflow.model.PollForActivityTaskRequest;
import com.amazonaws.services.simpleworkflow.model.RespondActivityTaskCanceledRequest;
import com.amazonaws.services.simpleworkflow.model.RespondActivityTaskCompletedRequest;
import com.amazonaws.services.simpleworkflow.model.RespondActivityTaskFailedRequest;
import com.amazonaws.services.simpleworkflow.model.TaskList;
import com.amazonaws.services.simpleworkflow.model.UnknownResourceException;

public class SynchronousActivityTaskPoller implements TaskPoller {

    private static final Log log = LogFactory.getLog(SynchronousActivityTaskPoller.class);

    private AmazonSimpleWorkflow service;

    private String domain;

    private String taskListToPoll;

    private ActivityImplementationFactory activityImplementationFactory;

    private String identity;

    private SynchronousRetrier reportCompletionRetrier;

    private SynchronousRetrier reportFailureRetrier;

    private boolean initialized;

    public SynchronousActivityTaskPoller(AmazonSimpleWorkflow service, String domain, String taskListToPoll,
            ActivityImplementationFactory activityImplementationFactory) {
        this();
        this.service = service;
        this.domain = domain;
        this.taskListToPoll = taskListToPoll;
        this.activityImplementationFactory = activityImplementationFactory;
        setReportCompletionRetryParameters(new ExponentialRetryParameters());
        setReportFailureRetryParameters(new ExponentialRetryParameters());
    }

    public SynchronousActivityTaskPoller() {
        identity = ManagementFactory.getRuntimeMXBean().getName();
        int length = Math.min(identity.length(), GenericWorker.MAX_IDENTITY_LENGTH);
        identity = identity.substring(0, length);
    }

    public AmazonSimpleWorkflow getService() {
        return service;
    }

    public void setService(AmazonSimpleWorkflow service) {
        this.service = service;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    public String getPollTaskList() {
        return taskListToPoll;
    }

    public void setTaskListToPoll(String taskList) {
        this.taskListToPoll = taskList;
    }

    public ActivityImplementationFactory getActivityImplementationFactory() {
        return activityImplementationFactory;
    }

    public void setActivityImplementationFactory(ActivityImplementationFactory activityImplementationFactory) {
        this.activityImplementationFactory = activityImplementationFactory;
    }

    public String getIdentity() {
        return identity;
    }

    public void setIdentity(String identity) {
        this.identity = identity;
    }

    public ExponentialRetryParameters getReportCompletionRetryParameters() {
        return reportCompletionRetrier.getRetryParameters();
    }

    public void setReportCompletionRetryParameters(ExponentialRetryParameters reportCompletionRetryParameters) {
        this.reportCompletionRetrier = new SynchronousRetrier(reportCompletionRetryParameters,
                UnknownResourceException.class);
    }

    public ExponentialRetryParameters getReportFailureRetryParameters() {
        return reportFailureRetrier.getRetryParameters();
    }

    public void setReportFailureRetryParameters(ExponentialRetryParameters reportFailureRetryParameters) {
        this.reportFailureRetrier = new SynchronousRetrier(reportFailureRetryParameters,
                UnknownResourceException.class);
    }

    public String getTaskListToPoll() {
        return taskListToPoll;
    }

    /**
     * Poll for a task using {@link #getPollTimeoutInSeconds()}
     * 
     * @return null if poll timed out
     */
    public ActivityTask poll() {
        if (!initialized) {
            checkRequiredProperty(service, "service");
            checkRequiredProperty(domain, "domain");
            checkRequiredProperty(taskListToPoll, "taskListToPoll");
            initialized = true;
        }

        PollForActivityTaskRequest pollRequest = new PollForActivityTaskRequest();
        pollRequest.setDomain(domain);
        pollRequest.setIdentity(identity);
        pollRequest.setTaskList(new TaskList().withName(taskListToPoll));
        if (log.isDebugEnabled()) {
            log.debug("poll request begin: " + pollRequest);
        }
        ActivityTask result = service.pollForActivityTask(pollRequest);
        if (result == null || result.getTaskToken() == null) {
            if (log.isDebugEnabled()) {
                log.debug("poll request returned no task");
            }
            return null;
        }
        if (log.isTraceEnabled()) {
            log.trace("poll request returned " + result);
        }
        return result;
    }

    /**
     * Poll for a activity task and execute correspondent implementation.
     * 
     * @return true if task was polled and decided upon, false if poll timed out
     * @throws Exception
     */
    @Override
    public boolean pollAndProcessSingleTask() throws Exception {
        ActivityTask task = poll();
        if (task == null) {
            return false;
        }
        execute(task);
        return true;
    }

    protected void execute(final ActivityTask task) throws Exception {
        String output = null;
        ActivityType activityType = task.getActivityType();
        try {
            ActivityExecutionContext context = new ActivityExecutionContextImpl(service, domain, task);
            ActivityImplementation activityImplementation = activityImplementationFactory
                    .getActivityImplementation(activityType);
            if (activityImplementation == null) {
                throw new ActivityFailureException("Unknown activity type: " + activityType);
            }
            output = activityImplementation.execute(context);
            if (!activityImplementation.getExecutionOptions().isManualActivityCompletion()) {
                respondActivityTaskCompletedWithRetry(task.getTaskToken(), output);
            }
        } catch (CancellationException e) {
            respondActivityTaskCanceledWithRetry(task.getTaskToken(), null);
            return;
        } catch (ActivityFailureException e) {
            if (log.isErrorEnabled()) {
                log.error("Failure processing activity task with taskId=" + task.getStartedEventId()
                        + ", workflowGenerationId=" + task.getWorkflowExecution().getWorkflowId() + ", activity="
                        + activityType + ", activityInstanceId=" + task.getActivityId(), e);
            }
            respondActivityTaskFailedWithRetry(task.getTaskToken(), e.getReason(), e.getDetails());
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("Failure processing activity task with taskId=" + task.getStartedEventId()
                        + ", workflowGenerationId=" + task.getWorkflowExecution().getWorkflowId() + ", activity="
                        + activityType + ", activityInstanceId=" + task.getActivityId(), e);
            }
            String reason = e.getMessage();
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String details = sw.toString();
            respondActivityTaskFailedWithRetry(task.getTaskToken(), reason, details);
        }
    }

    protected void respondActivityTaskFailedWithRetry(final String taskToken, final String reason,
            final String details) {
        if (reportFailureRetrier == null) {
            respondActivityTaskFailed(taskToken, reason, details);
        } else {
            reportFailureRetrier.retry(new Runnable() {

                @Override
                public void run() {
                    respondActivityTaskFailed(taskToken, reason, details);
                }
            });
        }
    }

    protected void respondActivityTaskFailed(String taskToken, String reason, String details) {
        RespondActivityTaskFailedRequest failedResponse = new RespondActivityTaskFailedRequest();
        failedResponse.setTaskToken(taskToken);
        failedResponse.setReason(WorkflowExecutionUtils.truncateReason(reason));
        failedResponse.setDetails(details);
        service.respondActivityTaskFailed(failedResponse);
    }

    protected void respondActivityTaskCanceledWithRetry(final String taskToken, final String details) {
        if (reportFailureRetrier == null) {
            respondActivityTaskCanceled(taskToken, details);
        } else {
            reportFailureRetrier.retry(new Runnable() {

                @Override
                public void run() {
                    respondActivityTaskCanceled(taskToken, details);
                }
            });
        }
    }

    protected void respondActivityTaskCanceled(String taskToken, String details) {
        RespondActivityTaskCanceledRequest canceledResponse = new RespondActivityTaskCanceledRequest();
        canceledResponse.setTaskToken(taskToken);
        canceledResponse.setDetails(details);
        service.respondActivityTaskCanceled(canceledResponse);
    }

    protected void respondActivityTaskCompletedWithRetry(final String taskToken, final String output) {
        if (reportCompletionRetrier == null) {
            respondActivityTaskCompleted(taskToken, output);
        } else {
            reportCompletionRetrier.retry(new Runnable() {

                @Override
                public void run() {
                    respondActivityTaskCompleted(taskToken, output);
                }
            });
        }
    }

    protected void respondActivityTaskCompleted(String taskToken, String output) {
        RespondActivityTaskCompletedRequest completedReponse = new RespondActivityTaskCompletedRequest();
        completedReponse.setTaskToken(taskToken);
        completedReponse.setResult(output);
        service.respondActivityTaskCompleted(completedReponse);
    }

    protected void checkRequiredProperty(Object value, String name) {
        if (value == null) {
            throw new IllegalStateException("required property " + name + " is not set");
        }
    }

    @Override
    public void shutdown() {
    }

    @Override
    public void shutdownNow() {
    }

    @Override
    public boolean awaitTermination(long left, TimeUnit milliseconds) throws InterruptedException {
        //TODO: Waiting for all currently running pollAndProcessSingleTask to complete 
        return true;
    }
}