Consuming External Web Service in Apex – Salesforce

One of the feature we have in Salesforce is that we can easily consume External Web Services. In this article, we will learn step by step demo of consuming Web Service in Apex. There are many public websites available to consume Web Service and one of them, I am using in this article is http://www.webservicex.net , from this location we are using Stock Quote Webservice. To consume this, we need WSDL.

The Web Services Description Language (WSDL) is an XML-based interface description language that is used for describing the functionality offered by a Web Service.

WSDL have to be downloaded from this location. We need this WSDL in later part of this tutorial.

Once, WSDL is downloaded and saved on local drive. We have to go to Salesforce and navigate to “Setup | Develop | Apex Classes”. On right hand side, you will find button named as “Generate from WSDL”. This button will generate equivalent Apex class to support Webservice call. In some Programming languages, these classes are known as Proxy classes or Stubs.

When we click on “Generate from WSDL” button, it will prompt for WSDL File. Select WSDL file downloaded previously and click on “Parse WSDL” button. On next page you will get this error : “Failed to parse wsdl: Found more than one wsdl:portType. WSDL with multiple portType not supported”.

In some cases you may also get error like : “Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported”.

Intentionally, I have used this WSDL to explain that currently Salesforce supports only single portType and binding.

PortType : defines a web service, the operations that can be performed, and the messages that are involved.
Binding : WSDL bindings defines the message format and protocol details for a web service.

Reason, we are getting an error because “wsdltoApex” doesnt support multiple PortType, Binding, SOAP 1.2 and Schema imports. You can read more here from Salesforce documentation.

How to resolve multiple portType and Binding error in Apex while generating stubs ?

We have to modify downloaded WSDL to make sure it only contains Single Binding and single PortType. Before modifying I would suggest to read about WSDL elements. I have uploaded both versions of WSDL (Please change attached file extensions from txt to xml). First one is Actual WSDL and second I have modified to remove errors. You can compare both and check how I removed multiple PortType and Binding elements from WSDL.

  1. Stockquote Actual WSDL File (Change extension from txt to xml)
  2. Stockquote Updated WSDL File (Change extension from txt to xml)

Once, you modify your wsdl, try to generate Apex class again and this time you will be able to generate class without any error.

Generating Apex from WSDL in Salesforce
Generating Apex from WSDL in Salesforce

So, here we have successfully generated Stub classes for Webservice.

How to use generated web-service Apex stub ?

Before trying to use webservice, we have to inform Salesforce that our code will try to get some Data from External source (rather interact with external system). And therefore Remote Site Setting comes into picture.

Navigate to “Setup | Security Control | Remote Site Settings“.

Create new Site setting for URL “http://www.webservicex.net“. If we skip this step, we will endup with error like “Unauthorized Endpoint”.

We can use generated Apex class in Visualforce or some other location. To keep this tutorial simple, I am using “Developer Console”. Open Developer Console and press “Ctrl+E”.

wwwWebservicexNet.StockQuoteSoap proxyClass = new wwwWebservicexNet.StockQuoteSoap();
String retVal = proxyClass.GetQuote('CTSH');
System.debug(retVal);

In above code “CTSH” is Stock symbol for Cognizant Technology Solution. You can use any other valid Stock Symbol. Output will be visible in Console Log. We can use this output as per our need

How you will find that which Class to instantiate ?
As shown in above code, I have created Object for “wwwWebservicexNet.StockQuoteSoap”.  I was able to identify that which class to instantiate? I was able to identify by porttype element name from WSDL.

How to increase Time out in Webservice ?

You may get Timeout exception while calling webservice. Default time is 10sec (At time of writing this tutorial, may change in future release). we can use “timeout_x” property to increase time to wait for response from web service. So above code can be re-written as

wwwWebservicexNet.StockQuoteSoap proxyClass = new wwwWebservicexNet.StockQuoteSoap();
proxyClass.timeout_x = 20000 ; // timeout in milliseconds
String retVal = proxyClass.GetQuote('CTSH');
System.debug(retVal);

Some Known Limitations to WSDL2Apex :

  1. It does not support multiple port bindings.
  2. Inheritance is not supported in wsdl to APEX conversion.
  3. Complex Object types such as Enumeration are not supported.
  4. WSDL Import functionality is not supported.

I hope this tutorial will be helpful for newbies. Please post your comment and feedback about this tutorial. I will be delighted to answer your query about this article.

