What is the recommended way to send a signal from a Workflow?

Thank you, but I need only for Java SDK, without tranfer signal from one SDK to another SDK.
If u help with in the Java SDK it would be more helpful. Can you demonstrate only with Java SDK?

It is the same idea, you can have one workflow which waits, for example:

Workflow.await(() -> unblockcondition);

and another which sends the signal:

ExternalWorkflowStub stub = Workflow.newUntypedExternalWorkflowStub("first-workflow-type");
stub.signal("signal-type", signalData);

Try it out and then post your code so we can look into specifics if you run into issues.

Hi All,

I am basically working on a similar scenario. In my case workflow, A waits for the signal from workflow B.
I am writing an integration test case using spring-boot and temporal java SDK.
I am facing the issue when workflow A keeps waiting for the signal. Is there a recommended way to achieve this . I mean some way to send signal to the waiting workflow .

Would you explain your problem? Here is documentation of signals.

Please find the below detail regarding the scenario.

  1. This is the code base for first workflow
public class OutboundWorkflowCommunication {

  static final String OUT_TEST_QUEUE = "OUTBOUND_QUEUE";

  static final String TASK_QUEUE = "TASK_QUEUE_OUT";

  static final String WORKFLOW_ID_OUT = "WORKFLOW_ID_OUT4";

  @WorkflowInterface
  public interface Outboundflow {
    @WorkflowMethod
    String getSomething(String name);

    @SignalMethod
    void getSignal(String message);
  }

  // 3 Activity 1

  // 4 Activity 2

  // 6 OutboundflowImpl
  public static class OutboundflowImpl implements Outboundflow {
    private String message;

    @Override
    public String getSomething(String name) {

      Workflow.await(() -> message != null);

      return "getSomething";
    }

    @Override
    public void getSignal(String message) {
      this.message = message;
      System.out.println("SomeSignal" + message);
    }
  }

  public static void main(String[] args) throws InterruptedException {
    WorkflowServiceStubs service = WorkflowServiceStubs.newInstance();
    WorkflowClient client = WorkflowClient.newInstance(service);

    WorkerFactory factory = WorkerFactory.newInstance(client);
    Worker worker = factory.newWorker(TASK_QUEUE);

    worker.registerWorkflowImplementationTypes(OutboundflowImpl.class);

    factory.start();

    Outboundflow workflowOut =
        client.newWorkflowStub(
            Outboundflow.class,
            WorkflowOptions.newBuilder()
                .setWorkflowId(WORKFLOW_ID_OUT)
                .setTaskQueue(TASK_QUEUE)
                .build());

    workflowOut.getSomething("Somethind");
  }
}
  1. This is the second workflow which is sending the signal to the first one .

public class InboundWorkflowCommunication {
  static final String IN_TEST_QUEUE = "INBOUND_QUEUE";

  static final String TASK_QUEUE = "TASK_QUEUE_IN";

  static final String WORKFLOW_ID_IN = "WORKFLOW_ID_IN4";
  static final String WORKFLOW_ID_OUT = "WORKFLOW_ID_OUT4";

  // 1 workflow 1
  @WorkflowInterface
  public interface Inboundflow {
    @WorkflowMethod
    String getAnything(String name);
  }

  // 3 Activity 1

  // 4 Activity 2

  // 5 InboundflowImpl
  public static class InboundflowImpl implements Inboundflow {

    @Override
    public String getAnything(String name) {
      OutboundWorkflowCommunication.Outboundflow outboundflow =
          Workflow.newExternalWorkflowStub(
              OutboundWorkflowCommunication.Outboundflow.class, WORKFLOW_ID_OUT);
      outboundflow.getSignal("Happy");
      return "getAnything";
    }
  }

