Hi,
I want to use multiple data converters for different workflows but i seem to come across an error where it cannot create the new workflow client
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘approvalWorkflowInteractorService’ defined in file [/home/anjula-paulus/workspace/endowus/endowus-workflow-engine/sg-endowus-workflow-engine/target/classes/com/endowus/workflow/engine/sg/approval/interactor/ApprovalWorkflowInteractorService.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name ‘approvalWorkflowClient’ defined in class path resource [com/endowus/workflow/engine/sg/approval/config/ApprovalsTemporalConfig.class]: Unsatisfied dependency expressed through method ‘approvalWorkflowClient’ parameter 0: Error creating bean with name ‘temporalWorkflowClient’ defined in class path resource [io/temporal/spring/boot/autoconfigure/RootNamespaceAutoConfiguration.class]: Unsatisfied dependency expressed through method ‘client’ parameter 0: Error creating bean with name ‘temporalClientTemplate’ defined in class path resource [io/temporal/spring/boot/autoconfigure/RootNamespaceAutoConfiguration.class]: Unsatisfied dependency expressed through method ‘clientTemplate’ parameter 0: Error creating bean with name ‘temporalRootNamespaceTemplate’ defined in class path resource [io/temporal/spring/boot/autoconfigure/RootNamespaceAutoConfiguration.class]: Failed to instantiate [io.temporal.spring.boot.autoconfigure.template.NamespaceTemplate]: Factory method ‘rootNamespaceTemplate’ threw exception with message: No qualifying bean of type ‘io.temporal.common.converter.DataConverter’ available: Several DataConverter beans found in the Spring context. Explicitly name ‘mainDataConverter’ the one bean that should be used by Temporal Spring Boot AutoConfiguration.
The springboot application used the temporal auto confirgure library as well.
The plan was to define muliple workflow clients and use teh @Qualifier annotation to pickup the respective client for the workflow.
Please help to resolve this matter.
Several DataConverter beans found in the Spring context. Explicitly name ‘mainDataConverter’ the one bean that should be used by Temporal Spring Boot AutoConfiguration.
If you have multiple data converter beans see here how to resolve ambiguity.
you should be able to then autowire them by name
@tihomir Do you have an example on how I could do this? I mean I have a workflowClient which i would like to override the Dataconverter?
I tried the approach you suggested but the activity tasks are completed succefully but the workflow task if failing due the proper converter not being used.
Any clue how i could resolve it?
Will create sample and share, would help if you show a bit of your code how you are creating multiple clients and registering converters so have better idea of what your setup looks like. From error shared looks like you are using default converter and your model object needs a no-arg default constructor or constructor (so seems you are not registering your custom one)
@tihomir
The mainDataConverter just would support normal java serde and other converter supports scala. This requirement is to support different workflows with different dtos in either scala or java. Not in mix.
The TemporalConfig
@Configuration
public class TemporalConfig {
@Bean("mainDataConverter") // This is the one Temporal will use by default
@Primary
public DataConverter mainDataConverter() {
return DefaultDataConverter.newDefaultInstance();
}
@Bean("scalaDataConverter")
public DataConverter scalaDataConverter() {
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new DefaultScalaModule())
.registerModule(new JavaTimeModule());
return DefaultDataConverter.newDefaultInstance()
.withPayloadConverterOverrides(new JacksonJsonPayloadConverter(objectMapper));
}
}
and then the ApprovalWorkflowInteractorService class
@Service
public class ApprovalWorkflowInteractorService {
private final WorkflowClient workflowClient;
public ApprovalWorkflowInteractorService(
WorkflowClient workflowClient,
DataConverter scalaDataConverter,
PersistenceService persistenceService
) {
WorkflowClientOptions existingOptions = workflowClient.getOptions();
WorkflowClientOptions newOptions = WorkflowClientOptions.newBuilder(existingOptions)
.setDataConverter(scalaDataConverter)
.build();
// Create new client with updated options
this.workflowClient = WorkflowClient.newInstance(
workflowClient.getWorkflowServiceStubs(),
newOptions
);
}
public CreateWorkflowResponse create(
final String taskType,
final CreateWorkflowRequest createWorkflowRequest
) {
UUID taskId = UUIDUtil.getRandomUUID();
String workflowId = UUID.randomUUID().toString();
WorkflowOptions.Builder workflowOptions = WorkflowOptions.newBuilder()
.setWorkflowId(workflowId);
workflowOptions.setTaskQueue("test");
TestOnceCreateWorkflow testOnceCreateWorkflow = workflowClient.newWorkflowStub(
TestOnceCreateWorkflow.class, workflowOptions.build()
);
try {
WorkflowClient.start(testOnceCreateWorkflow::create, taskTypeEnum,
TaskInfoDto.builder()
.taskId(taskId.toString())
.references(createWorkflowRequest.getReferences())
.payload(createWorkflowRequest.getPayload())
.build()
);
} catch (Exception e) {
throw new AppException("There is already a task workflow running for workflowId: {}");
}
return CreateWorkflowResponse.builder().taskId(taskId).build();
}
}
@tihomir Could you pls help on resolving this? I still couldnt get to separate the converters.
Yeah havent had time yet to look, will do today.
1 Like