【问题标题】:Unable to create envelope from given source because the root element is not named Envelope无法从给定源创建信封,因为根元素未命名为信封
【发布时间】:2016-11-07 17:23:42
【问题描述】:

我有一个在 SoapUI 中测试过的 SOAP 请求。我成功地得到了想要的响应。

当我在下面的if (isSuccessResponse(soapResponse)) { 测试响应是否成功时,会出现代码中的问题:

public static void main(String[] args) throws Exception {

 // Establish SOAP connection
 SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
 SOAPConnection soapConnection = soapConnectionFactory.createConnection();

 // Generate SOAP request
 SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), namespaceURI);

 // Test to see if SOAP response is available
 System.out.print("SOAP Response:");
 System.out.println();
 soapResponse.writeTo(System.out);

 // Close connection
 soapConnection.close();

 if (isSuccessResponse(soapResponse)) {
  System.out.println("Success!");
 } else {
  System.out.println("Fault!");
 }

}

成功了吗?

private static boolean isSuccessResponse(SOAPMessage soapResponse) throws Exception {
 NodeList responseNodes = soapResponse.getSOAPBody().getElementsByTagNameNS("*", "HelpDesk_QueryList_Service");

 if (responseNodes.getLength() == 1)
  return true;
 else
  return false;
}

请求: 该代码实际上打印出正确的请求,因为它与 SoapUI 中的工作请求相同。那么为什么我不能从实际响应中得到相关的相关信息呢?打印的响应是空白的默认响应,包含所有必需的标头,但我的请求中没有所需的信息:

private static SOAPMessage createSOAPRequest() throws Exception {
 MessageFactory messageFactory = MessageFactory.newInstance();

 // Create SOAP Message
 SOAPMessage soapMessage = messageFactory.createMessage();

 // Add request envelope, headers, and nodes from SOAP request 
 SOAPPart soapPart = soapMessage.getSOAPPart();

 // I used ? here for privacy reasons
 String xmlns = "?";
 String username = "?";
 String password = "?";
 String qualification = "'?";

 SOAPEnvelope envelope = soapPart.getEnvelope();
 envelope.addNamespaceDeclaration("urn", xmlns);

 SOAPHeader soapHeader = envelope.getHeader();
 SOAPElement authInfoElem = soapHeader.addChildElement("AuthenticationInfo", "urn");
 createElementAndSetText(authInfoElem, "userName", username);
 createElementAndSetText(authInfoElem, "password", password);

 SOAPBody soapBody = envelope.getBody();
 SOAPElement bodyElem = soapBody.addChildElement("HelpDesk_QueryList_Service", "urn");
 createElementAndSetText(bodyElem, "Qualification", qualification);

 MimeHeaders headers = soapMessage.getMimeHeaders();
 headers.addHeader("SOAPAction", xmlns + "/HelpDesk_QueryList_Service");

 // Save request
 soapMessage.saveChanges();

 // Print the request message
 System.out.print("SOAP Request:");
 System.out.println();
 soapMessage.writeTo(System.out);
 System.out.println();
 System.out.println();

 return soapMessage;
}

错误:我收到以下错误,但不确定原因。

Lis 07, 2016 6:10:34 ODP. com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl lookForEnvelope
SEVERE: SAAJ0514: Unable to create envelope from given source because the root element is not named Envelope
Lis 07, 2016 6:10:34 ODP. com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory createEnvelope
SEVERE: SAAJ0511: Unable to create envelope from given source
Exception in thread "main" com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source: 
    at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:117)
    at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:69)
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:128)
    at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.getSOAPBody(MessageImpl.java:1351)
    at com.xxxx.automation.remedy.RemedySOAPService.isSuccessResponse(RemedySOAPService.java:135)
    at com.xxxx.automation.remedy.RemedySOAPService.main(RemedySOAPService.java:52)
Caused by: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source because the root element is not named "Envelope"
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.lookForEnvelope(SOAPPartImpl.java:154)
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:121)
    at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:110)
    ... 5 more

