【问题标题】:Passing validation exceptions from Camel to CXF SOAP service将验证异常从 Camel 传递到 CXF SOAP 服务
【发布时间】:2017-04-03 19:39:50
【问题描述】:

我有一个问题我已经有一段时间无法解决了,而且我是 apache camel 的新手,它没有帮助。

我的简单应用使用 CXF(使用码头作为 http 引擎)公开 SOAP Web 服务,然后使用骆驼将肥皂请求传递给 akka 演员。

我想在通往参与者的路上验证 SOAP 请求并检查它是否包含某些标头和内容值。我不想使用 CXF 拦截器。问题是,骆驼中发生的事情(异常,错误消息返回)不会传播到 cxf。我总是得到 SUCCESS 202 作为响应和有关日志中验证异常的信息。

这是我的简单应用:

class RequestActor extends Actor with WithLogger {
  def receive = {
    case CamelMessage(body: Request, headers) =>
      logger.info(s"Received Request $body [$headers]")
    case msg: CamelMessage =>
      logger.error(s"unknown message ${msg.body}")
  }
}

class CustomRouteBuilder(endpointUrl: String, serviceClassPath: String, system: ActorSystem)
  extends RouteBuilder {
  def configure {
    val requestActor = system.actorOf(Props[RequestActor])

    from(s"cxf:${endpointUrl}?serviceClass=${serviceClassPath}")
      .onException(classOf[PredicateValidationException])
        .handled(true)
        .process(new Processor {
        override def process(exchange: Exchange): Unit = {
          val message = MessageFactory.newInstance().createMessage();
          val envelope = message.getSOAPPart().getEnvelope();
          val body = message.getSOAPBody();
          val fault = body.addFault();
          fault.setFaultCode("Server");
          fault.setFaultString("Unexpected server error.");
          val detail = fault.addDetail();
          val entryName = envelope.createName("message");
          val entry = detail.addDetailEntry(entryName);
          entry.addTextNode("The server is not able to complete the request. Internal error.");

          log.info(s"Returning $message")
          exchange.getOut.setFault(true)
          exchange.getOut.setBody(message)
        }

        })
      .end()
      .validate(header("attribute").isEqualTo("for_sure_not_defined"))
      .to(genericActor)
  }
}

object Init extends App {

  implicit val system = ActorSystem("superman")
  val camel = CamelExtension(system)
  val camelContext = camel.context
  val producerTemplate = camel.template

  val endpointClassPath = classOf[Service].getName
  val endpointUrl = "http://localhost:1234/endpoint"

  camel.context.addRoutes(new CustomRouteBuilder(endpointUrl, endpointClassPath, system))

}

当我运行应用程序时,我看到来自 log.info(s"Returning $message") 的日志,所以我确定路由调用处理器,因此也没有调用 actor 行:

exchange.getOut.setFault(true)
exchange.getOut.setBody(message)

做他们的工作。但我的 SOAP 服务仍然返回 202 SUCCESS 而不是错误信息。

【问题讨论】:

    标签: scala apache-camel akka cxf


    【解决方案1】:

    我不确定您要查找的是什么,但我以不同方式处理了 CXF 端点的异常。我必须在 SOAPFault 中返回带有自定义详细信息的 HTTP-500(如验证错误消息等),所以...

    1. 保持异常未由 Camel 处理以将其传递给 CXF .onException(classOf[PredicateValidationException]).handled(false)

    2. 创建 org.apache.cxf.interceptor.Fault 对象,其中包含异常中所需的所有详细信息。 (不是 SOAP 错误)。它允许设置自定义细节元素、自定义故障代码元素、消息。

    3. 最终将 Exchange.EXCEPTION_CAUGHT 属性替换为 cxfFault exchange.setProperty(Exchange.EXCEPTION_CAUGHT, cxfFault)

    来自 CXF 端点的结果消息是一个 HTTP-500,正文中带有 SOAPFault,详细信息我在 cxfFault 中设置

    【讨论】:

    • 非常感谢。这不是我要问的,但你的方法更好。
    【解决方案2】:

    Camel 只查看交换的输入部分,但您正在修改输出部分。

    尝试改变

    exchange.getOut.setFault(true)
    exchange.getOut.setBody(message)
    

    exchange.getIn.setFault(true)
    exchange.getIn.setBody(message)
    

    【讨论】:

    • 不,还是一样。 Web 服务返回 202。
    • 我建议您首先尝试将正文设置为您的自定义错误,然后逐渐添加其他内容以查看您的消息有什么问题。
    猜你喜欢
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多