Skip to content

Commit 7577911

Browse files
Add new constructor for WorkflowStub to target correct execution (#2709)
Add new constructor for WorkflowStub to target correct execution
1 parent 5394310 commit 7577911

28 files changed

+616
-109
lines changed

temporal-sdk/src/main/java/io/temporal/client/WorkflowClient.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,23 @@ static WorkflowClient newInstance(WorkflowServiceStubs service, WorkflowClientOp
158158
* @param workflowId Workflow id.
159159
* @param runId Run id of the workflow execution.
160160
* @return Stub that implements workflowInterface and can be used to signal, update, or query it.
161+
* @deprecated Use {@link #newWorkflowStub(Class, WorkflowTargetOptions)} instead.
162+
* @apiNote This method is deprecated because the returned stub does not properly account for the
163+
* runId.
161164
*/
165+
@Deprecated
162166
<T> T newWorkflowStub(Class<T> workflowInterface, String workflowId, Optional<String> runId);
163167

168+
/**
169+
* Creates workflow client stub for a known execution. Use it to send signals or queries to a
170+
* running workflow. Do not call methods annotated with @WorkflowMethod.
171+
*
172+
* @param workflowInterface interface that given workflow implements.
173+
* @param workflowTargetOptions options that specify target workflow execution.
174+
* @return Stub that implements workflowInterface and can be used to signal or query it.
175+
*/
176+
<T> T newWorkflowStub(Class<T> workflowInterface, WorkflowTargetOptions workflowTargetOptions);
177+
164178
/**
165179
* Creates workflow untyped client stub that can be used to start a single workflow execution. Use
166180
* it to send signals or queries to a running workflow. Do not call methods annotated
@@ -191,7 +205,11 @@ static WorkflowClient newInstance(WorkflowServiceStubs service, WorkflowClientOp
191205
* workflowId is assumed.
192206
* @param workflowType type of the workflow. Optional as it is used for error reporting only.
193207
* @return Stub that can be used to start workflow and later to signal or query it.
208+
* @deprecated Use {@link #newUntypedWorkflowStub(WorkflowTargetOptions, Optional)} instead.
209+
* @apiNote This method is deprecated because the returned stub does not properly account for the
210+
* runId.
194211
*/
212+
@Deprecated
195213
WorkflowStub newUntypedWorkflowStub(
196214
String workflowId, Optional<String> runId, Optional<String> workflowType);
197215

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

229+
/**
230+
* Creates workflow untyped client stub for a known execution. Use it to send signals or queries
231+
* to a running workflow. Do not call methods annotated with @WorkflowMethod.
232+
*
233+
* @param workflowTargetOptions options that specify target workflow execution.
234+
* @return Stub that can be used to start workflow and later to signal or query it.
235+
*/
236+
WorkflowStub newUntypedWorkflowStub(WorkflowTargetOptions workflowTargetOptions);
237+
238+
/**
239+
* Creates workflow untyped client stub for a known execution. Use it to send signals or queries
240+
* to a running workflow. Do not call methods annotated with @WorkflowMethod.
241+
*
242+
* @param workflowTargetOptions options that specify target workflow execution.
243+
* @param workflowType type of the workflow. Optional as it is used for error reporting only.
244+
* @return Stub that can be used to start workflow and later to signal or query it.
245+
*/
246+
WorkflowStub newUntypedWorkflowStub(
247+
WorkflowTargetOptions workflowTargetOptions, Optional<String> workflowType);
248+
208249
/**
209250
* Creates new {@link ActivityCompletionClient} that can be used to complete activities
210251
* asynchronously. Only relevant for activity implementations that called {@link

temporal-sdk/src/main/java/io/temporal/client/WorkflowClientInternalImpl.java

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,24 +149,51 @@ public <T> T newWorkflowStub(Class<T> workflowInterface, String workflowId) {
149149
return newWorkflowStub(workflowInterface, workflowId, Optional.empty());
150150
}
151151

152+
public <T> T newWorkflowStub(
153+
Class<T> workflowInterface, WorkflowTargetOptions workflowTargetOptions) {
154+
return newWorkflowStub(workflowInterface, workflowTargetOptions, false);
155+
}
156+
152157
@Override
158+
@SuppressWarnings("deprecation")
153159
public <T> T newWorkflowStub(
154160
Class<T> workflowInterface, String workflowId, Optional<String> runId) {
161+
return newWorkflowStub(
162+
workflowInterface,
163+
WorkflowTargetOptions.newBuilder()
164+
.setWorkflowId(workflowId)
165+
.setRunId(runId.orElse(null))
166+
.build(),
167+
true);
168+
}
169+
170+
public <T> T newWorkflowStub(
171+
Class<T> workflowInterface,
172+
WorkflowTargetOptions workflowTargetOptions,
173+
boolean legacyTargeting) {
155174
checkAnnotation(
156175
workflowInterface,
157176
WorkflowMethod.class,
158177
QueryMethod.class,
159178
SignalMethod.class,
160179
UpdateMethod.class);
161-
if (Strings.isNullOrEmpty(workflowId)) {
180+
if (Strings.isNullOrEmpty(workflowTargetOptions.getWorkflowId())) {
162181
throw new IllegalArgumentException("workflowId is null or empty");
163182
}
164-
WorkflowExecution execution =
165-
WorkflowExecution.newBuilder().setWorkflowId(workflowId).setRunId(runId.orElse("")).build();
183+
WorkflowExecution.Builder execution =
184+
WorkflowExecution.newBuilder().setWorkflowId(workflowTargetOptions.getWorkflowId());
185+
if (!Strings.isNullOrEmpty(workflowTargetOptions.getRunId())) {
186+
execution.setRunId(workflowTargetOptions.getRunId());
187+
}
166188

167189
WorkflowInvocationHandler invocationHandler =
168190
new WorkflowInvocationHandler(
169-
workflowInterface, this.getOptions(), workflowClientCallsInvoker, execution);
191+
workflowInterface,
192+
this.getOptions(),
193+
workflowClientCallsInvoker,
194+
execution.build(),
195+
legacyTargeting,
196+
workflowTargetOptions.getFirstExecutionRunId());
170197
@SuppressWarnings("unchecked")
171198
T result =
172199
(T)
@@ -194,6 +221,7 @@ public WorkflowStub newUntypedWorkflowStub(String workflowType, WorkflowOptions
194221
}
195222

196223
@Override
224+
@SuppressWarnings("deprecation")
197225
public WorkflowStub newUntypedWorkflowStub(
198226
String workflowId, Optional<String> runId, Optional<String> workflowType) {
199227
WorkflowExecution execution =
@@ -205,10 +233,46 @@ public WorkflowStub newUntypedWorkflowStub(
205233
@SuppressWarnings("deprecation")
206234
public WorkflowStub newUntypedWorkflowStub(
207235
WorkflowExecution execution, Optional<String> workflowType) {
236+
return newUntypedWorkflowStub(
237+
workflowType,
238+
true,
239+
WorkflowTargetOptions.newBuilder()
240+
.setWorkflowId(execution.getWorkflowId())
241+
.setRunId(execution.getRunId())
242+
.build());
243+
}
244+
245+
@Override
246+
public WorkflowStub newUntypedWorkflowStub(WorkflowTargetOptions workflowTargetOptions) {
247+
return newUntypedWorkflowStub(Optional.empty(), false, workflowTargetOptions);
248+
}
249+
250+
@Override
251+
public WorkflowStub newUntypedWorkflowStub(
252+
WorkflowTargetOptions workflowTargetOptions, Optional<String> workflowType) {
253+
return newUntypedWorkflowStub(workflowType, false, workflowTargetOptions);
254+
}
255+
256+
@SuppressWarnings("deprecation")
257+
WorkflowStub newUntypedWorkflowStub(
258+
Optional<String> workflowType,
259+
boolean legacyTargeting,
260+
WorkflowTargetOptions workflowTargetOptions) {
261+
WorkflowExecution.Builder execution =
262+
WorkflowExecution.newBuilder().setWorkflowId(workflowTargetOptions.getWorkflowId());
263+
if (!Strings.isNullOrEmpty(workflowTargetOptions.getRunId())) {
264+
execution.setRunId(workflowTargetOptions.getRunId());
265+
}
208266
WorkflowStub result =
209-
new WorkflowStubImpl(options, workflowClientCallsInvoker, workflowType, execution);
267+
new WorkflowStubImpl(
268+
options,
269+
workflowClientCallsInvoker,
270+
workflowType,
271+
execution.build(),
272+
legacyTargeting,
273+
workflowTargetOptions.getFirstExecutionRunId());
210274
for (WorkflowClientInterceptor i : interceptors) {
211-
result = i.newUntypedWorkflowStub(execution, workflowType, result);
275+
result = i.newUntypedWorkflowStub(execution.build(), workflowType, result);
212276
}
213277
return result;
214278
}

temporal-sdk/src/main/java/io/temporal/client/WorkflowInvocationHandler.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.lang.reflect.InvocationHandler;
2121
import java.lang.reflect.Method;
2222
import java.util.*;
23+
import javax.annotation.Nullable;
2324

2425
/**
2526
* Dynamic implementation of a strongly typed workflow interface that can be used to start, signal
@@ -107,11 +108,19 @@ static void closeAsyncInvocation() {
107108
Class<?> workflowInterface,
108109
WorkflowClientOptions clientOptions,
109110
WorkflowClientCallsInterceptor workflowClientCallsInvoker,
110-
WorkflowExecution execution) {
111+
WorkflowExecution execution,
112+
boolean legacyTargeting,
113+
@Nullable String firstExecutionRunId) {
111114
workflowMetadata = POJOWorkflowInterfaceMetadata.newInstance(workflowInterface, false);
112115
Optional<String> workflowType = workflowMetadata.getWorkflowType();
113116
WorkflowStub stub =
114-
new WorkflowStubImpl(clientOptions, workflowClientCallsInvoker, workflowType, execution);
117+
new WorkflowStubImpl(
118+
clientOptions,
119+
workflowClientCallsInvoker,
120+
workflowType,
121+
execution,
122+
legacyTargeting,
123+
firstExecutionRunId);
115124
for (WorkflowClientInterceptor i : clientOptions.getInterceptors()) {
116125
stub = i.newUntypedWorkflowStub(execution, workflowType, stub);
117126
}

temporal-sdk/src/main/java/io/temporal/client/WorkflowStub.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* WorkflowStub is a client side stub to a single workflow instance. It can be used to start,
2020
* signal, query, update, wait for completion and cancel a workflow execution. Created through
2121
* {@link WorkflowClient#newUntypedWorkflowStub(String, WorkflowOptions)} or {@link
22-
* WorkflowClient#newUntypedWorkflowStub(WorkflowExecution, Optional)}.
22+
* WorkflowClient#newUntypedWorkflowStub(WorkflowTargetOptions, Optional)}.
2323
*/
2424
public interface WorkflowStub {
2525

@@ -160,10 +160,25 @@ <R> WorkflowUpdateHandle<R> startUpdateWithStart(
160160
<R> R executeUpdateWithStart(
161161
UpdateOptions<R> updateOptions, Object[] updateArgs, Object[] startArgs);
162162

163+
/**
164+
* Sends a signal to a workflow, starting the workflow if it is not already running.
165+
*
166+
* @param signalName name of the signal handler. Usually it is a method name.
167+
* @param signalArgs signal method arguments
168+
* @param startArgs workflow start arguments
169+
* @return workflow execution
170+
*/
163171
WorkflowExecution signalWithStart(String signalName, Object[] signalArgs, Object[] startArgs);
164172

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

178+
/**
179+
* @return current workflow execution. Returns null if the workflow has not been started yet.
180+
*/
181+
@Nullable
167182
WorkflowExecution getExecution();
168183

169184
/**
@@ -406,6 +421,9 @@ <R> CompletableFuture<R> getResultAsync(
406421
*/
407422
WorkflowExecutionDescription describe();
408423

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

411429
/**

0 commit comments

Comments
 (0)