function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jon Mountjoy_Jon Mountjoy_ 

Calling a web service (aka SOA) always fails (not security)

Hi

I'm calling my own SOAP web service and it always fails with:

Web service callout failed: Unable to parse callout response. Apex type not found for element =gah

It's a simple web service, with one operation, getInfo, returning a String.  I've added the WSDL below.
I "generate code from WSDL" (code also attached below) and call this code, which then fails. (The code generated fine).

The error occurs when I subsequently execute the code. ie.

Contactz11.ContactInfoImplPort c = new Contactz11.ContactInfoImplPort();
String r = c.getInfo();

This does actually call the SOAP service (I see that in my server log).  The problem appears to be in Apex's conversion of the resulting String.

Any advice gratefully accepted...

Jon


Here's the generated Apex Code:
//Generated by wsdl2apex

public class Contactz11 {
public class getInfo {
private String[] apex_schema_type_info = new String[]{'http://ws.memestorm.com/','false'};
private String[] field_order_type_info = new String[]{};
}
public class ContactInfoImplPort {
public String endpoint_x = 'http://memestorm.dyndns.org:8080/contactz';
private String[] ns_map_type_info = new String[]{'http://ws.memestorm.com/', 'Contactz11'};
public String getInfo() {
Contactz11.getInfo request_x = new Contactz11.getInfo();
Contactz11.getInfoResponse response_x;
Map<String, Contactz11.getInfoResponse> response_map_x = new Map<String, Contactz11.getInfoResponse>();
response_map_x.put('response_x', response_x);
WebServiceCallout.invoke(
this,
request_x,
response_map_x,
new String[]{endpoint_x,
'',
'http://ws.memestorm.com/',
'getInfo',
'http://ws.memestorm.com/',
'getInfoResponse',
'Contactz11.getInfoResponse'}
);
response_x = response_map_x.get('response_x');
return response_x.gah;
}
}
public class getInfoResponse {
public String gah;
private String[] gah_type_info = new String[]{'gah','http://www.w3.org/2001/XMLSchema','string','0','1','false'};
private String[] apex_schema_type_info = new String[]{'http://ws.memestorm.com/','false'};
private String[] field_order_type_info = new String[]{'gah'};
}
}


Here's the WSDL:

<?xml version="1.0" encoding="utf-8"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://ws.memestorm.com/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ContactService" targetNamespace="http://ws.memestorm.com/">
  <wsdl:types>
<xsd:schema xmlns="http://ws.memestorm.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://ws.memestorm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="getInfo" type="getInfo"/>
<xsd:complexType name="getInfo">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="getInfoResponse" type="getInfoResponse"/>
<xsd:complexType name="getInfoResponse">
<xsd:sequence>
<xsd:element minOccurs="0" name="gah" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
  </wsdl:types>
  <wsdl:message name="getInfo">
    <wsdl:part element="ns1:getInfo" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getInfoResponse">
    <wsdl:part element="ns1:getInfoResponse" name="result">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="ContactInfo">
    <wsdl:operation name="getInfo">
      <wsdl:input message="ns1:getInfo" name="getInfo">
    </wsdl:input>
      <wsdl:output message="ns1:getInfoResponse" name="getInfoResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ContactServiceSoapBinding" type="ns1:ContactInfo">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getInfo">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="getInfo">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getInfoResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ContactService">
    <wsdl:port binding="ns1:ContactServiceSoapBinding" name="ContactInfoImplPort">
      <soap:address location="http://memestorm.dyndns.org:8080/contactz"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Best Answer chosen by Admin (Salesforce Developers) 
wesnoltewesnolte

And generating Apex code from the metadata API and including it in my Force.com IDE eclipse project will give me Apex based access to the metadata right?

 

Specifically I'm looking to dynamically update label - value pairs in picklists.

All Answers

MyGodItsColdMyGodItsCold
Can you tell me where

wsdl2apex

is?

Jon Mountjoy_Jon Mountjoy_
Hi

If you go to Setup/Build/Code which lists your Apex objects, you can simply hit
"Generate from WSDL" which will guide you through a WSDL upload and generate the Apex for you.

Jon