Related posts

  • Vineet Puranik

    Nice Tutorial

  • Gautham Korada

    Amazing tutorial..but i am struct up near removing the error related to MultiplePort binding because the 2 files given seems the same..not sure if i am looking at it correctly..pls help me

    • JitendraZaa

      Hi Gautam, If you compare both File, One is larger in size and one is smaller. Larger is original and will not work. Smaller size is updated and will work. You can use Notepad++ to compare XML Files

      • Gautham Korada

        I did the same Jitendra, tried comparing in Notepad++ ..ok anyway will give another try..

        • Gautham Korada

          I m sorry Jitendra, Now i see it..thank you.

          • Gautham Korada

            Jitendra, I have tried one more WSDL from the same website which is for Currency Convertor, but i m getting an error while parsing..

            Error: Failed to parse wsdl: Parse error: Found invalid XML. end tag name must match start tag name
            from line 200 (position: TEXT seen …
            ZWD-Zimbabwe Dollar… @200:3628)

            But i see all the tags are properly matching ..kindly suggest me where i need to modify in order to PARSE.

          • Gautham Korada

            Atleast give me an idea how to call StockQuote from a VF page.

          • lakshminarayana

            Hey , did u resolved that error.?
            if u did it tel me how to work with it.

      • sudha

        hi could u provide Tutorial on REST API integration

      • sudha

        hi i m getting error while execute in Anonymous Window

        • JitendraZaa

          Execute it using VF page please.. Anonymous window is not useful in Async call…

          • sudha

            even in visualforce also i am getting same error

  • ganesh.jujjuru

    hi shiva,
    i was trying to do example of .net integration, But iam facing the below error

    System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: System.Web.Services.Protocols.SoapException: Server was unable to process request. —> System.IO.IOException: There is not enough space on the disk. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count) at System.IO.FileStream.FlushWrite(Boolean calledFromFinalizer) at System.IO.FileStream.Dispose(Boolean disposing) at System.IO.Stream.Close() at System.IO.StreamWriter.Dispose(Boolean disposing) at System.IO.TextWriter.Dispose() at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources) at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources) at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources) at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence) at System.Xml.Serialization.XmlSerializer.FromMappings(XmlMapping[] mappings, Type type) at System.Web.Services.Protocols.SoapServerType..ctor(Type type, WebServiceProtocols protocolsSupported) at System.Web.Services.Protocols.SoapServerProtocol.Initialize() at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing) — End of inner exception stack trace — faultcode=soap:Server faultactor=: Class.ganesh1234.wwwWebservicexNet.StockQuoteSoap.GetQuote: line 25, column 1 AnonymousBlock: line 2, column 1 AnonymousBlock: line 2, column 1

    Please rectify my error ………..Thanks in Advance Shiva

    • JitendraZaa

      Hi Ganesh..

      Its not related to Salesforce or .Net. Check space on your Hard disc. It is Operating System related error.

      • ganesh.jujjuru

        Hi how much space i need in Hard disc..?

    • kullai

      Hi Jitendra Zaa,

      How to Updating the Second XML page is there Any Link please send me

  • srinivas

    HI jithendra,
    can you explain one scenario for REST
    if we write the REST based apex class how can we generate the end-point url for the class

  • lakshminarayana

    hi unable to download that WSDL…can u provide me the any other links for downloading that WSDL

  • Raghuprasad

    Hi Jitendra,
    I’m given a WSDL wherein required parameters to send across request object are of enum types. And there are not supported in salesforce. In that case is it possible to convert them into complex/simple types ? if yes, how ?

    thanks,
    Raghuprasad

  • raj

    Hi Jitendra,
    i am working with sfdc from couple of months still and newbie to web services.
    i have followed the steps and was able to create stub and use it in developer console. please let me how we can use the response in vf pages

    Thanks for your help
    Regards,
    Raj

    • JitendraZaa

      Hi Raj,
      You can call webservice in Controller class of Visualforce and save returned value in some Field. SHow that field in Viusalforce..

      • raj

        Thank you Jitendra,

        working on the parsing the received response using dom , is there any sort of good example for restful or soap producer and consumer? This would be great help for me in understanding the both the implementations and will be useful in my another attempt of using websercies being called from a second party to transfer the acounts list and corresponding the cases list vice versa.

        Thank you
        Raj

  • Deep

    Elaboration is Best, Thanks I matched up with he article and was able to implement it.

  • Deep

    How can we display the web service response in a VF page or an Salesforce Object

  • Krithika

    How do I work if I am unable to generate the WSDL classes and have to handcraft the soap calls? The external webservice has confirmed that is the approach to be taken. Do you have any samples?

  • RAJ KIRAN

    how do we write test classes for these consuming webservices??

  • Rohit Patil

    Hi Jitendra,
    Is it possible to consume Exchange service wsdl in salesforce?

    • You can consume any WSDL in support with some exceptions , you should go through this post which explains which component in WSDL is not supported – https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex.htm

      Apex does not support any other WSDL constructs, types, or services, including:
      RPC/encoded services
      WSDL files with mulitple portTypes, multiple services, or multiple bindings
      WSDL files that import external schemas. For example, the following WSDL fragment imports an external schema, which is not supported:

  • santosh kumar

    Hi Sending Attachment from Salesforce to external system through SOAP Call is possible?pls help me

  • Akshay Deshmukh

    This is really an amazing blog. Your blog has really helped me understand webservice consumption concept in apex.

    However many company’s quotes are not getting generated due to some issues with WSDL site. I tried with MSFT, CRM etc but still no luck.

    Thanks a lot.

  • Deep Singhal

    Hi Jitendra,
    Is there a way to trace outgoing SOAP envelope in sandboxes to help debugging the issues. I tried to play with debug level but of not much help. Now I use RequestBib/GetSandbox to trace the message after changing the endpoint. Is there a way to trace the message in debug with the actual endpoint.

    Out of business-
    I am a fan of your posts because of the knowledge and simplicity involved. It also feels good that you work for the same organization that I do :).

    • Thanks for your words @CommonIntellect:disqus

      I think Requestbin is good option. If its REST API then we can use custom object, however for SOAP API it would be tricky to capture SOAP request.

  • Shivani

    Hi Jitendra,

    Its a nice tutorial. However what if WSDL file is not compatible with Salesforce? What are the options available? Can you please guide in that?

    Thanks

    • Hi Shivani,
      I would suggest to make appropriate changes to make it compatible with Salesforce. There is no thumb rule on how to achieve this, it differs as per WSDL and type of error you are getting. Other way is to use proxy webservices which will be compatible with Salesforce and source system as well or use ETL tool. As a last resort, you can use REST API and make SOAP request manually.