CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-temporal--temporal-sdk

Temporal Workflow Java SDK - A framework for authoring Workflows and Activities in Java

Overview
Eval results
Files

exceptions.mddocs/

Exception Hierarchy and Error Handling

Comprehensive exception hierarchy for handling workflow and activity failures, with support for retries, timeouts, cancellation, and custom application failures.

Capabilities

Base Exception Classes

Foundation classes for the Temporal exception hierarchy.

/**
 * Base class for all Temporal-related exceptions.
 */
public class TemporalException extends RuntimeException {
    /**
     * Creates TemporalException with message.
     * @param message exception message
     */
    public TemporalException(String message);

    /**
     * Creates TemporalException with message and cause.
     * @param message exception message
     * @param cause underlying cause
     */
    public TemporalException(String message, Throwable cause);

    /**
     * Creates TemporalException with cause.
     * @param cause underlying cause
     */
    public TemporalException(Throwable cause);
}

/**
 * Base for failures that can cross workflow boundaries.
 */
public abstract class TemporalFailure extends TemporalException {
    /**
     * Creates TemporalFailure with message and cause.
     * @param message failure message
     * @param cause original cause
     * @param dataConverter data converter for details
     */
    protected TemporalFailure(String message, Throwable cause, DataConverter dataConverter);

    /**
     * Gets original failure that was converted.
     * @return original failure or null
     */
    public Throwable getOriginalFailure();

    /**
     * Gets failure details as Optional.
     * @param detailsClass class of details
     * @param detailsType generic type of details
     * @return optional failure details
     */
    public <T> Optional<T> getDetails(Class<T> detailsClass, Type detailsType);

    /**
     * Gets failure details as Optional.
     * @param detailsClass class of details
     * @return optional failure details
     */
    public <T> Optional<T> getDetails(Class<T> detailsClass);

    /**
     * Gets raw failure details.
     * @return optional payloads
     */
    public Optional<Payloads> getDetailsPayloads();

    /**
     * Gets data converter used for details.
     * @return data converter
     */
    public DataConverter getDataConverter();
}

Application Failures

Application-level failures with custom error types and retry control.

/**
 * Application-level failures with custom error types.
 */
public final class ApplicationFailure extends TemporalFailure {
    /**
     * Creates new application failure.
     * @param message error message
     * @param type error type
     * @param nonRetryable whether failure should not be retried
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newFailure(String message, String type, boolean nonRetryable, Object... details);

    /**
     * Creates retryable application failure.
     * @param message error message
     * @param type error type
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newFailure(String message, String type, Object... details);

    /**
     * Creates non-retryable application failure.
     * @param message error message
     * @param type error type
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newNonRetryableFailure(String message, String type, Object... details);

    /**
     * Creates application failure from throwable.
     * @param message error message
     * @param type error type
     * @param nonRetryable whether failure should not be retried
     * @param cause original cause
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newFailureWithCause(String message, String type, boolean nonRetryable, Throwable cause, Object... details);

    /**
     * Creates retryable failure with cause.
     * @param message error message
     * @param type error type
     * @param cause original cause
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newFailureWithCause(String message, String type, Throwable cause, Object... details);

    /**
     * Creates non-retryable failure with cause.
     * @param message error message
     * @param type error type
     * @param cause original cause
     * @param details additional details
     * @return ApplicationFailure instance
     */
    public static ApplicationFailure newNonRetryableFailureWithCause(String message, String type, Throwable cause, Object... details);

    /**
     * Gets application error type.
     * @return error type
     */
    public String getType();

    /**
     * Checks if failure is non-retryable.
     * @return true if non-retryable
     */
    public boolean isNonRetryable();
}

Usage Examples:

public class PaymentActivitiesImpl implements PaymentActivities {
    @Override
    public PaymentResult processPayment(PaymentInfo paymentInfo) {
        try {
            return paymentService.charge(paymentInfo);
        } catch (InsufficientFundsException e) {
            // Non-retryable business error
            throw ApplicationFailure.newNonRetryableFailure(
                "Insufficient funds",
                "INSUFFICIENT_FUNDS",
                paymentInfo.getAmount(),
                paymentInfo.getAccountId()
            );
        } catch (PaymentGatewayException e) {
            // Retryable technical error
            throw ApplicationFailure.newFailure(
                "Payment gateway temporarily unavailable",
                "GATEWAY_ERROR",
                e.getGatewayCode()
            );
        }
    }
}

// Catching application failures in workflows
public class OrderWorkflowImpl implements OrderWorkflow {
    @Override
    public OrderResult processOrder(OrderRequest request) {
        try {
            PaymentResult payment = activities.processPayment(request.getPaymentInfo());
            return new OrderResult(true, payment.getTransactionId());
        } catch (ApplicationFailure e) {
            if ("INSUFFICIENT_FUNDS".equals(e.getType())) {
                // Handle insufficient funds
                return new OrderResult(false, "Payment declined: insufficient funds");
            } else if (e.isNonRetryable()) {
                // Handle other non-retryable errors
                return new OrderResult(false, "Payment failed: " + e.getMessage());
            } else {
                // Let retryable errors propagate
                throw e;
            }
        }
    }
}

Activity Failures

Failures that wrap exceptions from activity executions.

/**
 * Wraps exceptions thrown by activity executions.
 */
public final class ActivityFailure extends TemporalFailure {
    /**
     * Gets scheduled event ID.
     * @return scheduled event ID
     */
    public long getScheduledEventId();

    /**
     * Gets started event ID.
     * @return started event ID
     */
    public long getStartedEventId();

    /**
     * Gets activity type.
     * @return activity type
     */
    public String getActivityType();

    /**
     * Gets activity ID.
     * @return activity ID
     */
    public String getActivityId();

    /**
     * Gets retry state.
     * @return retry state
     */
    public RetryState getRetryState();
}

Child Workflow Failures

Failures from child workflow executions.

/**
 * Wraps failures from child workflow executions.
 */
public final class ChildWorkflowFailure extends TemporalFailure {
    /**
     * Gets namespace of child workflow.
     * @return namespace
     */
    public String getNamespace();

    /**
     * Gets workflow execution of child.
     * @return workflow execution
     */
    public WorkflowExecution getExecution();

    /**
     * Gets workflow type of child.
     * @return workflow type
     */
    public String getWorkflowType();

    /**
     * Gets initiated event ID.
     * @return initiated event ID
     */
    public long getInitiatedEventId();

    /**
     * Gets started event ID.
     * @return started event ID
     */
    public long getStartedEventId();

    /**
     * Gets retry state.
     * @return retry state
     */
    public RetryState getRetryState();
}

Timeout Failures

Failures indicating timeout occurred during execution.

/**
 * Indicates timeout occurred during execution.
 */
public final class TimeoutFailure extends TemporalFailure {
    /**
     * Gets timeout type.
     * @return timeout type
     */
    public TimeoutType getTimeoutType();

    /**
     * Gets last heartbeat details if available.
     * @param detailsClass class of details
     * @param detailsType generic type of details
     * @return optional heartbeat details
     */
    public <T> Optional<T> getLastHeartbeatDetails(Class<T> detailsClass, Type detailsType);

    /**
     * Gets last heartbeat details if available.
     * @param detailsClass class of details
     * @return optional heartbeat details
     */
    public <T> Optional<T> getLastHeartbeatDetails(Class<T> detailsClass);
}

/**
 * Types of timeouts that can occur.
 */
public enum TimeoutType {
    START_TO_CLOSE,
    SCHEDULE_TO_START,
    SCHEDULE_TO_CLOSE,
    HEARTBEAT
}

Usage Examples:

public class TimeoutHandlingWorkflowImpl implements TimeoutHandlingWorkflow {
    @Override
    public String processWithTimeouts(ProcessingRequest request) {
        try {
            // Activity with timeout
            ProcessingActivities activities = Workflow.newActivityStub(
                ProcessingActivities.class,
                ActivityOptions.newBuilder()
                    .setStartToCloseTimeout(Duration.ofMinutes(5))
                    .setHeartbeatTimeout(Duration.ofMinutes(1))
                    .build()
            );

            return activities.processData(request);
        } catch (ActivityFailure e) {
            if (e.getCause() instanceof TimeoutFailure) {
                TimeoutFailure timeout = (TimeoutFailure) e.getCause();
                switch (timeout.getTimeoutType()) {
                    case START_TO_CLOSE:
                        return handleStartToCloseTimeout(request, timeout);
                    case HEARTBEAT:
                        return handleHeartbeatTimeout(request, timeout);
                    default:
                        return "Processing failed due to timeout: " + timeout.getTimeoutType();
                }
            }
            throw e;
        }
    }

    private String handleHeartbeatTimeout(ProcessingRequest request, TimeoutFailure timeout) {
        // Get last heartbeat details to resume processing
        Optional<ProcessingProgress> progress = timeout.getLastHeartbeatDetails(ProcessingProgress.class);
        if (progress.isPresent()) {
            // Resume from last known progress
            request.setResumeFromIndex(progress.get().getProcessedCount());
            return "Resuming processing from index: " + progress.get().getProcessedCount();
        }
        return "Processing timed out without progress information";
    }
}

Cancellation Failures

Failures indicating workflow or activity was canceled.

/**
 * Indicates workflow or activity was canceled.
 */
public final class CanceledFailure extends TemporalFailure {
    /**
     * Creates CanceledFailure with details.
     * @param details cancellation details
     * @param dataConverter data converter
     * @return CanceledFailure instance
     */
    public static CanceledFailure newFailure(Object details, DataConverter dataConverter);

    /**
     * Creates CanceledFailure with message and details.
     * @param message cancellation message
     * @param details cancellation details
     * @param dataConverter data converter
     * @return CanceledFailure instance
     */
    public static CanceledFailure newFailure(String message, Object details, DataConverter dataConverter);
}

Usage Examples:

public class CancellationHandlingWorkflowImpl implements CancellationHandlingWorkflow {
    @Override
    public String processWithCancellation(ProcessingRequest request) {
        try {
            // Long running activity
            ProcessingActivities activities = Workflow.newActivityStub(ProcessingActivities.class);
            return activities.processLargeDataset(request);
        } catch (CanceledFailure e) {
            // Handle cancellation gracefully
            Optional<String> cancellationReason = e.getDetails(String.class);
            String reason = cancellationReason.orElse("No reason provided");

            // Perform cleanup
            activities.cleanupPartialProcessing(request.getId());

            return "Processing was canceled: " + reason;
        }
    }
}

public class CancellableActivityImpl implements CancellableActivity {
    @Override
    public String processData(String data) {
        ActivityExecutionContext context = Activity.getExecutionContext();

        try {
            for (int i = 0; i < 1000; i++) {
                // Check for cancellation via heartbeat
                context.heartbeat("Processing item " + i);

                // Process item
                Thread.sleep(1000);
            }
            return "Processing completed";
        } catch (ActivityCompletionException e) {
            if (e.getCause() instanceof CanceledFailure) {
                // Activity was canceled
                return "Processing canceled at item " + getCurrentIndex();
            }
            throw Activity.wrap(e);
        }
    }
}

Termination Failures

Failures indicating workflow was terminated.

/**
 * Indicates workflow was terminated.
 */
public final class TerminatedFailure extends TemporalFailure {
    /**
     * Creates TerminatedFailure.
     * @param reason termination reason
     * @param details termination details
     * @param dataConverter data converter
     * @return TerminatedFailure instance
     */
    public static TerminatedFailure newFailure(String reason, Object details, DataConverter dataConverter);
}

Server Failures

Failures originating from the Temporal server.

/**
 * Failures originating from the Temporal server.
 */
public final class ServerFailure extends TemporalFailure {
    /**
     * Gets server error type.
     * @return server error type
     */
    public String getType();

    /**
     * Checks if failure is non-retryable.
     * @return true if non-retryable
     */
    public boolean isNonRetryable();
}

Nexus Operation Failures

Failures from Nexus operation executions.

/**
 * Failures from Nexus operation executions.
 */
public final class NexusOperationFailure extends TemporalFailure {
    /**
     * Gets scheduled event ID.
     * @return scheduled event ID
     */
    public long getScheduledEventId();

    /**
     * Gets endpoint name.
     * @return endpoint name
     */
    public String getEndpoint();

    /**
     * Gets service name.
     * @return service name
     */
    public String getService();

    /**
     * Gets operation name.
     * @return operation name
     */
    public String getOperation();

    /**
     * Gets operation ID.
     * @return operation ID
     */
    public String getOperationId();
}

Default Failure Converter

Default implementation for converting between exceptions and Temporal failures.

/**
 * Default implementation for converting between exceptions and Temporal failures.
 */
public class DefaultFailureConverter implements FailureConverter {
    /**
     * Gets default instance.
     * @return default failure converter
     */
    public static DefaultFailureConverter INSTANCE;

