Throwing exception while registering activity in worker

  public static class SampleWorkflowImpl implements SampleWorkflow {

    private final ActivityStub activities =
        Workflow.newUntypedActivityStub(
            ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(30)).build());

    @Override
    public String sampleMethod() {
      EncodedValues encodedValues = new EncodedValues("val1", "val2");
      return (String) activities.execute("Execute", Object.class, encodedValues);
    }
  }

  static class TestDynamicActivityImpl implements DynamicActivity {
    @Override
    public Object execute(EncodedValues args) {
      System.out.println("execute");
      return "dynamic activity executed";
    }
  }

Here I directly implemented the DynamicActivity interface, overridden the execute method. And created stub using Workflow.newUntypedActivityStub and called the execute method activities.execute("Execute", Object.class, encodedValues);

Is this correct?

When invoking an activity don’t use EncodedValues and specify the concrete type that the activity returns.

     activities.execute("ActivityType1", String.class, "val1", "val2");

In the dynamic activity implementation:

TestDynamicActivityImpl implements DynamicActivity {
    @Override
    public Object execute(EncodedValues args) {
      String activityType = Activity.getExecutionContext().getInfo().getActivityType();
      System.out.println("execute " + activityType);
      String arg1 = args.get(0, String.class);
      String arg2 = args.get(1, String.class);
      return "dynamic activity executed with args " + arg1 + " " + arg2;
    }
  }

1 Like

Here you are passing activityName as ActivityType1, How it is executing the execute method? we should pass it as Execute, right? I tried but it is working.

DynamicActivity by definition can be used to implement any activity type. It is done by always invoking its execute method.

If you explained you use case I would be able to give you more detailed recommendation.

My use case like this,

@ActivityInterface
public interface TemporalTask{
    Object executeTask(Object obj);
}

Our framework just has this interface alone.

User needs to implement their task needs to be completed.
Like this,

public class Task1 implements TemporalTask{
    @Override
    Object executeTask(Object obj){
           ....
           ....

    }
}

public class Task2 implements TemporalTask{
        @Override
        Object executeTask(Object obj){
               ....
               ....

        }
    }

I will be having a workflow code that will receive a list of TemporalTask objects as input, and it will iterate all the TemporalTask from the list and execute its task by calling exeuteTask method.

I have a flag to differentiate whether this needs to be called in sequential or parallel.
Here each task will have its own timeout properties and retry options

I am trying to achieve this.

Kindly let me know you need any clarifications. Thanks in advance!!

I would separate the user task interface and the activity interface in this case. Something like:

public interface TemporalTask{
    Object executeTask(Object obj);
}

public class Task1 implements TemporalTask{
    @Override
    Object executeTask(Object obj){
           ....
           ....

    }
}

public class Task2 implements TemporalTask{
        @Override
        Object executeTask(Object obj){
               ....
               ....

        }
    }

And the activity interface and implementation become:

@ActivityInterface
public interface TaskExecutor{
    Object executeTask(String taskType, Object obj);
}

public class TaskExecutorImpl implements TaskExecutor{
    Map<String, TemporalTask> tasks = ...

        @Override
    Object executeTask(String taskType, Object obj) {
              return  tasks.get(taskType).executeTask(obj);
        }
    }

And from the workflow you invoke it as:

private final TaskExecutor taskExecutor =
    Workflow.newActivityStub(
        TaskExecutor.class,
        ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(40)).build());
...
Object result = taskExecutor.executeTask(taskName, input);

Note that the above code is not going to work out of the box as the default DataConverter doesn’t support deserialization of arguments of polymorphic types. So you either need to implement the custom DataConverter that works with Java polymorphism or use concrete types in the activity signature.

1 Like

Thank you so much @maxim. Let me try this.
once again thanks for your kind response

1 Like

Hi,

I’m trying to get my head around Dynamic Activity - and I’ve seen the examples etc - but I still am unsure as to what significance the activityName has - can you please confirm?

I could rewrite above to:

activities.execute("Bob", String.class, "val1", "val2");

and the result would be exactly the same?

Thanks,
Jay.

and the result would be exactly the same?

I’m not sure what you mean by exactly the same. It invokes a completely different activity by type “Bob” instead of activity of type “ActivityType1”.

Hi Maxim,

Thanks for the quick reply. In which case, my confusion remains - for a Dynamic Activity, Where is “ActivityType1” defined?

In the example here: samples-java/HelloDynamic.java at main · temporalio/samples-java · GitHub

String greetingResult = activity.execute("DynamicACT", String.class, greeting, name, type);

is called from DynamicGreetingWorkflowImpl, but I don’t see where “DynamicACT” is defined.

Regards,
Jay.

A DynamicActivity implements all activity types that hit the worker.