5

I am looking at a strange exception when I make an apex callout to a external system. I am forming a very simple apex code to hit the endpoint using wsdl2Apex class. I get the below excception:

Exception:

System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: [ISS.0088.9164] Access to WSDescriptor wsdl2apexClassName.webservices:wsdlName denied. faultcode=soapenv:Client faultactor=http://..endpoint

Apex Callout Code:

    wsdl2apexclassName sample = new wsdl2apexclassName();
wsdl2apexclassName.input req = new wsdl2apexclassName.input();
sample.endpoint_x = 'the end point goes here';

sample.inputHttpHeaders_x = new Map<String, String>();
sample.inputHttpHeaders_x.put('Username','username');
sample.inputHttpHeaders_x.put('Password','pass');
wsdl2apexclassName.response res = sample.functionwhichhasInvokeMethod(req);
system.debug('******' + res);

WSDL has these information in the beginning:

> <?xml version="1.0" encoding="UTF-8"?><wsdl:definitions
> xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="wsdlName"
> targetNamespace="http://URL"
> xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
> xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
> xmlns:soapjms="http://www.w3.org/2010/soapjms/"
> xmlns:tns="http://URL****"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
> xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
> xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/">   
<wsdl:types>
......

DEbug log: CALLOUT_REQUEST

invokeMethod:[apex_schema_type_info=(http://endpoint, false, false), field_order_type_info=

(Input), Input=Input:[apex_schema_type_info=(http://targetURL, false, false), 

field_order_type_info=(listOfPfOrderOutboundIo), listOfPfOrderOutboundIo=null, 

listOfPfOrderOutboundIo_type_info=(listOfPfOrderOutboundIo, 

http://targetURL, null, 1, 1, 

false)], orderInput_type_info=(Input, 

http://targetURL, null, 1, 1, 

true)]::SOAPAction="SOAPAction" 

Accept=text/xml Username=usernamee**** User-Agent=SFDC-Callout/38.0 SFDC_STACK_DEPTH=1 

Password=**** Content-Type=text/xml; charset=UTF-8
  • Can you check the end point is accessible from browser? – Ashwani Dec 29 '16 at 21:41
  • @Ashwani Yes it is. In additional I am able to hit the endpoint using SOAP UI and get a successful response. – SfdcBat Dec 29 '16 at 21:42
  • 1
    Can you capture the SOAP request SF is sending from your debug log? I imagine your request is improperly formed if you can hit it from a soap ui. There should be a line in your debug named CALLOUT_REQUEST that will show you the envelope being sent. – Jesse Milburn Dec 29 '16 at 22:04
  • 1
    @SfdcBat Are you certain the credentials should be in the HTTP headers? Maybe the need to be in the SOAP headers. If you can share the WSDL (without the endpoint if required) and the working SOAP UI request it would be helpful. – Daniel Ballinger Dec 30 '16 at 1:16
  • 1
    @SfdcBat The sample code to call the web service from Apex looks a bit odd. Is sample actually a proxy class like wsdl2apexClassName.webservices. I say odd because it is usually an inner class that contains the web method proxies. – Daniel Ballinger Dec 30 '16 at 1:45
3

The reason for this erro was , I was passing the username and password in the wrong way in Http header like below:

sample.inputHttpHeaders_x = new Map<String, String>();
sample.inputHttpHeaders_x.put('Username','username');
sample.inputHttpHeaders_x.put('Password','pass');

It should be added to the header using a property name 'authorization' and the username and password should be base64encoded as below

Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);    
sample.inputHttpHeaders_x.put('Authorization', authorizationHeader);

Reference - https://developer.salesforce.com/blogs/developer-relations/2009/01/using-basic-authentication-with-web-services.html

This has solved my problem. Hope it helps anybody else also.

  • Glad you got it solved :) I would be curious to see what that request xml ended up looking like. – Jesse Milburn Dec 30 '16 at 21:29
  • @SfdcBat - I got lost in all the other drama on this question and completely overlooked how you were sending the credentials. Your answer is the typical way of doing it for http requests . Sometimes it is the most basic things. Glad you got it worked out. – Eric Dec 31 '16 at 2:18
  • @Eric yeah understand that . Its always about basics! :) – SfdcBat Dec 31 '16 at 2:21
2

To debug this issue you can create a temporary RequestBin URL by going to https://requestb.in/ - enter image description here
1. Click on "Create a RequestBin" and keep this window open 2. Copy this URL and add to the remote site settings in SFDC 3. Replace original endpoint with this URL as per sample code below -

//Generated by wsdl2apex

public class docSampleComDocsample {
    public class EchoStringResponse_element {
        public String EchoStringResult;
        private String[] EchoStringResult_type_info = new String[]{'EchoStringResult','http://doc.sample.com/docSample',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://doc.sample.com/docSample','true','false'};
        private String[] field_order_type_info = new String[]{'EchoStringResult'};
    }
    public class EchoString_element {
        public String input;
        private String[] input_type_info = new String[]{'input','http://doc.sample.com/docSample',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://doc.sample.com/docSample','true','false'};
        private String[] field_order_type_info = new String[]{'input'};
    }
    public class DocSamplePort {
        public String endpoint_x = 'http://requestb.in/10vmy8b1';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://doc.sample.com/docSample', 'docSampleComDocsample'};
        public String EchoString(String input) {
            docSampleComDocsample.EchoString_element request_x = new docSampleComDocsample.EchoString_element();
            request_x.input = input;
            docSampleComDocsample.EchoStringResponse_element response_x;
            Map<String, docSampleComDocsample.EchoStringResponse_element> response_map_x = new Map<String, docSampleComDocsample.EchoStringResponse_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'urn:dotnet.callouttest.soap.sforce.com/EchoString',
              'http://doc.sample.com/docSample',
              'EchoString',
              'http://doc.sample.com/docSample',
              'EchoStringResponse',
              'docSampleComDocsample.EchoStringResponse_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.EchoStringResult;
        }
    }
}
  1. Perform callout, I executed this code from developer console-

    docSampleComDocsample.DocSamplePort stub = new docSampleComDocsample.DocSamplePort(); String input = 'This is the input string'; String output = stub.EchoString(input);

  2. Go to RequestBin window and click on below icon to see the request payload - enter image description here

  3. The request payload will be shown as below - enter image description here

  4. Once the debug is complete you can remove the remote site settings and replace the endpoint in code with original endpiont

  • Thanks. What do we get by doing step 5 and 6 here? – SfdcBat Dec 30 '16 at 14:53
  • Hi @SfdcBat, at step 5 just copy request RAW BODY payload and compare it with the working copy of request payload from SOAP UI to see if there is any difference in the request payload. – LakhanP Dec 30 '16 at 15:22
  • Can I use the payload details which you gave in step 5 and compare with my SOAP UI request to actual endpoint? – SfdcBat Dec 30 '16 at 16:27
  • I didn't have complete WSDL therefore I used one of the sample it will not be useful for you. – LakhanP Dec 30 '16 at 16:43
  • I don't understand how using this can be helpuful to me. My wsdl and endpoint is from some other system which is expecting a different kind of request. I wont be able to replace that endpoint here. – SfdcBat Dec 30 '16 at 16:57

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.