    /**
     * Converts exception to failure.
     * @param exception exception to convert
     * @param dataConverter data converter for details
     * @return temporal failure
     */
    @Override
    public TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter);

    /**
     * Converts failure to exception.
     * @param failure failure to convert
     * @param dataConverter data converter for details
     * @return exception
     */
    @Override
    public Throwable failureToException(FailureInfo failure, DataConverter dataConverter);
}

/**
 * Interface for converting between exceptions and failures.
 */
public interface FailureConverter {
    /**
     * Converts exception to failure for transmission.
     * @param exception exception to convert
     * @param dataConverter data converter
     * @return temporal failure
     */
    TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter);

    /**
     * Converts failure back to exception.
     * @param failure failure info from server
     * @param dataConverter data converter
     * @return exception
     */
    Throwable failureToException(FailureInfo failure, DataConverter dataConverter);
}

Usage Examples:

public class CustomFailureConverter implements FailureConverter {
    @Override
    public TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter) {
        if (exception instanceof CustomBusinessException) {
            CustomBusinessException cbe = (CustomBusinessException) exception;
            return ApplicationFailure.newFailure(
                cbe.getMessage(),
                cbe.getErrorCode(),
                cbe.isRetryable() == false, // nonRetryable
                cbe.getContext()
            );
        }

        // Delegate to default converter
        return DefaultFailureConverter.INSTANCE.exceptionToFailure(exception, dataConverter);
    }

    @Override
    public Throwable failureToException(FailureInfo failure, DataConverter dataConverter) {
        // Convert back to custom exception if needed
        if (failure.getType().equals("CustomBusinessException")) {
            return new CustomBusinessException(
                failure.getMessage(),
                failure.getSource(),
                failure.getNonRetryableFlag()
            );
        }

        // Delegate to default converter
        return DefaultFailureConverter.INSTANCE.failureToException(failure, dataConverter);
    }
}

public class ErrorHandlingExample {
    public void demonstrateErrorHandling() {
        try {
            // Call activity that might fail
            String result = activities.riskyOperation();
        } catch (ActivityFailure activityFailure) {
            Throwable cause = activityFailure.getCause();

            if (cause instanceof ApplicationFailure) {
                ApplicationFailure appFailure = (ApplicationFailure) cause;

                switch (appFailure.getType()) {
                    case "VALIDATION_ERROR":
                        // Handle validation errors
                        handleValidationError(appFailure);
                        break;
                    case "BUSINESS_RULE_VIOLATION":
                        // Handle business rule violations
                        handleBusinessRuleViolation(appFailure);
                        break;
                    default:
                        // Handle other application failures
                        handleGenericApplicationFailure(appFailure);
                }
            } else if (cause instanceof TimeoutFailure) {
                TimeoutFailure timeoutFailure = (TimeoutFailure) cause;
                handleTimeout(timeoutFailure);
            }
        } catch (ChildWorkflowFailure childFailure) {
            // Handle child workflow failures
            System.err.println("Child workflow failed: " + childFailure.getWorkflowType());
        }
    }

    private void handleValidationError(ApplicationFailure failure) {
        Optional<ValidationErrorDetails> details = failure.getDetails(ValidationErrorDetails.class);
        if (details.isPresent()) {
            System.err.println("Validation failed: " + details.get().getFieldErrors());
        }
    }
}

Retry State Enum

Indicates the current retry state of a failed execution.

/**
 * Indicates the current retry state of a failed execution.
 */
public enum RetryState {
    /**
     * Execution is being retried.
     */
    IN_PROGRESS,

    /**
     * Execution failed non-retryably or retry policy exhausted.
     */
    NON_RETRYABLE_FAILURE,

    /**
     * Timeout exceeded while retrying.
     */
    TIMEOUT,

    /**
     * Maximum number of attempts reached.
     */
    MAXIMUM_ATTEMPTS_REACHED,

    /**
     * Retry policy not set.
     */
    RETRY_POLICY_NOT_SET,

    /**
     * Internal service error during retries.
     */
    INTERNAL_SERVICE_ERROR,

    /**
     * Execution was canceled while retrying.
     */
    CANCEL_REQUESTED
}

Install with Tessl CLI

npx tessl i tessl/maven-io-temporal--temporal-sdk

docs

activities.md

client.md

data-conversion.md

exceptions.md

index.md

workers.md

workflows.md

tile.json