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:
- 先做参数校验兜底:在方法开头添加null检查,避免直接触发NPE,同时输出调试信息:
public Paciente getPaciente(GetPacienteRequest request) { if (request == null) { System.err.println("接收的请求对象为null"); throw new WebServiceException("请求参数不能为空"); } // 后续取值逻辑 } - 对比报文差异:用上面的方法捕获Delphi发送的请求,和SOAPUI的请求做逐行对比,重点看:
- 命名空间前缀是否匹配
- 必填元素是否缺失
- 字段大小写、格式是否符合WSDL定义
- 检查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
相关产品推荐
相关产品推荐

