Salesforce is a wonder tool for sure, but sometimes we need to work our way through it. For example, when we were trying to generate Apex class from WSDL in Salesforce, we encountered errors every single time. All our attempts at invoking external services through Apex were greeted with the same error message!

Failed to parse wsdl: attribute name cannot be null at: 885:31,

<xs:attribute ref=”tns:Idn” /> name is required etc.        

pic 

We tried implementing a number of changes related to wsdl attributes (with salesforce datatypes) but nothing seemed to work this time.

However, we got lucky when we implemented our own Apex class, which subsequently connected to the external system through HTTP ,additionally utilising the current WSDL parameters as reference.

In our implementation, we’ll connect to external system to get Business Data using Business Search external service.

Sample Code                                                                

Http http = new Http();

HttpRequestreq = new HttpRequest();

//Identify endpoint url

req.setEndpoint(‘https://xxx.appshark.com/ews/services/DataService’);

//Set request header as SOAP Action                                             

req.setHeader(‘SOAPAction’, ‘”http://ws.appshark.com/connect/v1″‘);

req.setMethod(‘POST’);

//Identify Authentication details and add to request body                     

stringstrReq = ‘<soap:Envelope;

strReq+=’ ;

strReq+='<AuthenticationToken;

strReq+='<Password ;

strReq+='<Channel ;

//Invoke which service you want to invoke from wsdl and add those parameters to request body                          strReq+='<soap:Body ;

strReq+='<ns1:BusinessSearchParam>’;

strReq+='<ns1:LinkId>123456789</ns1:LinkId>’;

strReq+='<ns1:Products>’;

strReq+='<ns1:Product>Appshark LOS</ns1:Product>’;

strReq+='</ns1:Products>’;

strReq+='</ns1:BusinessSearchParam>’;

strReq+='</ns1:BusinessSearch>’;

strReq+='</soap:Body>’;

strReq+='</soap:Envelope>’;

req.setBody(strReq); //xmldata is injecting to request body

HTTP objresponse= http.send(req);; //holds the response after request

 

To sum it up, in general, these are the steps we followed to achieve the desired result:

  1. Identify endpoint url

req.setEndpoint(‘https://xxx.ecredit.com/ews/services/DataService’);

  1. Set request header as SOAPAction

req.setHeader(‘SOAPAction’, ‘”http://ws.ecredit.com/connect/v1″‘);

  1. Identify Authentication details and add to request body.

strReq+='<soap:Header>’;

strReq+='<AuthenticationToken ;

strReq+='<Password ;

strReq+='<Channel ;

  1. Invoke the service you want to invoke from wsdl and add those parameters to request body

strReq+='<soap:Body ;

strReq+='<ns1:BusinessSearchParam>’;

strReq+='<ns1:LinkId>123456789</ns1:LinkId>’;

strReq+='<ns1:Products>’;

strReq+='<ns1:Product>Cortera LOS</ns1:Product>’;

strReq+='</ns1:Products>’;

strReq+='</ns1:BusinessSearchParam>’;

strReq+='</ns1:BusinessSearch>’;

strReq+='</soap:Body>

 

Therefore, it is indeed possible to invoke/connect to external system through HTTP API without generating classes from WSDL.