通过Spring集成实现MongoDB入站流程

时间:2018-08-03 15:43:15

标签: java spring-integration spring-integration-dsl

我们将拥有一个包含多个工作单元的Mongo集合。我的想法是该文档将具有一个带有四个选项的状态字段:未处理,处理,完成,失败。 Spring Integration将配置为从该数据库读取并处理存储在该数据库中的消息。

将根据值UNPROCESSED从集合中读取入站Mongo DSL流:

MongoDbMessageSource messageSource = new MongoDbMessageSource(mongo, new LiteralExpression("{'status' : 'UNPROCESSED'}"));
return IntegrationFlows.from(messageSource)...

这是问题所在:如果我有几台工作机从同一数据库中读取数据,我想阻止它们在相同行的未处理数据上进行操作,因为我的轮询器将保守值用于maxMessagesPerPoll或消息处理需要一会儿。

似乎合适的场所是使用TransactionSynchronizationFactory定义 ProcessBeforeCommit 阶段以将状态更新为“正在处理”,以及 ProcessAfterCommit 阶段以更新状态。完成或失败。但是,在查看轮询器和TransactionManagers的API时,添加此功能的机制尚不清楚。 XML中有一些示例,但是使用DSL我看不到任何示例。

我还想确保 ProcessBeforeCommit 在读取数据库时发生,而不是在处理之后发生……是吗?另外,如果这不是设计从Mongo集合中读取的解决方案的最佳方法,请随时提出更好的体系结构。

1 个答案:

答案 0 :(得分:1)

否,ProcessBeforeCommitProcessAfterCommit是非常接近的回调。它们肯定会在您的过程结束时发生。让我们考虑一下您有一种方法:

@Transactional
void foo() {}

当您调用这样的方法时,事务将在输入方法主体之前 开始。 当我们在方法主体执行后退出时,将执行 beforeCommit 回调。它可能会失败,因为在我们的过程中可能会丢失外部连接(DB?)。并且只有在可以的情况下,我们才能继续进行afterCommit

您可以通过AbstractMessageSourceAdvice实现https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-channels-section.html#conditional-pollers来完成您的要求。因此,在afterReceive()实现中,您可以将文档更新为PROCESSING,甚至决定返回null而不是消息:仅仅是因为它在数据库中的状态已经为{{1} }。可以将这样的PROCESSING注入Advice中:

PollerSpec

/** * Specify AOP {@link Advice}s for the {@code pollingTask}. * @param advice the {@link Advice}s to use. * @return the spec. */ public PollerSpec advice(Advice... advice) { DONE实际上可以通过将FAILED应用于TransactionSynchronizationFactoryBean来实现:

PollerSpec