How to have Activity options configurable?

Hi team, i’m new to Temporal. Im using Temporal with my Spring boot project
with gradle implementation group: 'io.temporal', name: 'temporal-spring-boot-starter-alpha', version:1.23.2 and Java 11

Here my use case is to have activity options like startToClose, Heartbeat, and MaxRetryAttempts as configurable. Currently for me having it as part of constructor works at run time

public UserCreateWorkflowImpl(@Value("${temporal.user-create.start-to-close-timeout:30m}") Duration stc,
                                   @Value("${temporal.user-create.heartbeat:30s}") Duration heartBeat,
                                   @Value("${temporal.user-create.retry.initial-interval:2m}") Duration initialInterval,
                                   @Value("${temporal.user-create.retry.backoff-coefficient:2}") int backoffCoefficient,
                                   @Value("${temporal.user-create.retry.max-interval:1h}") Duration maxInterval

    ) {
        userCreateActivity = Workflow.newActivityStub(UserSessionActivity.class, ActivityOptions.newBuilder()
                                                                                 .setScheduleToCloseTimeout(stc)
                                                                                 .setHeartbeatTimeout(heartBeat)
                                                                                 .setRetryOptions(RetryOptions.newBuilder()
                                                                                                              .setInitialInterval(initialInterval)
                                                                                                              .setBackoffCoefficient(backoffCoefficient)
                                                                                                              .setMaximumInterval(maxInterval)
                                                                                                              .build())
                                                                                 .build());
    }

But im not able to write unit test for these (Junit5).

I also have gone through other community post similar to this, and there i got to know we should use this way.

So can anyone pls clarify

  1. How can I make these options configurable without breaking
  2. How to write UTs for these
  3. How the code will break in this case if I write in this way

community post i referred

temporal-spring-boot-starter-alpha

would consider updating the sdk version, just note the “alpha” was dropped since 1.24.0 sdk release.

Currently for me having it as part of constructor works at run time

interested to know how this works, is your workflow impl a component?
instead of passing these options in constructor would look into

  1. injecting them in local activity and have local activity return them as result
  2. have your workflow impl implement ApplicationContextAware interface which would allow you to get hold of beans from application context

(would probably go with option 1 if possible)

But im not able to write unit test for these (Junit5).

Temporal spring boot starter does have support for SpringBootTest, see sdk-java/temporal-spring-boot-autoconfigure at master · temporalio/sdk-java · GitHub

1 Like

Thanks for the reply @tihomir ,

  1. sure will check for the update
  2. Its not a component, but I will check and update here
    2.a I will try the option 1, just to be more clear here you mention local activity will be the Normal ActivityImpl returning this configuration right ?

something like this

workflowImplMethod(){
 ActivityOptions configActivity = config.getConfigs()
  // build new stub with the config passed
 stub.activity1();
}

something like this

not really, so your workflow impl would just execute a local activity, something like:

FetchOptionsActivity fetchOptionsActivity =
        Workflow.newLocalActivityStub(
            FetchOptionsActivity.class,
            LocalActivityOptions.newBuilder()
                .setStartToCloseTimeout(Duration.ofSeconds(2))
                .build());
// ...
MyActivityOptions myActivityOptions = fetchOptionsActivity.getOptions();
// use myActivityOptions now to create activity stubs

and this local activity can be a Component that can return beans, something like:

@Component
@ActivityImpl(taskQueues = "myTaskQueue") // note for local activity this has to be same 
//task queue as what you define for you workflow impls  as local activities are executed
// as part of your workflow task
public class FetchOptionsActivityImpl implements FetchOptionsActivity {
   
   @Autowired MyActivityOptions options;

  @Override
  public MyActivityOptions getOptions() {
    return options;
  }
}
1 Like

Hey Thanks @tihomir , the solution suggested works fine for my use case.

But just out of curiosity. I have a workflow method createUser(Params params),

Do you see any drawback or bad practice, if I sent this configuration as part of the method parameter replacing the local activity call

createUser(Params params, Config config)

If you are ok with maintaining activity options on each client that can start workflow executions, passing them in as workflow input is imo fine

1 Like