PS. (It's cold here too)
MyGodItsColdMyGodItsCold

I have a 456K WSDL. When I try to generate APEX, it says:

Error: sobjectEnterpriseSoapSforceCom

Error: Script too large: //Generated by wsdl2apex

I'll try the Partner WSDL.

MyGodItsColdMyGodItsCold
Never mind. I think I got it. Instead of either Enterprise or Partner WSDL, I choose APEX WSDL to download (from Setup | Integrate | API) - that came down as 'apex.xml'. Then when I chose the button Generate code from WSDL, I pointed it to the apex.xml I had saved on my PC. It created a class for me which compiled successfully. Now, I'll plow in to it & see if I can program all I need to.
MyGodItsColdMyGodItsCold

No, this isn't it. I'm hoping I can use the Enterprise WSDL to generate APEX code so I can call our salesforce API to do an update with more than 99 contacts.

Do you know if such a thing is possible? I know we have an internal Java program that's doing that, and I know that APEX is allowed to consume web services? Can't we consume ourselves (sic)...? We could call this the Cannibal approach to Web 2.0 - better than the Mythical Man Month?

SuperfellSuperfell
No, you can't call the salesforce.com Web Services API from Apex code.
MyGodItsColdMyGodItsCold
Great. So, I write a web service that acts as an intermediary?
SuperfellSuperfell
Sure, but remember that you can't make callouts during a trigger.
MyGodItsColdMyGodItsCold
OK. So, if i'm in a trigger, and I want to update all the contacts for an account, and there are more than the allowable number, what do i do to get them updated, and where is an example of doing so - all I've come accross so far is Cookbook, page 74-5 is to message the user that they're trying to update too many accounts, or an account with too many contacts.... So, what's a user to do? What am I the developer to do?
 
SuperfellSuperfell
If you have data on account that applies to every single contact, then surely the best place to leave it is on account, and not try to push it down to every contact.

Perhaps you can explain why you need to update every contact when the account gets updated.
PreussenBlauPreussenBlau

I would agree with you in theory.  But we're trying to give our users more functionality.  Our contact views are not sufficient for our users due to the fact that they are based solely on the contact owner.  We want to add a custom Account Team field to the contact and reference that field in views to provide greater functionality.  Yes, users can be instructed to use reports albeit there are still constraints there as well.  But our users are accustomed to working with views and it seems a waste to have the views when they're not fully functional.  Here's some of the data that we want to propagate to a contact from an account and sometimes from the parent account in particular. 

Account Team Members (custom field set via API update)

Address fields (enrich the contact views by referencing state codes, ehance material orders)

Various Opt Out fields (email, mail, etc. allowing users to set these fields at the parent and/or account)

Account Mail Owner (the sales person referenced in mailings)

This data will provide greater functionality in the following ways:

1)  Enrich our contact views and allow users to see important information directly on the contact.

2)  Provide better reporting in particular for Marketing mailings. 

3)  Improve the functionality for material ordering (custom object) that is tied closely to the contact.

NareshNaresh
Hi,
I am having the same issue. I am getting the following error:
"Web service callout failed: Unable to parse callout response. Apex type not found for element http://www.serviceobjects.com/=Desc"

Please post me if you get any solution.

Thanks in advance!

NG
SuperfellSuperfell
This means the response XML includes an xml element that was not defined in the WSDL (i.e. your runtime message does not conform to the WSDL contract). SOAP diagnostics tools like SOAPScope can help you check that the SOAP messages do match what the WSDL says they would look like, one common problem is that the schema defines elementFormDefault="qualified" but the messages are not namespace qualified (or visa versa).
MyGodItsColdMyGodItsCold

But I'm assuming your previous statement:

No, you can't call the salesforce.com Web Services API from Apex code

is still true, right?

(btw, I've found that "soapUI" can track some things I couldn't with the version of SOAPScope I was using - could just have been a matter of feature mismatch...).

wesnoltewesnolte

I think I found it at

 

setup > develop > apex classes

 

And hit the button 'Generate from WSDL'?

Jon Mountjoy_Jon Mountjoy_
Yes wesnolte, that's how you generate Apex classes for the platform - given some WSDL that describes a web service that you want to invoke.
wesnoltewesnolte

And generating Apex code from the metadata API and including it in my Force.com IDE eclipse project will give me Apex based access to the metadata right?

 

Specifically I'm looking to dynamically update label - value pairs in picklists.

This was selected as the best answer
Jon Mountjoy_Jon Mountjoy_

Ah, now there you are doing something slightly different.  You're wanting to invoke the platform from the platform.  As I think SimonF noted earlier in this thread, you can't call the salesforce.com web services API from Apex.

 

It might be worth starting a new thread to figure out if you can accomplish your goals using some other mechanism though.

wesnoltewesnolte
Will do. Thanks.