Testing Framework for Java SDK?

Have you had a chance to take a look?

Thanks,
Derek

The activity is performing as designed. It retries the unexpected exception:

08:46:31.029 [Activity Executor taskQueue="SampleActivities1", namespace="default": 2] WARN  i.t.i.sync.POJOActivityTaskHandler - Activity failure. ActivityId=c9da829f-c8c7-3143-8887-1df4ff816586, activityType=SampleActivities1GetInfo, attempt=4690
java.lang.IllegalArgumentException: null
	at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

Note the attempt field that keeps increasing. What exactly are you trying to test? In real production code the same will happen. The exception is going to be retried until the problem is fixed. If you don’t want it to be retried change the retry policy to specify that this exception shouldn’t be retried.

Two things i’m expecting or hoping for

  1. In the workflow code base, I’m expecting that when the promise gets executed it will fail and throw an exception or somehow I can get the error, so that I can cancel the other activities in the workflow. What is the proper way to do this. I did take a look at the cancellation example and expected to get the same results.
  public void execute(Map<String, String> bindings) {
    // In the parallel block, we want to execute all of them in parallel and wait for all of them.
    // if one activity fails then we want to cancel all the rest of them as well.
    List<Promise<Void>> results = new ArrayList<>(bindings.size());
    CancellationScope scope =
        Workflow.newCancellationScope(
            () -> {
              for (Statement statement : branches) {
                results.add(Async.function(statement::execute, bindings));
              }
            });
    // As code inside the scope is non blocking the run doesn't block.
    scope.run();

    try {
      Promise.anyOf(results).get();

      // If one activity fails then all the rest will fail
      for (Promise<Void> p : results) {
        p.get();
      }
    } catch (RuntimeException ex) {
      // Cancel uncompleted activities
      scope.cancel();
      System.out.println("One of the Activities failed.  Canceling the rest." + ex.getMessage());
      throw ex;
    }
  }
  1. I thought it does not do retries by default if no retryPolicy is specified, but I guess I was wrong… https://github.com/darewreck54/temporal-java-samples/blob/test_issue/src/main/java/io/temporal/samples/dsl/models/ActivityInvocation.java#L35. I’ve also tries to use the api setDoNotRetry() but I guess I was using that incorrectly after seeing the implementation. The only way I could get it to work is if i used setMaximumAttempts and set it to 1. I notice that you need to set this to 1 at least in unit test or a timeout, or the unit test would go on forever.
  1. I believe Promise.anyOf does exactly what you expect. The problem is that activity is not failed from the workflow point of view.
  2. Ignoring doNotRetry is a bug in the unit testing framework. Working on the fix.
  1. The bug was fixed by https://github.com/temporalio/sdk-java/pull/223 and is not present in the latest SDK releases. Please upgrade your SDK version.

What is the proper way to handle exceptions thrown by the activity? Do we need to convert it to a workflow exception for it to be recognized as a failure from
The perspective of the workflow?

An exception from an activity is retried unless it is specified in doNotRetry part of the retry policy. If specified it is delivered to workflow in the form of ApplicationFailure exception. The ApplicationFailure contains the string name of the java exception in its type property and the message in its message property. An activity failure is always delivered as ActivityFailure exception with the ApplicationFailure as a cause.

If you need to pass additional information in the ApplicationFailure you can create it directly in an activity or workflow using ApplicationFailure.newFailure static method. If you want to mark a failure as non-retryable from an activity without explicitly specifying it in the retry policy create it using ApplicationFailure.newNonRetryableFailure.