
本文介绍在基于 HAPI HL7v2 库构建的医疗接口中,如何正确生成符合规范的 NACK(Negative Acknowledgment)响应消息,以明确告知发送方消息已接收但内容校验失败。
本文介绍在基于 HAPI HL7v2 库构建的医疗接口中,如何正确生成符合规范的 NACK(Negative Acknowledgment)响应消息,以明确告知发送方消息已接收但内容校验失败。
在 HL7 v2 消息交互中,ACK 是标准确认响应,而当接收系统成功接收到消息但无法处理(如字段缺失、数据格式错误、业务规则不满足等)时,必须返回 NACK —— 即带有 AE(Application Error)确认码的 ACK 类型消息。HAPI HL7v2 并未提供独立的 generateNACK() 方法,而是通过 generateACK() 的重载方法实现这一语义。
正确生成 NACK 的方式
调用 Message.generateACK() 并传入两个关键参数:
- AcknowledgmentCode.AE:表示应用层错误(即 NACK 的核心标识);
- Exception 对象(可选但推荐):用于自动填充 ERR 段(Segment ERR),提供结构化错误详情(如错误位置、代码、描述)。
import ca.uhn.hl7v2.AcknowledgmentCode;
import ca.uhn.hl7v2.model.Message;
// 假设 msg 是已解析的入站消息(如 ADT_A01)
try {
// 校验逻辑失败示例
if (msg.getMSH().getSendingApplication().isEmpty()) {
throw new IllegalArgumentException("Missing Sending Application in MSH-3");
}
} catch (Exception ex) {
// 生成 NACK 响应
Message nack = msg.generateACK(AcknowledgmentCode.AE, ex);
// 发送 nack 至发送方(例如通过 TCPClient 或 MinLowerLayerProtocol)
sender.send(nack.encode());
}✅ 关键点说明:
- AcknowledgmentCode.AE 是 NACK 的强制性标识;若传入 AA(Application Accept)或 AR(Application Reject),则不属于标准 NACK。
- ERR 段是 HL7 v2 NACK 的重要组成部分(见 HL7 v2.7 § 2.16.3),它使接收方可定位错误字段(如 ERR-3 = 错误位置,ERR-5 = 错误 code)。HAPI 会自动根据 Exception 的堆栈和消息上下文填充该段——但需确保原始 msg 已完成解析且字段可访问。
- 若不传 Exception,ERR 段可能为空或仅含默认占位符,导致对方难以诊断问题,因此强烈建议始终传递有意义的异常。
注意事项与常见陷阱
- ❌ 不要手动修改 MSA-1 字段来“伪造” NACK:这违反协议一致性,且 ERR 段不会自动生成。
- ⚠️ generateACK() 返回的是全新消息对象(非原地修改),务必使用返回值发送,而非对原 msg 调用 encode()。
- ? 若发现生成的 NACK 缺失 ERR-3/ERR-4/ERR-5 字段(如 Stack Overflow 中提到的问题),请确认:
- 使用的 HAPI 版本 ≥ 2.3(旧版存在 ERR 初始化缺陷);
- Exception 实例包含足够上下文(推荐使用 HL7Exception 或其子类);
- 入站 msg 已成功解析(msg.parse() 成功),否则字段路径不可达。
总结
NACK 不是特殊消息类型,而是带 AE 码并含 ERR 段的 ACK。通过 msg.generateACK(AcknowledgmentCode.AE, exception) 即可合规、高效地实现。结合清晰的异常构造与版本验证,可确保 HIS 等上游系统获得可操作的错误反馈,大幅提升接口健壮性与运维效率。