跳到主要内容
← 返回博客

本文涉及的模块: Integration Flow Helper

SAP CPI 中的未知 header 和属性:在静默失败之前发现它们

为什么 SAP CPI 中拼错或缺失的 header 或 exchange property 不会报错就失败,常见原因有哪些,以及如何在设计时和运行时发现它们。

SAP CPI 中的未知 header 和属性:在静默失败之前发现它们

从未被设置的 header 不会让 SAP CPI iFlow 停下来。读取它的表达式返回空值,Router 条件变为 false,负载字段留空,消息照常继续。真正的错误(如果有的话)会在几个步骤之后或在接收系统中才出现。

本文解释为什么缺失的 header 和 exchange property 会静默失败、反复出现的原因,以及能比消息更早发现它们的检查方法。

为什么缺失的名称不会报错

Apache Camel 把不存在的 header 或属性当作空值,而不是错误。这对可选值来说很方便,但也正因如此,一个拼写错误可以在 iFlow 中潜伏好几个月。你看到的现象取决于读取该名称的位置:

  • 像 ${property.orderId} 这样的 Content Modifier 值会变成空字符串。
  • 像 ${header.orderType} = 'EXPRESS' 这样的 Router 或 Filter 条件求值为 false,消息于是走另一条路由,通常是默认路由。
  • 像 /orders/${property.orderId} 这样的接收方地址会调用 /orders/,接收系统返回的错误里根本不会提到缺失的属性。
  • 在 Groovy 脚本中,message.getHeader("orderId", String) 返回 null,脚本随后因空指针错误而失败,或者把文本 null 写进负载。

常见原因

  • 属性名拼写错误或大小写不对:exchange property 名称区分大小写,因此 orderID 和 orderId 是两个不同的属性。header 名称不区分大小写。
  • 多余的空格,例如 ${header.orderId }:带空格的名称是另一个名称。
  • 某个值只在 Router 的一条路由上设置,却在各路由汇合之后被读取。
  • 发送方发送了 header,但没有放行:HTTPS 发送方只会放行 iFlow 的 Runtime Configuration 中 Allowed Header(s) 所列的自定义 header。
  • 期望从另一个 iFlow 传来的属性:exchange property 不会随 ProcessDirect 调用传递,只有 header 会(参见 ProcessDirect 和 JMS 文章)。
  • header 行读取了同一个 Content Modifier 中设置的属性,而 Content Modifier 会先处理 header 表,再处理属性表。

让缺失的值明确地报错

对于流程离不开的值,请在需要它们的地方就报错,而不是三个步骤之后。在流程开头加一个简短的 Groovy 步骤就足够了:

import com.sap.gateway.ip.core.customdev.util.Message

def Message processData(Message message) {
    def orderId = message.getProperty("orderId")
    if (orderId == null || orderId.toString().trim().isEmpty()) {
        throw new IllegalStateException("Exchange property orderId is not set")
    }
    return message
}

这样,消息会以错误结束,并带有一句点名缺失属性的说明,可以在消息处理日志中看到。对于 Router 条件,请让默认路由承担明确的用途:如果不应出现没有匹配任何路由的情况,就以 Error End 事件结束它,而不是让消息沿着原本作为后备的路径继续前进。

测试时,请把 iFlow 的日志级别设为 Trace。Trace 会显示每个步骤中的 header 和 exchange property,让你准确看到某个值是在哪里消失的。

部署前的检查清单

  1. 列出 iFlow 读取的每个 header 和属性:在表达式、条件、适配器字段和脚本中。
  2. 为每一个找到设置它的步骤,到达读取位置的每一条路径都要检查。
  3. 比较确切的拼写,包括属性的大小写以及任何空格。
  4. 对于来自发送方的 header,确认它们已列在 Allowed Header(s) 中。
  5. 对于来自另一个 iFlow 的值,确认它们以 header 而不是属性的形式传递。

在大型 iFlow 上手动完成这项检查要花不少时间,这也是它最值得优先自动化的原因。

避免问题的命名习惯

  • 选定一种风格(例如 camelCase),并在整个 package 的所有 header 和属性中统一使用。
  • 把整个流程依赖的值集中在靠近开头的一个 Content Modifier 中设置,这样只需在一个地方查找。
  • 把 SAP_ 和 Camel 前缀留给 SAP 和 Apache Camel;为你自己的名称采用不同的形式。
  • 只在本 iFlow 内需要的值使用属性,只有需要离开本 iFlow 的值才使用 header。

关于 Camel Simple 表达式的文章解释了这份清单中每个名称背后的语法。

Kitegra 如何帮你

浏览器扩展 Kitegra 会在 SAP Integration Suite 设计器中执行这份检查清单。它的 Lint 面板会在你部署之前标出 iFlow 中没有任何地方设置的 header 和属性、未闭合的 ${,以及表达式中多余的空格。

当你输入 ${ 或 $ 时,它只提示 iFlow 中已设置的名称(包括在 Groovy 和 JavaScript 脚本中设置的名称),以及 SAP 和 Camel 的标准 header,因此从一开始就更不容易拼错。只在部分路径上设置的名称会标注为“仅在部分路径上设置”。它从不保存、部署或编辑 iFlow 的内容;只有在你点击四个指定操作之一时,tenant 才会发生变化,而且这些操作可以关闭。

如果某个值在运行时为空,逐步跟踪消息可以显示每个步骤之前的 header 和属性,而 iFlow 审查清单则涵盖了背后的设计错误。

没有 Kitegra 账户时,每个模块可用于 5 个 iFlow。Free 套餐涵盖 50 个,Starter 100 个,Pro 300 个;Business 不限。比较各套餐。

在下一个 iFlow 中试试

了解 Kitegra 在 SAP Integration Suite 设计器中能做什么,或在 Kitegra 的其他 Chrome 扩展旁查看它。

常见问题

为什么 header 缺失时 SAP CPI 不报错?

对于不存在的 header 或属性,Apache Camel 返回空值。问题只会在这个空值造成损害的地方显现,通常是几个步骤之后。

为什么我能看到 exchange property 已经设置,它却是 null?

请检查大小写:exchange property 名称区分大小写。还要确认设置它的步骤在消息实际经过的路径上执行了,并且这个值不是指望通过 ProcessDirect 调用传过来的。

为什么发送方发来的 header 没有到达我的 iFlow?

HTTPS 发送方只放行 iFlow 的 Runtime Configuration 中 Allowed Header(s) 所列的自定义 header。请把该 header 名称添加到那里。

如何查看每个步骤中的 header 和属性?

把 iFlow 的日志级别设为 Trace 并运行一条消息。监控中的 Trace 会显示每个步骤的 header 和 exchange property。

必需的值缺失时,如何让流程停止?

添加一个脚本步骤来检查该值,并抛出带有清晰消息的异常;或者把 Router 的默认分支指向 Error End 事件。

能在部署之前检查吗?

可以,方法是把 iFlow 读取的每个名称与它设置的名称进行比对。Kitegra 的 Lint 面板会在设计器中完成这项工作。

无需离开设计器即可处理 iFlow

将 Kitegra 添加到 Chrome 或 Microsoft Edge。免费开始,无需账户。