使用APEX_WEB_SERVICE调用SOAP服务遇ORA-30625错误求助
调用SOAP Web服务时触发
ORA-30625: method dispatch on NULL SELF argument is disallowed错误,SOAP-UI中请求可正常执行,但PL/SQL代码无法正常运行,代码如下:
declare l_token VARCHAR2(32767); l_envelope CLOB; l_xml XMLTYPE; l_result VARCHAR2(32767); BEGIN l_envelope := q'!<?xml version='1.0' encoding='UTF-8'?>!'; l_envelope := l_envelope || '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"> <soap:Header/> <soap:Body> <ws:getMsisdnAndAvailabilityFromSerial> <simCardSerial>8925801191077167862</simCardSerial> <loginInfo> <!--Optional:--> <nomeAplicacao>***</nomeAplicacao> <!--Optional:--> <usuario>***</usuario> <!--Optional:--> <password>***</password> <!--Optional:--> <token>***</token> </loginInfo> </ws:getMsisdnAndAvailabilityFromSerial> </soap:Body> </soap:Envelope>'; -- Aqui, certifique-se de que todas as instâncias de objetos não são nulas IF l_envelope IS NOT NULL THEN l_xml := XMLTYPE.createXML(l_envelope); ELSE -- Lidar com o caso onde l_envelope é NULL RAISE_APPLICATION_ERROR(-20001, 'Envelope é NULL'); END IF; -- -- l_xml := xmltype(l_envelope); dbms_output.put_line('Envelope SOAP: ' || l_envelope); l_xml := apex_web_service.make_request(p_url => 'http://ServerIP/SimRegWebService', p_action => 'http://ServerIP/SimRegWebService/getMsisdnAndAvailabilityFromSerial' , p_envelope => l_envelope); dbms_output.put_line('Resposta SOAP: ' || l_xml.getclobval()); l_result := apex_web_service.parse_xml(p_xml => l_xml, p_xpath => '', p_ns => 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"'); dbms_output.put_line('Resultado: ' || l_result); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLERRM); END;
排查方向与解决方案
ORA-30625错误本质是调用对象方法时,对象实例为NULL,结合代码和SOAP服务特性,重点排查以下几点:
1. 检查apex_web_service.make_request的返回值
当Web服务请求失败(网络不通、URL错误、权限限制等),make_request可能返回NULL。后续调用l_xml.getclobval()时,因为l_xml是NULL,直接触发错误。
解决: 在使用l_xml前增加非空判断:
-- 调用Web服务后增加判断 IF l_xml IS NOT NULL THEN dbms_output.put_line('Resposta SOAP: ' || l_xml.getclobval()); ELSE DBMS_OUTPUT.PUT_LINE('Erro: Web服务请求未返回有效XML'); END IF;
2. 修正p_action参数的正确性
SOAP Action值必须与服务端要求完全一致,代码中当前的p_action用了服务器URL拼接方法名,大概率不符合要求。可以从SOAP-UI的请求头中复制准确的SOAP Action值(通常是命名空间+方法名,比如http://ws.mcel.co.mz/getMsisdnAndAvailabilityFromSerial)。
解决: 替换p_action为SOAP-UI中验证过的正确值。
3. 优化SOAP信封的构建方式
代码中手动拼接XML时使用了大量转义字符,容易导致XML格式错误,虽然SOAP-UI能处理,但PL/SQL解析时可能出问题。
解决: 用q'[...]'直接引用完整XML,避免转义错误:
l_envelope := q'[<?xml version='1.0' encoding='UTF-8'?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"> <soap:Header/> <soap:Body> <ws:getMsisdnAndAvailabilityFromSerial> <simCardSerial>8925801191077167862</simCardSerial> <loginInfo> <nomeAplicacao>***</nomeAplicacao> <usuario>***</usuario> <password>***</password> <token>***</token> </loginInfo> </ws:getMsisdnAndAvailabilityFromSerial> </soap:Body> </soap:Envelope>]';
4. 确认数据库服务器的网络与权限
SOAP-UI在本地能访问服务,但数据库服务器可能没有目标URL的访问权限,或者网络不通。
解决: 在数据库服务器上测试目标URL的连通性,同时检查数据库的ACL权限配置(确保APEX_WEB_SERVICE有权限访问外部网络)。
5. 避免解析空XML
如果l_xml为NULL,调用apex_web_service.parse_xml也会触发错误,需要提前判断。
解决: 解析前增加非空判断:
IF l_xml IS NOT NULL THEN l_result := apex_web_service.parse_xml(p_xml => l_xml, p_xpath => '', p_ns => 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"'); dbms_output.put_line('Resultado: ' || l_result); ELSE DBMS_OUTPUT.PUT_LINE('Erro: 无法解析空的XML响应'); END IF;
修改后的完整代码示例
declare l_token VARCHAR2(32767); l_envelope CLOB; l_xml XMLTYPE; l_result VARCHAR2(32767); BEGIN -- 直接引用完整XML,避免转义错误 l_envelope := q'[<?xml version='1.0' encoding='UTF-8'?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"> <soap:Header/> <soap:Body> <ws:getMsisdnAndAvailabilityFromSerial> <simCardSerial>8925801191077167862</simCardSerial> <loginInfo> <nomeAplicacao>***</nomeAplicacao> <usuario>***</usuario> <password>***</password> <token>***</token> </loginInfo> </ws:getMsisdnAndAvailabilityFromSerial> </soap:Body> </soap:Envelope>]'; dbms_output.put_line('Envelope SOAP: ' || l_envelope); -- 调用Web服务,替换为正确的SOAP Action l_xml := apex_web_service.make_request( p_url => 'http://ServerIP/SimRegWebService', p_action => 'http://ws.mcel.co.mz/getMsisdnAndAvailabilityFromSerial', p_envelope => l_envelope ); -- 检查XML响应是否为空 IF l_xml IS NOT NULL THEN dbms_output.put_line('Resposta SOAP: ' || l_xml.getclobval()); -- 解析XML结果 l_result := apex_web_service.parse_xml( p_xml => l_xml, p_xpath => '', p_ns => 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.mcel.co.mz/"' ); dbms_output.put_line('Resultado: ' || l_result); ELSE DBMS_OUTPUT.PUT_LINE('Erro: Web服务请求未返回有效XML'); END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLERRM); END; /
内容的提问来源于stack exchange,提问作者nelio mboana