  public static void main(String[] args) throws InterruptedException {
    WorkflowServiceStubs service = WorkflowServiceStubs.newInstance();
    WorkflowClient client = WorkflowClient.newInstance(service);

    WorkerFactory factory = WorkerFactory.newInstance(client);
    Worker worker = factory.newWorker(TASK_QUEUE);

    worker.registerWorkflowImplementationTypes(InboundflowImpl.class);

    factory.start();

    Inboundflow workflowIn =
        client.newWorkflowStub(
            Inboundflow.class,
            WorkflowOptions.newBuilder()
                .setWorkflowId(WORKFLOW_ID_IN)
                .setTaskQueue(TASK_QUEUE)
                .build());

    workflowIn.getAnything("Anything");
  }
}
  1. I am writing an integration test case for the above two. I am using springboot + temporal SDK.
    Now the problem is the first workflow is stuck as it is not receiving a signal.

  2. I have tried to find the workflowId and send the signal but I am getting the error.

What does your test look like?
Here is a test that uses your provided workflow code you can cut/paste and run locally:

public class FlowTest {
  private static String outboundFlowId = "OutboundFlowWorkflow";
  private static String inboundFlowId = "InboundFlowWorkflow";

  @Rule
  public TestWorkflowRule testWorkflowRule =
      TestWorkflowRule.newBuilder()
          .setWorkflowTypes(InboundFlowImpl.class, OutboundFlowImpl.class)
          .build();

  @Test
  public void testUserWorkflow() {
    OutboundFlow outboundFlow =
        testWorkflowRule
            .getWorkflowClient()
            .newWorkflowStub(
                OutboundFlow.class,
                WorkflowOptions.newBuilder()
                    .setTaskQueue(testWorkflowRule.getTaskQueue())
                    .setWorkflowId(outboundFlowId)
                    .build());

    InboundFlow inboundFlow =
        testWorkflowRule
            .getWorkflowClient()
            .newWorkflowStub(
                InboundFlow.class,
                WorkflowOptions.newBuilder()
                    .setTaskQueue(testWorkflowRule.getTaskQueue())
                    .setWorkflowId(inboundFlowId)
                    .build());

    WorkflowExecution inboundFlowExec =
        WorkflowClient.start(inboundFlow::getAnything, "Something...");
    WorkflowExecution outboundFlowExec =
        WorkflowClient.start(outboundFlow::getSomething, "Something else ...");

    String outboundResult = WorkflowStub.fromTyped(outboundFlow).getResult(String.class);
    String inboundResult = WorkflowStub.fromTyped(inboundFlow).getResult(String.class);
    assertEquals("getAnything", inboundResult);
    assertEquals("getSomething", outboundResult);

    assertCompleted(inboundFlowExec);
    assertCompleted(outboundFlowExec);
  }

  @WorkflowInterface
  public interface OutboundFlow {
    @WorkflowMethod
    String getSomething(String name);

    @SignalMethod
    void getSignal(String message);
  }

  public static class OutboundFlowImpl implements OutboundFlow {
    private String message;

    @Override
    public String getSomething(String name) {
      Workflow.await(() -> message != null);

      return "getSomething";
    }

    @Override
    public void getSignal(String message) {
      this.message = message;
    }
  }

  @WorkflowInterface
  public interface InboundFlow {
    @WorkflowMethod
    String getAnything(String name);
  }

  public static class InboundFlowImpl implements InboundFlow {
    @Override
    public String getAnything(String name) {
      OutboundFlow outboundFlowWorkflow =
          Workflow.newExternalWorkflowStub(OutboundFlow.class, outboundFlowId);
      outboundFlowWorkflow.getSignal("Happy");
      return "getAnything";
    }
  }

  private void assertCompleted(WorkflowExecution execution) {
    DescribeWorkflowExecutionResponse resp =
        testWorkflowRule
            .getWorkflowClient()
            .getWorkflowServiceStubs()
            .blockingStub()
            .describeWorkflowExecution(
                DescribeWorkflowExecutionRequest.newBuilder()
                    .setNamespace(testWorkflowRule.getTestEnvironment().getNamespace())
                    .setExecution(execution)
                    .build());

    assertEquals(
        WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED,
        resp.getWorkflowExecutionInfo().getStatus());
  }
}
1 Like