【发布时间】:2014-11-01 02:39:43
【问题描述】:
我有如下要求:
- 接受包含 XML 的 HTTP POST 请求到某个 URL。
- 执行先决条件操作,例如将请求 XML 保存到文件中。
- 验证传入的 XML 是否匹配相应的架构。
- 如果架构验证失败,则使用 HTTP 400 响应代码同步响应。
- 如果架构验证通过,则使用 HTTP 200 响应代码同步响应。
- 传递 XML 消息以进行进一步处理。
- 此进一步处理完成后,使用 HTTP 200 响应代码异步响应调用方。
这是我目前配置路由的方式:
onException(IOException.class)
.log(LoggingLevel.INFO, "Schema validation error on incoming message: ${id}")
.handled(true)
.maximumRedeliveries(0)
.process(schemaValidationErrorProcessor);
from("restlet:http://localhost:" + portNum + "/api/XX/XXX?restletMethod=POST")
.log(LoggingLevel.INFO, "Received message")
.convertBodyTo(String.class)
.multicast()
.parallelProcessing()
.to(SAVE_REQUEST_TO_FILE_QUEUE, PROCESS_PROVISIONING_REQUEST_QUEUE);
from(SAVE_REQUEST_TO_FILE_QUEUE)
.log(LoggingLevel.INFO, "Storing message: ${id}")
.to("file://" + requestLogFolder);
from(PROCESS_PROVISIONING_REQUEST_QUEUE)
.log(LoggingLevel.INFO, "Processing provisioning request: ${id}")
.process(requestGate)
.choice()
.when(header(SYSTEM_STATUS_HEADER).isEqualTo(true))
.unmarshal(xmlParser)
.inOnly("bean:requestHandler?method=handle")
.when(header(SYSTEM_STATUS_HEADER).isEqualTo(false))
.log(LoggingLevel.INFO, "Intentially dropping message")
.endChoice();
模式验证部分是通过 .unmarshal(xmlParser) 行实现的(我在其他地方配置了一个 JaxbDataFormat 对象,其中设置了模式)。当模式验证失败时,会引发 IOException,这由我的 schemaValidationErrorProcessor 处理,它将 HTTP 400 添加到响应中。
一切正常。
我遇到的问题是将 XML 消息传递给进一步处理。基本上,我需要异步完成此操作,因为当模式验证通过时,我需要以 200 响应同步响应。我需要做的处理在 .inOnly("bean:requestHandler?method=handle") 行中。
我天真地认为将我的 bean 的路由设置为 inOnly 会将其设置为异步的,并且主路由不会等待响应。但是,当 requestHandler.handle 方法抛出异常时,情况并非如此,它会被抛回 REST 端点的调用者。我不希望这种情况发生,因为我希望所有这些处理都在“后台”完成,因为消费者已经收到了 200 响应。
所以,我的问题是,我将如何实现这种行为?我曾考虑过使用队列等,但如果可能的话,最好避免使用此类组件。
【问题讨论】:
-
您是说您响应了两次,一次是同步的,一次是异步的,这充其量是奇怪的,在最坏的情况下是不可能的。您可以做的是使用 Websockets 之类的东西或 Atmosphere 之类的抽象来继续将消息推送到客户端,但是所有消息都是异步的(这对您来说可能是一件好事)。要在 Camel 中获得异步行为,请参阅:camel.apache.org/async.html
-
它们是我们的业务需求。客户想要一个同步响应来表明我们已成功收到他们的消息,并且他们想要在我们成功处理消息后进行异步回调。
标签: apache-camel