Skip to content

Conversation

treblereel
Copy link
Collaborator

@treblereel treblereel commented Oct 22, 2025

Fix #897

This change introduces execution support for sub-workflows within the main workflow definition.
It allows a workflow to invoke another workflow declaratively via the RunTask construct

@treblereel treblereel requested a review from fjtirado as a code owner October 22, 2025 20:35
@treblereel treblereel self-assigned this Oct 22, 2025
@treblereel treblereel added the java Pull requests that update java code label Oct 22, 2025
@mcruzdev
Copy link
Contributor

Great @treblereel I was working on RunTask.shell support #892, I will wait this pull request to get your changes.

@ricardozanini
Copy link
Member

@treblereel can you please update the description and link the issue?

protected CompletableFuture<WorkflowModel> internalExecute(
WorkflowContext workflowContext, TaskContext taskContext) {
if (taskContext.task() != null && taskContext.task() instanceof RunTask runTask) {
RunWorkflow runWorkflow = runTask.getRun().getRunWorkflow();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be null since getRun() will have scripts, shell, container:

    private RunTaskConfiguration value;
    private RunContainer runContainer;
    private RunScript runScript;
    private RunShell runShell;
    private RunWorkflow runWorkflow;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ricardozanini I agree this could be revisited later, but for now, the scope of this executor is limited to run.workflow Once additional Run* types are introduced, we can generalize the logic and handle nulls consistently across all cases

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be done first, not later.

Copy link
Collaborator

@fjtirado fjtirado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think RunTaskExecutor should mimic CallTaskExecutor.

so rather than directly instantiating RunWorkflowExceutor, load the four different executor using serviceloader.

The reason is that the other run task will require additional dependencies and should be located in different modules (like HTTP or OpenAPI)

So, even if running workflow does not need additional dependencies, it should be loaded through serivce loading mechanism

Comment on lines 70 to 87
SubflowConfiguration subflowConfiguration = runWorkflow.getWorkflow();
String name = subflowConfiguration.getName();
String version = subflowConfiguration.getVersion();
String namespace = subflowConfiguration.getNamespace();
for (Map.Entry<WorkflowDefinitionId, WorkflowDefinition> kv :
application.workflowDefinitions().entrySet()) {
WorkflowDefinitionId workflowDefinitionId = kv.getKey();
if (workflowDefinitionId.name().equals(name)
&& workflowDefinitionId.namespace().equals(namespace)
&& workflowDefinitionId.version().equals(version)) {
WorkflowDefinition workflowDefinition = kv.getValue();
WorkflowApplication workflowApplication = workflowDefinition.application();
return workflowApplication
.workflowDefinition(workflowDefinition.workflow())
.instance(taskContext.input().asJavaObject())
.start();
}
}
Copy link
Collaborator

@fjtirado fjtirado Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorkflowDefinition identification does not need to be done every time the workflow is executed, most of this code should be executed just once.

Comment on lines 82 to 84
return workflowApplication
.workflowDefinition(workflowDefinition.workflow())
.instance(taskContext.input().asJavaObject())
Copy link
Collaborator

@fjtirado fjtirado Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you already have the workflowDefinition, you do not need to retreive it again from the appliaction.
Also, you can create a WorkflowDefinitionId is a record, the proper way to do this should be

WorkflowDefinition workflowDefinition = application.workflowDefinitions().get(new WorkflowDefinitionId(name, namespace.version));
if (workflowDefinition != null) {

                 return workflowDefinition.instance(taskContext.input()).start();
} else {
   // throw exception indicating the workflow is not defined
}

Also, you do not need to call asJavaObject(), instance should accept a WorkflowModel as per https://github.com/serverlessworkflow/sdk-java/blob/main/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowModelFactory.java#L72-L74

Copy link
Collaborator

@fjtirado fjtirado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to refactor the PR once I have fixed #899

@fjtirado
Copy link
Collaborator

@treblereel I have merged #900, please rebase and continue from there, thanks

@fjtirado fjtirado self-requested a review October 23, 2025 10:20
Signed-off-by: Dmitrii Tikhomirov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

java Pull requests that update java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement support for sub-workflow execution

4 participants