4

good day!

We have a system that consumes webservice in SAP. Due to the complexity of webservice structure that SF is invoking in SAP, we use the tool wsdl2apex to generate stub classes. Basically, the connectivity is like this:

SF ==> APIgee ==> Siteminder ==> SAP

The system needs a few enhancements particularly in logging. The goal is to have comprehensive log, to easily pinpoint the culprit when failure happens. The main reason why this enhancement conceived is that there were some webservice/network/middleware-related issues and we really had a hard time tracing that.

When we had those issues, the log only says:

Web service callout failed: Unexpected element. Parser was expecting element 'http://schemas.xmlsoap.org/soap/envelope/:Envelope' but found ':HTML'

The error message above is same error when we had authentication error, gateway timeout, SAP unavailability, or any siteminder error, which is being relayed to APIgee, the point where SF connects. The errors actually would have different HTTP headers and messages in the body, but I don't know how to get the content/body and headers using wsdl2apex (or WebServiceCallout) approach.

QUESTIONS:

  1. How do I extract/generate the XML SOAP envelope being sent to webservice from the stub classes generated by wsdl2apex?
  2. How do I extract/generate the raw data returned by the webservice from the stub classes generated by wsdl2apex?
  3. How do I get the HTTP headers returned by the webservice from the stub classes generated by wsdl2apex?

NOTE: when the call was a success, outputHttpHeaders_x contains HTTP headers. However, when there's an error, i.e. 400, 401, 404, 40x, outputHttpHeaders_x is not getting populated. Though a SOAPUI simulation clearly shows there were headers returned.

Please don't tell me to use HTTPRequest instead. I am not in the position to revamp the current code, and I don't have the time and budget to do that. Also, we have a very complex webservice and wsdl2apex tools is really handy to generate all the stubs for such complex webservice.

THANK YOU!

3

The easiest way to debug a WebServiceCallout.invoke call is to capture the debug log from a Developer Edition org.

In this case it will include the CALLOUT_REQUEST, CALLOUT_RESPONSE events. The info for these includes the SOAP XML body that is being sent and the corresponding response.

If a developer edition org isn't an option, then there are a few of other options you can try:

  1. Change the endpoint_x to point to SOAP UI running on your local machine with a public IP adddress. I've used SOAP UI in this way in the past to intercept the Salesforce Callout. You can then relay the same call to the correct web service to see what the response is.
  2. In the wsdl2apex generated class, modify the methods immediately before the WebServiceCallout.invoke to dump out the request_x variable. This will include all the details that you are passing the web service. Again, you would need to manually turn this into a SOAP UI Request to see the actual web service output. If you just send it to System.debug you will get a JSON representation. It isn't too difficult to turn this into a SOAP envelope.
  3. If you can get access to the EventLog paid feature, you can access the Apex Callout and Apex SOAP logs. I haven't seen the content of these log types, but suspect they would be useful.
  4. You ruled out using HttpRequest, but I'm going to include this anyway. We made a free alternative version of Wsdl2Apex here at work. Part of this is the option to automatically generate the Apex code required to use HttpRequest for the WSDL. Maybe consider it, as it would give you more options in how the request and response are processed.

As far as I know there isn't a way outside of logging to see the actual response in code.

  • Hi Daniel, thanks for the possible workaround. I generated a stub class using FuseIT's WSDL2Apex. Adjusted code and executed. However, I am getting an error returned by the endpoint. I was able to spot the difference in the generated XML: Salesforce: <m:BAPI_ACC_DOC_CHK xmlns:m"urn:sap-com:document:sap:rfc:functions"> </m:BAPI_ACC_DOC_CHK> FuseIT: <BAPI_ACC_DOC_CHK xmlns"urn:sap-com:document:sap:rfc:functions"> </BAPI_ACC_DOC_CHK> SF stub XML payload includes namespace prefix "m", which works. When prefix is removed (which FuseIT stub class produces), I get a fault. – pnoytechie Nov 4 '15 at 6:11
  • How can I (manually) add the namespace prefix for FuseIT generated stub class? – pnoytechie Nov 4 '15 at 6:12
  • by the way, when calling the HTTP counterpart, the same issue occurs. it lacks the needed namespace prefix – pnoytechie Nov 4 '15 at 6:37
  • Typically the xml namespaces are handled by the *_type_info members in the sub classes. These map the namespaces for each element, along with the type and cardinality details. Try comparing and adjusting those. Are you able to share the WSDL in question so I can test the Apex generation with it? – Daniel Ballinger Nov 4 '15 at 8:46
  • in the HTTP method, I added the prefix in body.addChildElement when generating the method node: DOM.XmlNode methodNode = body.addChildElement('YBAPI_ACC_DOCUMENT_CHECK', NAME_SPACE, 'm');. However, in the generated XML, child nodes had their own namespace, without prefix. bigger problem. – pnoytechie Nov 4 '15 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.