CAUSE:

com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source because the root element is not named "Envelope"
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.lookForEnvelope(SOAPPartImpl.java:154)
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:121)
    at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:110)
    at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:69)
    at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:128)
    at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.getSOAPBody(MessageImpl.java:1351)
    at com.xxxx.automation.remedy.RemedySOAPService.isSuccessResponse(RemedySOAPService.java:135)
    at com.xxxx.automation.remedy.RemedySOAPService.main(RemedySOAPService.java

:52)

SOAP 响应:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns0:HelpDesk_QueryList_ServiceResponse xmlns:ns0="urn:XX:XXXX:HPD_IncidentInterface_WS">
         <ns0:getListValues>
            <ns0:Assigned_Group>XXXX</ns0:Assigned_Group>
            <ns0:Assigned_Group_Shift_Name/>
            <ns0:Assigned_Support_Company>XXXX</ns0:Assigned_Support_Company>
            <ns0:Assigned_Support_Organization>XXXX</ns0:Assigned_Support_Organization>
            <ns0:Assignee/>
            <ns0:Categorization_Tier_1/>
            <ns0:Categorization_Tier_2/>
            <ns0:Categorization_Tier_3/>
            <ns0:City/>
            <ns0:Closure_Manufacturer/>
            <ns0:Closure_Product_Category_Tier1>XXXX</ns0:Closure_Product_Category_Tier1>
            <ns0:Closure_Product_Category_Tier2>XXXX</ns0:Closure_Product_Category_Tier2>
            <ns0:Closure_Product_Category_Tier3/>
            <ns0:Closure_Product_Model_Version/>
            <ns0:Closure_Product_Name/>
            <ns0:Company>XXXX</ns0:Company>
            <ns0:Contact_Company>XXXX</ns0:Contact_Company>
            <ns0:Contact_Sensitivity>Standard</ns0:Contact_Sensitivity>
            <ns0:Country/>
            <ns0:Department>XXXX</ns0:Department>
            <ns0:Summary>XXXX</ns0:Summary>
            <ns0:Notes/>
            <ns0:First_Name>XXXX</ns0:First_Name>
            <ns0:Impact>4-Minor/Localized</ns0:Impact>
            <ns0:Incident_Number>XXXX</ns0:Incident_Number>
            <ns0:Internet_E-mail>XXXX</ns0:Internet_E-mail>
            <ns0:Last_Name>XXXX</ns0:Last_Name>
            <ns0:Manufacturer/>
            <ns0:Organization>XXXX</ns0:Organization>
            <ns0:Phone_Number>XXXX</ns0:Phone_Number>
            <ns0:Priority>Low</ns0:Priority>
            <ns0:Priority_Weight>0</ns0:Priority_Weight>
            <ns0:Product_Categorization_Tier_1>XXXX</ns0:Product_Categorization_Tier_1>
            <ns0:Product_Categorization_Tier_2>XXXX</ns0:Product_Categorization_Tier_2>
            <ns0:Product_Categorization_Tier_3/>
            <ns0:Product_Model_Version/>
            <ns0:Product_Name/>
            <ns0:Region/>
            <ns0:Reported_Source xsi:nil="true"/>
            <ns0:Resolution/>
            <ns0:Resolution_Category/>
            <ns0:Resolution_Category_Tier_2/>
            <ns0:Resolution_Category_Tier_3/>
            <ns0:Service_Type>User Service Restoration</ns0:Service_Type>
            <ns0:Site>XXXX</ns0:Site>
            <ns0:Site_Group>XXXX</ns0:Site_Group>
            <ns0:Status>Cancelled</ns0:Status>
            <ns0:Status_Reason xsi:nil="true"/>
            <ns0:Urgency>4-Low</ns0:Urgency>
            <ns0:VIP>No</ns0:VIP>
            <ns0:ServiceCI/>
            <ns0:ServiceCI_ReconID/>
            <ns0:HPD_CI/>
            <ns0:HPD_CI_ReconID/>
            <ns0:HPD_CI_FormName/>
            <ns0:z1D_CI_FormName/>
            <ns0:Vendor_Ticket_Number xsi:nil="true"/>
            <ns0:Corporate_ID>XXXX</ns0:Corporate_ID>
            <ns0:Submitter>XXXX</ns0:Submitter>
            <ns0:Pending_Date xsi:nil="true"/>
         </ns0:getListValues>
      </ns0:HelpDesk_QueryList_ServiceResponse>
   </soapenv:Body>
