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
14
  • Can you check the end point is accessible from browser?
    – Ashwani
    Dec 29, 2016 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, 2016 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. Dec 29, 2016 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. Dec 30, 2016 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. Dec 30, 2016 at 1:45

2 Answers 2

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.

3
  • Glad you got it solved :) I would be curious to see what that request xml ended up looking like. Dec 30, 2016 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, 2016 at 2:18
  • @Eric yeah understand that . Its always about basics! :)
    – SfdcBat
    Dec 31, 2016 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

5
  • Thanks. What do we get by doing step 5 and 6 here?
    – SfdcBat
    Dec 30, 2016 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, 2016 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, 2016 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, 2016 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, 2016 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.