Problem
new EnqueueOptions(workflowName, queue) (and className = null on the three-/four-argument constructors) enqueues a workflow with class_name = NULL. That's intended for targets that look workflows up by name alone, such as Python. But when a Java executor dequeues such a row, it fails with a NullPointerException instead of reporting that no registered workflow matches.
DBOSExecutor.executeWorkflowById builds the lookup key from the stored row:
var wfName =
RegisteredWorkflow.fullyQualifiedName(
status.workflowName(), status.className(), status.instanceName());
and RegisteredWorkflow.fullyQualifiedName starts with Objects.requireNonNull(className, "className cannot be null"), so it throws before the DBOSWorkflowFunctionNotFoundException path below it is reached.
QueueService catches the exception and logs "Error starting workflow …", so from reading the code the workflow is left claimed and PENDING by that executor. I haven't reproduced this end to end.
ClientTest.clientEnqueueNullClassName covers enqueuing with a null class name, but it pauses the queue service and only checks the stored row. Nothing covers a Java executor dequeuing that row.
Expected
A class-less row that reaches a Java executor fails the same way as any other unregistered workflow (DBOSWorkflowFunctionNotFoundException), with an error that says the class name is missing, rather than an NPE. Java workflows are always keyed by class, so there's no by-name fallback to add; a null class name can never match.
Suggested fix
- Handle a null
className in executeWorkflowById (and any other path that builds fullyQualifiedName from a stored row, e.g. recovery and fork) as "no matching workflow".
- Add a test that enqueues with no class name, lets the queue run, and checks the outcome.
- Javadoc on the
EnqueueOptions constructors: say that the class name is required to target a Java workflow, and omitting it is only for workflows not registered on a class (such as Python functions).
The Java docs used to claim that "DBOS searches all registered classes" when the class name is omitted; that's being corrected in dbos-inc/dbos-docs#626.
Problem
new EnqueueOptions(workflowName, queue)(andclassName = nullon the three-/four-argument constructors) enqueues a workflow withclass_name = NULL. That's intended for targets that look workflows up by name alone, such as Python. But when a Java executor dequeues such a row, it fails with aNullPointerExceptioninstead of reporting that no registered workflow matches.DBOSExecutor.executeWorkflowByIdbuilds the lookup key from the stored row:and
RegisteredWorkflow.fullyQualifiedNamestarts withObjects.requireNonNull(className, "className cannot be null"), so it throws before theDBOSWorkflowFunctionNotFoundExceptionpath below it is reached.QueueServicecatches the exception and logs "Error starting workflow …", so from reading the code the workflow is left claimed andPENDINGby that executor. I haven't reproduced this end to end.ClientTest.clientEnqueueNullClassNamecovers enqueuing with a null class name, but it pauses the queue service and only checks the stored row. Nothing covers a Java executor dequeuing that row.Expected
A class-less row that reaches a Java executor fails the same way as any other unregistered workflow (
DBOSWorkflowFunctionNotFoundException), with an error that says the class name is missing, rather than an NPE. Java workflows are always keyed by class, so there's no by-name fallback to add; a null class name can never match.Suggested fix
classNameinexecuteWorkflowById(and any other path that buildsfullyQualifiedNamefrom a stored row, e.g. recovery and fork) as "no matching workflow".EnqueueOptionsconstructors: say that the class name is required to target a Java workflow, and omitting it is only for workflows not registered on a class (such as Python functions).The Java docs used to claim that "DBOS searches all registered classes" when the class name is omitted; that's being corrected in dbos-inc/dbos-docs#626.