-
Notifications
You must be signed in to change notification settings - Fork 13
Open
Description
Hi,
I'm hitting an issue with trying to use this when workflow impl classes are Spring proxied due to @Transactional on the methods in the class.
For example, a setup like this fails:
@Service
public class AccountSyncWorkflowImpl implements AccountSyncWorkflow {
private AccountSyncWorkflow proxy;
public void setProxy(AccountSyncWorkflow proxy) {
this.proxy = proxy;
}
@Override
@Workflow(name = "syncAccount")
public void syncAccount(UUID accountId) {
// workflow body...
}
@Transactional(readOnly = true)
public void loadAccount(UUID accountId) {
// db read
}
}
@Configuration
public class AccountSyncWorkflowConfig {
private final AccountSyncWorkflowImpl workflowImpl;
public AccountSyncWorkflowConfig(AccountSyncWorkflowImpl workflowImpl) {
this.workflowImpl = workflowImpl; // Spring-managed bean, proxied due to @Transactional
}
@Bean
@Primary
public AccountSyncWorkflow accountSyncWorkflow() {
var proxy = DBOS.registerWorkflows(AccountSyncWorkflow.class, workflowImpl);
workflowImpl.setProxy(proxy);
return proxy;
}
}
DBOS.startWorkflow(() -> accountSyncWorkflow.syncAccount(UUID.randomUUID()));Will error with:
java.lang.RuntimeException: Only @Workflow functions may be called from the startWorkflow lambda
at dev.dbos.transact.internal.DBOSInvocationHandler.invoke(DBOSInvocationHandler.java:60)
at jdk.proxy3/jdk.proxy3.$Proxy116.syncAccount(Unknown Source)
...
The issue is that in DBOSInvocationHandler.invoke, getAnnotation is called on the proxy which doesn't have the annotation.
dbos-transact-java/transact/src/main/java/dev/dbos/transact/internal/DBOSInvocationHandler.java
Lines 49 to 58 in 7b8ee81
| public Object invoke(Object proxy, Method method, Object[] args) throws Exception { | |
| var implMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes()); | |
| implMethod.setAccessible(true); | |
| var hook = hookHolder.get(); | |
| var wfTag = implMethod.getAnnotation(Workflow.class); | |
| if (wfTag != null) { | |
| return handleWorkflow(implMethod, args, wfTag, hook); | |
| } |
I think instead the real class should be resolved and the annotation info cached when the workflow is registered, then in invoke it uses this cache instead of doing reflection on every invocation.
Thank you
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels