You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8 SOAP服务对接Delphi遇空指针,求完整报文获取方法

排查Java 8 SOAP服务与Delphi对接的空指针问题及报文捕获方案

一、捕获完整SOAP请求/响应报文

针对你使用的javax.jws.WebService(JAX-WS)栈,有两种可靠方式获取完整报文:

1. 开启JAX-WS内置日志

在JVM启动参数中添加以下配置,服务端会直接在日志/控制台输出包含HTTP头、SOAP信封的完整请求和响应:

-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
-Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true

2. 自定义SOAP拦截Handler

编写一个报文拦截处理器,精准捕获请求和响应内容:

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayOutputStream;
import java.util.Set;

public class SoapLoggingHandler implements SOAPHandler<SOAPMessageContext> {
    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean isOutbound = (Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
        try {
            SOAPMessage msg = context.getMessage();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            msg.writeTo(baos);
            String content = baos.toString("UTF-8");
            
            if (isOutbound) {
                System.out.println("=== 输出SOAP响应 ===");
            } else {
                System.out.println("=== 接收SOAP请求 ===");
            }
            System.out.println(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        // 同样可以捕获错误场景下的报文
        return true;
    }

    @Override
    public void close(MessageContext context) {}
}

然后在你的WebService实现类上添加注解,绑定处理器:

@WebService
@HandlerChain(file = "handler-chain.xml")
public class AccederWSService_AccederWSSoapPortImpl {
    // 服务方法实现
}

在类路径下创建handler-chain.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
    <handler-chain>
        <handler>
            <handler-class>your.package.SoapLoggingHandler</handler-class>
        </handler>
    </handler-chain>
</handler-chains>

二、空指针异常(NPE)排查思路

错误发生在getPaciente方法第22行(获取输入值的位置),核心问题是Delphi发送的请求未被正确解析为Java对象,导致你调用对象方法时触发NPE:

  1. 先做参数校验兜底:在方法开头添加null检查,避免直接触发NPE,同时输出调试信息:
    public Paciente getPaciente(GetPacienteRequest request) {
        if (request == null) {
            System.err.println("接收的请求对象为null");
            throw new WebServiceException("请求参数不能为空");
        }
        // 后续取值逻辑
    }
    
  2. 对比报文差异:用上面的方法捕获Delphi发送的请求,和SOAPUI的请求做逐行对比,重点看:
    • 命名空间前缀是否匹配
    • 必填元素是否缺失
    • 字段大小写、格式是否符合WSDL定义
  3. 检查JAXB绑定规则:确认生成的Java实体类和WSDL的元素映射是否完全一致,比如是否存在@XmlElement注解的命名空间、名称配置错误。

三、Delphi对接失败的核心原因

即使WSDL一致,不同客户端与服务端栈的兼容性差异也会导致问题:

  • SOAP版本不匹配:Delphi可能默认使用SOAP 1.1/1.2,而你的服务或原WebLogic服务使用了另一个版本。通过报文的Content-Type判断:SOAP 1.1是text/xml,SOAP 1.2是application/soap+xml。
  • HTTP头差异:Delphi可能发送了WebLogic兼容但JAX-WS默认不处理的头信息,比如SOAPAction头值不正确、自定义Cookie或Authorization头缺失/格式错误。
  • 数据类型兼容性:Delphi对日期、数值等类型的序列化格式可能和WebLogic不同(比如日期格式用DD/MM/YYYY而非标准ISO格式),导致JAXB解析失败,进而输入对象字段为null。
  • 命名空间宽松度差异:WebLogic可能允许命名空间前缀不严格匹配,而JAX-WS的默认绑定要求严格一致,导致Delphi发送的请求无法被正确解析。

内容的提问来源于stack exchange,提问作者Isaac de la Cruz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:05:02