从CordaService调用serviceHub.startFlow与Flow调用子流的差异及报错咨询
Corda流调用的两种方式差异及错误排查
核心差异点
线程与执行上下文
- Subflow调用:和父流共享同一个Flow协程执行上下文,包括事务上下文、Corda专用的协程调度器,挂起逻辑完全融入父流的协程生命周期,无需额外处理上下文传递。
- CordaService调用:通过
serviceHub.startFlow启动的是独立Flow实例,运行在单独的协程中;CordaService本身是单例服务,运行在普通线程池,不会自动为启动的Flow注入Flow专属的事务上下文。
挂起机制约束
- Subflow:父流的
@Suspendable注解会为整个调用链提供合法的协程上下文,即使子流的部分方法未标注注解,也可能被父流的上下文兜底,不会触发上下文缺失错误。 - CordaService启动的流:必须严格遵守Corda的协程规则,所有挂起方法(包括流入口的
call()方法)都必须标注@Suspendable,否则Corda无法为其创建事务上下文,直接抛出异常。
事务上下文传递
- Subflow:自动继承父流的事务上下文,流内的操作(比如创建、签署事务)能直接复用父流的上下文信息。
- CordaService:启动的流没有现成的事务上下文可继承,必须依赖
@Suspendable注解让Corda的协程框架初始化并维护事务上下文。
你的错误原因及解决办法
错误根源
你调用的目标流存在未标注@Suspendable的挂起方法——要么是流的call()方法没加注解,要么是流内部调用的自定义挂起方法(比如封装了send()/receive()/subFlow()的方法)遗漏了注解。Subflow调用时因为父流的上下文兜底,没触发检查,但CordaService启动独立流时,Corda会严格校验协程上下文,因此抛出Transaction context is missing异常。
解决方案
- 检查目标流的
call()方法,确保顶部标注@Suspendable注解:@Suspendable override fun call(): YourReturnType { // 流逻辑 } - 遍历流内所有自定义方法,只要方法内部调用了Corda的挂起API(比如
subFlow()、send()、serviceHub.vault.queryBy()),就必须给该方法加上@Suspendable注解。 - 若在CordaService中启动流时需要指定协程上下文,可绑定Corda的应用协程上下文:
不过最核心的还是补全所有必要的val appCoroutineContext = serviceHub.getAppContext().coroutineContext serviceHub.startFlow(::YourTargetFlow, params).execute(appCoroutineContext)@Suspendable注解。
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