</soapenv:Envelope>

【问题讨论】:

  • 从我的阅读中:堆栈不在请求的伪造中,而是在响应的处理中。响应是有效的 SOAP 吗?
  • 我真的认为问题出在此处:private static boolean isSuccessResponse(SOAPMessage soapResponse) throws Exception { 但我还不确定出了什么问题。
  • 我在上面包含了一个示例成功响应。一方面,我的回复名称错误,所以我将 HelpDesk_QueryList_Service 更改为 HelpDesk_QueryList_ServiceResponse...

标签: java soap remedy


【解决方案1】:

首先,您的错误似乎是在 SAAJ 框架处理响应时发生的。因此,我不会深入研究请求的创建,我认为这很好,特别是因为您认为 SoapUI 伪造的请求相同。您还可以检查 HTTP 标头以进一步确定这一点。

堆栈跟踪的重要部分是:

at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:128)
at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.getSOAPBody(MessageImpl.java:1351)

这告诉我们 SOAP 框架无法处理 响应信封。假设响应确实有效,这看起来很可疑。

查看您的代码,我怀疑这是对 SAAJ API 的滥用:

// Close connection
soapConnection.close();

if (isSuccessResponse(soapResponse)) {
  System.out.println("Success!");
} else {
  System.out.println("Fault!");
}

在实际使用消息之前关闭连接。如果 SAAJ 实现是惰性的(我猜是这样,这将是有道理的),则不会立即从网络 Socket 解析消息。通过使用响应消息之前关闭连接,实际上是在套接字被读取之前关闭了套接字,因此实现无法读取该消息。

我建议在您使用响应对象之后延迟关闭与 的连接。

这部分代码可以做同样的论证:

 System.out.print("SOAP Response:");
 System.out.println();
 soapResponse.writeTo(System.out);

 // Close connection
 soapConnection.close();

通过将响应转储到控制台,您实际上使框架使用套接字(读取 HTTP 响应)。稍后,一旦您要求框架将响应流解析为信封,如果它没有缓存流的内容,则此操作失败:没有更多字节要解析。

所以简而言之:在框架有机会实际解析结果之前,不要“触摸”连接或响应对象。从 API 设计的角度来看,这并不明显,但这是可以理解的行为。

其他一些线索: stackoverflow 上的其他人报告说他们的旧版本的 Xerces/Xalan 是罪魁祸首(那些是 XML 解析器,JDK 内置了自己的 Xerces 版本),所以你可能也想检查一下: Java Spring WS org.springframework.ws.soap.saaj.SaajSoapEnvelopeException: Could not access envelope http://mmmsoftware.blogspot.fr/2009/06/xml-namespace-error-with-spring-ws.html

【讨论】:

  • soapConnection.close(); 移动到下方或检查isSuccessResponse(soapResponse) 之后似乎不起作用。嗯……
  • 我会编辑的。下一个嫌疑人是 response.writeTo(System.out),它消耗了流!
  • 好点,我会将更改合并到我的设计中,但它似乎并不能防止 SAAJ 错误。经过调试,问题肯定出在这里:NodeList responseNodes = soapResponse.getSOAPBody().getElementsByTagNameNS("*", "HelpDesk_QueryList_ServiceResponse");
  • 快速环顾四周后,我发现了其他可能性,但我在这里没有选择。如果这仍然不起作用,我会建议对源代码进行 grep 并在内部进行调试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2017-06-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-24
相关资源
最近更新 更多