diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandler.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandler.java index 18ef07f8c..d06793141 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandler.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandler.java @@ -83,4 +83,9 @@ protected Function getActivityFunc( (a) -> stub.execute(activityName, method.getReturnType(), method.getGenericReturnType(), a); return function; } + + @Override + protected String proxyToString() { + return "ActivityProxy{" + "options=" + options + '}'; + } } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandlerBase.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandlerBase.java index b073b5651..9405384ff 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandlerBase.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/ActivityInvocationHandlerBase.java @@ -53,6 +53,14 @@ public static T newProxy(Class activityInterface, InvocationHandler invoc @Override public Object invoke(Object proxy, Method method, Object[] args) { + // Proxy the toString method so the stub can be inspected when debugging. + try { + if (method.equals(Object.class.getMethod("toString"))) { + return proxyToString(); + } + } catch (NoSuchMethodException e) { + throw new Error("unexpected", e); + } POJOActivityMethodMetadata methodMetadata = activityMetadata.getMethodMetadata(method); MethodRetry methodRetry = methodMetadata.getMethod().getAnnotation(MethodRetry.class); String activityType = methodMetadata.getActivityTypeName(); @@ -62,4 +70,6 @@ public Object invoke(Object proxy, Method method, Object[] args) { protected abstract Function getActivityFunc( Method method, MethodRetry methodRetry, String activityName); + + protected abstract String proxyToString(); } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/ChildWorkflowInvocationHandler.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/ChildWorkflowInvocationHandler.java index ebd6a5d23..69910a3f3 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/ChildWorkflowInvocationHandler.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/ChildWorkflowInvocationHandler.java @@ -71,6 +71,14 @@ class ChildWorkflowInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) { + // Proxy the toString method so the stub can be inspected when debugging. + try { + if (method.equals(Object.class.getMethod("toString"))) { + return proxyToString(); + } + } catch (NoSuchMethodException e) { + throw new Error("unexpected", e); + } // Implement StubMarker if (method.getName().equals(StubMarker.GET_UNTYPED_STUB_METHOD)) { return stub; @@ -99,4 +107,14 @@ public Object invoke(Object proxy, Method method, Object[] args) { } throw new IllegalArgumentException("unreachable"); } + + private String proxyToString() { + return "ChildWorkflowProxy{" + + "workflowType='" + + stub.getWorkflowType() + + '\'' + + ", options=" + + stub.getOptions() + + '}'; + } } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/ExternalWorkflowInvocationHandler.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/ExternalWorkflowInvocationHandler.java index 5d201dee2..60171f574 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/ExternalWorkflowInvocationHandler.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/ExternalWorkflowInvocationHandler.java @@ -47,6 +47,14 @@ public ExternalWorkflowInvocationHandler( @Override public Object invoke(Object proxy, Method method, Object[] args) { + // Proxy the toString method so the stub can be inspected when debugging. + try { + if (method.equals(Object.class.getMethod("toString"))) { + return proxyToString(); + } + } catch (NoSuchMethodException e) { + throw new Error("unexpected", e); + } // Implement StubMarker if (method.getName().equals(StubMarker.GET_UNTYPED_STUB_METHOD)) { return stub; @@ -73,4 +81,14 @@ public Object invoke(Object proxy, Method method, Object[] args) { } return null; } + + private String proxyToString() { + return "ExternalWorkflowProxy{" + + "workflowType='" + + workflowMetadata.getWorkflowType().orElse("") + + '\'' + + ", execution=" + + stub.getExecution() + + '}'; + } } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/LocalActivityInvocationHandler.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/LocalActivityInvocationHandler.java index 6d12850f8..dc5511657 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/LocalActivityInvocationHandler.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/LocalActivityInvocationHandler.java @@ -79,4 +79,9 @@ public Function getActivityFunc( (a) -> stub.execute(activityName, method.getReturnType(), method.getGenericReturnType(), a); return function; } + + @Override + protected String proxyToString() { + return "LocalActivityProxy{" + "options='" + options + '}'; + } } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceInvocationHandler.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceInvocationHandler.java index e0110fa80..7f1bc10b7 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceInvocationHandler.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceInvocationHandler.java @@ -48,6 +48,15 @@ public class NexusServiceInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Proxy the toString method so the stub can be inspected when debugging. + try { + if (method.equals(Object.class.getMethod("toString"))) { + return proxyToString(); + } + } catch (NoSuchMethodException e) { + throw new Error("unexpected", e); + } + if (method.getName().equals(StubMarker.GET_UNTYPED_STUB_METHOD)) { return stub; } @@ -69,4 +78,14 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl this.stub.execute(opName, method.getReturnType(), method.getGenericReturnType(), arg), method.getReturnType()); } + + private String proxyToString() { + return "NexusServiceProxy{" + + "serviceName=" + + serviceDef.getName() + + '\'' + + ", options=" + + stub.getOptions() + + '}'; + } } diff --git a/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceStubImpl.java b/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceStubImpl.java index 2ec5a86f4..77f30def4 100644 --- a/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceStubImpl.java +++ b/temporal-sdk/src/main/java/io/temporal/internal/sync/NexusServiceStubImpl.java @@ -28,10 +28,10 @@ import java.util.Collections; public class NexusServiceStubImpl implements NexusServiceStub { - final String name; - final NexusServiceOptions options; - final WorkflowOutboundCallsInterceptor outboundCallsInterceptor; - final Functions.Proc1 assertReadOnly; + private final String name; + private final NexusServiceOptions options; + private final WorkflowOutboundCallsInterceptor outboundCallsInterceptor; + private final Functions.Proc1 assertReadOnly; public NexusServiceStubImpl( String name, @@ -118,6 +118,11 @@ public NexusOperationHandle start( arg, mergedOptions, Collections.emptyMap())); - return new NexusOperationHandleImpl(result.getOperationExecution(), result.getResult()); + return new NexusOperationHandleImpl<>(result.getOperationExecution(), result.getResult()); + } + + @Override + public NexusServiceOptions getOptions() { + return options; } } diff --git a/temporal-sdk/src/main/java/io/temporal/workflow/NexusServiceStub.java b/temporal-sdk/src/main/java/io/temporal/workflow/NexusServiceStub.java index f8f6f7084..1617cc262 100644 --- a/temporal-sdk/src/main/java/io/temporal/workflow/NexusServiceStub.java +++ b/temporal-sdk/src/main/java/io/temporal/workflow/NexusServiceStub.java @@ -109,4 +109,9 @@ Promise executeAsync( */ NexusOperationHandle start( String operationName, Class resultClass, Type resultType, Object arg); + + /** + * @return Options used to create this stub. + */ + NexusServiceOptions getOptions(); }