Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,23 @@ static WorkflowClient newInstance(WorkflowServiceStubs service, WorkflowClientOp
* @param workflowId Workflow id.
* @param runId Run id of the workflow execution.
* @return Stub that implements workflowInterface and can be used to signal, update, or query it.
* @deprecated Use {@link #newWorkflowStub(Class, WorkflowTargetOptions)} instead.
* @apiNote This method is deprecated because the returned stub does not properly account for the
* runId.
*/
@Deprecated
<T> T newWorkflowStub(Class<T> workflowInterface, String workflowId, Optional<String> runId);

/**
* Creates workflow client stub for a known execution. Use it to send signals or queries to a
* running workflow. Do not call methods annotated with @WorkflowMethod.
*
* @param workflowInterface interface that given workflow implements.
* @param workflowTargetOptions options that specify target workflow execution.
* @return Stub that implements workflowInterface and can be used to signal or query it.
*/
<T> T newWorkflowStub(Class<T> workflowInterface, WorkflowTargetOptions workflowTargetOptions);
Copy link
Member

@cretz cretz Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic, but I like WorkflowStubOptions name myself in case we ever want an option unrelated to "workflow target"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah my reason for not using WorkflowStubOptions was because these options are specifically for creating a stub that is attached to a running workflow, instead of a stub that can start a workflow


/**
* Creates workflow untyped client stub that can be used to start a single workflow execution. Use
* it to send signals or queries to a running workflow. Do not call methods annotated
Expand Down Expand Up @@ -191,7 +205,11 @@ static WorkflowClient newInstance(WorkflowServiceStubs service, WorkflowClientOp
* workflowId is assumed.
* @param workflowType type of the workflow. Optional as it is used for error reporting only.
* @return Stub that can be used to start workflow and later to signal or query it.
* @deprecated Use {@link #newUntypedWorkflowStub(WorkflowTargetOptions, Optional)} instead.
* @apiNote This method is deprecated because the returned stub does not properly account for the
* runId.
*/
@Deprecated
WorkflowStub newUntypedWorkflowStub(
String workflowId, Optional<String> runId, Optional<String> workflowType);

Expand All @@ -202,9 +220,32 @@ WorkflowStub newUntypedWorkflowStub(
* @param execution workflow id and optional run id for execution
* @param workflowType type of the workflow. Optional as it is used for error reporting only.
* @return Stub that can be used to start workflow and later to signal or query it.
* @deprecated Use {@link #newUntypedWorkflowStub(WorkflowTargetOptions, Optional)} instead.
* @apiNote This method is deprecated because the returned stub does not properly account for the
* runId.
*/
WorkflowStub newUntypedWorkflowStub(WorkflowExecution execution, Optional<String> workflowType);

/**
* Creates workflow untyped client stub for a known execution. Use it to send signals or queries
* to a running workflow. Do not call methods annotated with @WorkflowMethod.
*
* @param workflowTargetOptions options that specify target workflow execution.
* @return Stub that can be used to start workflow and later to signal or query it.
*/
WorkflowStub newUntypedWorkflowStub(WorkflowTargetOptions workflowTargetOptions);

/**
* Creates workflow untyped client stub for a known execution. Use it to send signals or queries
* to a running workflow. Do not call methods annotated with @WorkflowMethod.
*
* @param workflowTargetOptions options that specify target workflow execution.
* @param workflowType type of the workflow. Optional as it is used for error reporting only.
* @return Stub that can be used to start workflow and later to signal or query it.
*/
WorkflowStub newUntypedWorkflowStub(
WorkflowTargetOptions workflowTargetOptions, Optional<String> workflowType);

/**
* Creates new {@link ActivityCompletionClient} that can be used to complete activities
* asynchronously. Only relevant for activity implementations that called {@link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,51 @@ public <T> T newWorkflowStub(Class<T> workflowInterface, String workflowId) {
return newWorkflowStub(workflowInterface, workflowId, Optional.empty());
}

public <T> T newWorkflowStub(
Class<T> workflowInterface, WorkflowTargetOptions workflowTargetOptions) {
return newWorkflowStub(workflowInterface, workflowTargetOptions, false);
}

@Override
@SuppressWarnings("deprecation")
public <T> T newWorkflowStub(
Class<T> workflowInterface, String workflowId, Optional<String> runId) {
return newWorkflowStub(
workflowInterface,
WorkflowTargetOptions.newBuilder()
.setWorkflowId(workflowId)
.setRunId(runId.orElse(null))
.build(),
true);
}

public <T> T newWorkflowStub(
Class<T> workflowInterface,
WorkflowTargetOptions workflowTargetOptions,
boolean legacyTargeting) {
checkAnnotation(
workflowInterface,
WorkflowMethod.class,
QueryMethod.class,
SignalMethod.class,
UpdateMethod.class);
if (Strings.isNullOrEmpty(workflowId)) {
if (Strings.isNullOrEmpty(workflowTargetOptions.getWorkflowId())) {
throw new IllegalArgumentException("workflowId is null or empty");
}
WorkflowExecution execution =
WorkflowExecution.newBuilder().setWorkflowId(workflowId).setRunId(runId.orElse("")).build();
WorkflowExecution.Builder execution =
WorkflowExecution.newBuilder().setWorkflowId(workflowTargetOptions.getWorkflowId());
if (!Strings.isNullOrEmpty(workflowTargetOptions.getRunId())) {
execution.setRunId(workflowTargetOptions.getRunId());
}

WorkflowInvocationHandler invocationHandler =
new WorkflowInvocationHandler(
workflowInterface, this.getOptions(), workflowClientCallsInvoker, execution);
workflowInterface,
this.getOptions(),
workflowClientCallsInvoker,
execution.build(),
legacyTargeting,
workflowTargetOptions.getFirstExecutionRunId());
@SuppressWarnings("unchecked")
T result =
(T)
Expand Down Expand Up @@ -194,6 +221,7 @@ public WorkflowStub newUntypedWorkflowStub(String workflowType, WorkflowOptions
}

@Override
@SuppressWarnings("deprecation")
public WorkflowStub newUntypedWorkflowStub(
String workflowId, Optional<String> runId, Optional<String> workflowType) {
WorkflowExecution execution =
Expand All @@ -205,10 +233,46 @@ public WorkflowStub newUntypedWorkflowStub(
@SuppressWarnings("deprecation")
public WorkflowStub newUntypedWorkflowStub(
WorkflowExecution execution, Optional<String> workflowType) {
return newUntypedWorkflowStub(
workflowType,
true,
WorkflowTargetOptions.newBuilder()
.setWorkflowId(execution.getWorkflowId())
.setRunId(execution.getRunId())
.build());
}

@Override
public WorkflowStub newUntypedWorkflowStub(WorkflowTargetOptions workflowTargetOptions) {
return newUntypedWorkflowStub(Optional.empty(), false, workflowTargetOptions);
}

@Override
public WorkflowStub newUntypedWorkflowStub(
WorkflowTargetOptions workflowTargetOptions, Optional<String> workflowType) {
return newUntypedWorkflowStub(workflowType, false, workflowTargetOptions);
}

@SuppressWarnings("deprecation")
WorkflowStub newUntypedWorkflowStub(
Optional<String> workflowType,
boolean legacyTargeting,
WorkflowTargetOptions workflowTargetOptions) {
WorkflowExecution.Builder execution =
WorkflowExecution.newBuilder().setWorkflowId(workflowTargetOptions.getWorkflowId());
if (!Strings.isNullOrEmpty(workflowTargetOptions.getRunId())) {
execution.setRunId(workflowTargetOptions.getRunId());
}
WorkflowStub result =
new WorkflowStubImpl(options, workflowClientCallsInvoker, workflowType, execution);
new WorkflowStubImpl(
options,
workflowClientCallsInvoker,
workflowType,
execution.build(),
legacyTargeting,
workflowTargetOptions.getFirstExecutionRunId());
for (WorkflowClientInterceptor i : interceptors) {
result = i.newUntypedWorkflowStub(execution, workflowType, result);
result = i.newUntypedWorkflowStub(execution.build(), workflowType, result);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.*;
import javax.annotation.Nullable;

/**
* Dynamic implementation of a strongly typed workflow interface that can be used to start, signal
Expand Down Expand Up @@ -107,11 +108,19 @@ static void closeAsyncInvocation() {
Class<?> workflowInterface,
WorkflowClientOptions clientOptions,
WorkflowClientCallsInterceptor workflowClientCallsInvoker,
WorkflowExecution execution) {
WorkflowExecution execution,
boolean legacyTargeting,
@Nullable String firstExecutionRunId) {
workflowMetadata = POJOWorkflowInterfaceMetadata.newInstance(workflowInterface, false);
Optional<String> workflowType = workflowMetadata.getWorkflowType();
WorkflowStub stub =
new WorkflowStubImpl(clientOptions, workflowClientCallsInvoker, workflowType, execution);
new WorkflowStubImpl(
clientOptions,
workflowClientCallsInvoker,
workflowType,
execution,
legacyTargeting,
firstExecutionRunId);
for (WorkflowClientInterceptor i : clientOptions.getInterceptors()) {
stub = i.newUntypedWorkflowStub(execution, workflowType, stub);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* WorkflowStub is a client side stub to a single workflow instance. It can be used to start,
* signal, query, update, wait for completion and cancel a workflow execution. Created through
* {@link WorkflowClient#newUntypedWorkflowStub(String, WorkflowOptions)} or {@link
* WorkflowClient#newUntypedWorkflowStub(WorkflowExecution, Optional)}.
* WorkflowClient#newUntypedWorkflowStub(WorkflowTargetOptions, Optional)}.
*/
public interface WorkflowStub {

Expand Down Expand Up @@ -160,10 +160,25 @@ <R> WorkflowUpdateHandle<R> startUpdateWithStart(
<R> R executeUpdateWithStart(
UpdateOptions<R> updateOptions, Object[] updateArgs, Object[] startArgs);

/**
* Sends a signal to a workflow, starting the workflow if it is not already running.
*
* @param signalName name of the signal handler. Usually it is a method name.
* @param signalArgs signal method arguments
* @param startArgs workflow start arguments
* @return workflow execution
*/
WorkflowExecution signalWithStart(String signalName, Object[] signalArgs, Object[] startArgs);

/**
* @return workflow type name if it was provided when the stub was created.
*/
Optional<String> getWorkflowType();

/**
* @return current workflow execution. Returns null if the workflow has not been started yet.
*/
@Nullable
WorkflowExecution getExecution();

/**
Expand Down Expand Up @@ -406,6 +421,9 @@ <R> CompletableFuture<R> getResultAsync(
*/
WorkflowExecutionDescription describe();

/**
* @return workflow options if they were provided when the stub was created.
*/
Optional<WorkflowOptions> getOptions();

/**
Expand Down
Loading
Loading