I am trying to read a custom dependent picklist field and update it’s field-dependencies. I have followed the common resources found online and getting the below error:
FATAL_ERROR System.CalloutException: Web service callout failed:
Unable to find apex schema infoMy MetadataService class snippet:
public class MetadataService { public class MetadataPort { /*other variables for session data here*/ public MetadataService.IReadResult readMetadata(String type_x,String[] fullNames) { MetadataService.readMetadata_element request_x = new MetadataService.readMetadata_element(); request_x.type_x = type_x; request_x.fullNames = fullNames; MetadataService.IReadResponseElement response_x; Map<String, MetadataService.IReadResponseElement> response_map_x = new Map<String, MetadataService.IReadResponseElement>(); response_map_x.put('response_x', response_x); WebServiceCallout.invoke( this, request_x, response_map_x, new String[]{endpoint_x, '', 'http://soap.sforce.com/2006/04/metadata', 'readMetadata', 'http://soap.sforce.com/2006/04/metadata', 'readMetadataResponse', 'MetadataService.read' + type_x + 'Response_element'} ); response_x = response_map_x.get('response_x'); return response_x.getResult(); } } public virtual class Metadata { public String fullName; } public class ReadCustomFieldResult implements IReadResult { public MetadataService.CustomField[] records; public MetadataService.Metadata[] getRecords() { return records; } private String[] records_type_info = new String[]{'records','http://soap.sforce.com/2006/04/metadata',null,'0','-1','false'}; private String[] apex_schema_type_info = new String[]{'http://soap.sforce.com/2006/04/metadata','true','false'}; private String[] field_order_type_info = new String[]{'records'}; } public class readCustomFieldResponse_element implements IReadResponseElement { public MetadataService.ReadCustomFieldResult result; public IReadResult getResult() { return result; } private String[] result_type_info = new String[]{'result','http://soap.sforce.com/2006/04/metadata',null,'1','1','false'}; private String[] apex_schema_type_info = new String[]{'http://soap.sforce.com/2006/04/metadata','true','false'}; private String[] field_order_type_info = new String[]{'result'}; } public interface IReadResult { MetadataService.Metadata[] getRecords(); } public interface IReadResponseElement { IReadResult getResult(); } ... /*Other dependant classes like CustomField, ValueSet etc here*/ }
Script that I am running to read the custom field:
MetadataService.MetadataPort service = new MetadataService.MetadataPort(); service.SessionHeader = new MetadataService.SessionHeader_element(); service.SessionHeader.sessionId = UserInfo.getSessionId(); service.readMetadata('CustomField', new String[]{'Account.State__c'});
The error is occurring at line:
WebServiceCallout.invoke(...);
I am guessing the response is not being parsed into
readCustomFieldResponse_element
class instance which is causing the error.The salesforce documentation is also not very clear about the process. Any help would be greatly appreciated.
UPDATE 1: Following is the response XML I am receiving from readMetadata call, retrieved using SoapUI.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/04/metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <readMetadataResponse> <result> <records xsi:type="CustomField"> <fullName>Account.State__c</fullName> <externalId>false</externalId> <label>State Name</label> <required>false</required> <trackFeedHistory>false</trackFeedHistory> <trackHistory>false</trackHistory> <type>Picklist</type> <valueSet> <controllingField>Country__c</controllingField> <restricted>true</restricted> <valueSetDefinition> <sorted>false</sorted> <value> <fullName>Canberra</fullName> <default>false</default> <label>Canberra</label> </value> <value> <fullName>Maharastra</fullName> <default>false</default> <label>Maharastra</label> </value> <value> <fullName>Sidney</fullName> <default>false</default> <label>Sidney</label> </value> <value> <fullName>West Bengal</fullName> <default>true</default> <label>West Bengal</label> </value> </valueSetDefinition> <valueSettings> <controllingFieldValue>India</controllingFieldValue> <valueName>Maharastra</valueName> </valueSettings> </valueSet> </records> </result> </readMetadataResponse> </soapenv:Body> </soapenv:Envelope>
And my classes in MetadataService:
public class ReadCustomFieldResult implements IReadResult { public MetadataService.CustomField[] records; public MetadataService.Metadata[] getRecords() { return records; } private String[] records_type_info = new String[]{'records',SOAP_M_URI,null,'0','-1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] field_order_type_info = new String[]{'records'}; } public class readCustomFieldResponse_element implements IReadResponseElement { public MetadataService.ReadCustomFieldResult result; public IReadResult getResult() { return result; } private String[] result_type_info = new String[]{'result',SOAP_M_URI,null,'1','1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] field_order_type_info = new String[]{'result'}; } public class CustomField extends Metadata{ public String fullName; public String businessOwnerGroup; public String businessOwnerUser; public String businessStatus; public Boolean caseSensitive; public String customDataType; public String defaultValue; public String deleteConstraint; public Boolean deprecated; public String description; public String displayFormat; public String encryptionScheme; public Boolean escapeMarkup; public String externalDeveloperName; public Boolean externalId; public String fieldManageability; public String formula; public String formulaTreatBlanksAs; public String inlineHelpText; public Boolean isAIPredictionField; public Boolean isConvertLeadDisabled; public Boolean isFilteringDisabled; public Boolean isNameField; public Boolean isSortingDisabled; public String label; public Integer length; public MetadataServiceBase.LookupFilter lookupFilter; public String maskChar; public String maskType; public String metadataRelationshipControllingField; public Boolean populateExistingRows; public Integer precision; public String referenceTargetField; public String referenceTo; public String relationshipLabel; public String relationshipName; public Integer relationshipOrder; public Boolean reparentableMasterDetail; public Boolean required; public Boolean restrictedAdminField; public Integer scale; public String securityClassification; public Integer startingNumber; public Boolean stripMarkup; public String summarizedField; public MetadataServiceBase.FilterItem[] summaryFilterItems; public String summaryForeignKey; public String summaryOperation; public Boolean trackFeedHistory; public Boolean trackHistory; public Boolean trackTrending; public String type_x; public Boolean unique; public MetadataServiceBase.ValueSet valueSet; public Integer visibleLines; public Boolean writeRequiresMasterRead; public Boolean displayLocationInDecimal; private String[] businessOwnerGroup_type_info = new String[]{'businessOwnerGroup',SOAP_M_URI,null,'0','1','false'}; private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'}; private String[] businessOwnerUser_type_info = new String[]{'businessOwnerUser',SOAP_M_URI,null,'0','1','false'}; private String[] businessStatus_type_info = new String[]{'businessStatus',SOAP_M_URI,null,'0','1','false'}; private String[] caseSensitive_type_info = new String[]{'caseSensitive',SOAP_M_URI,null,'0','1','false'}; private String[] customDataType_type_info = new String[]{'customDataType',SOAP_M_URI,null,'0','1','false'}; private String[] defaultValue_type_info = new String[]{'defaultValue',SOAP_M_URI,null,'0','1','false'}; private String[] deleteConstraint_type_info = new String[]{'deleteConstraint',SOAP_M_URI,null,'0','1','false'}; private String[] deprecated_type_info = new String[]{'deprecated',SOAP_M_URI,null,'0','1','false'}; private String[] description_type_info = new String[]{'description',SOAP_M_URI,null,'0','1','false'}; private String[] displayFormat_type_info = new String[]{'displayFormat',SOAP_M_URI,null,'0','1','false'}; private String[] encryptionScheme_type_info = new String[]{'encryptionScheme',SOAP_M_URI,null,'0','1','false'}; private String[] escapeMarkup_type_info = new String[]{'escapeMarkup',SOAP_M_URI,null,'0','1','false'}; private String[] externalDeveloperName_type_info = new String[]{'externalDeveloperName',SOAP_M_URI,null,'0','1','false'}; private String[] externalId_type_info = new String[]{'externalId',SOAP_M_URI,null,'0','1','false'}; private String[] fieldManageability_type_info = new String[]{'fieldManageability',SOAP_M_URI,null,'0','1','false'}; private String[] formula_type_info = new String[]{'formula',SOAP_M_URI,null,'0','1','false'}; private String[] formulaTreatBlanksAs_type_info = new String[]{'formulaTreatBlanksAs',SOAP_M_URI,null,'0','1','false'}; private String[] inlineHelpText_type_info = new String[]{'inlineHelpText',SOAP_M_URI,null,'0','1','false'}; private String[] isAIPredictionField_type_info = new String[]{'isAIPredictionField',SOAP_M_URI,null,'0','1','false'}; private String[] isConvertLeadDisabled_type_info = new String[]{'isConvertLeadDisabled',SOAP_M_URI,null,'0','1','false'}; private String[] isFilteringDisabled_type_info = new String[]{'isFilteringDisabled',SOAP_M_URI,null,'0','1','false'}; private String[] isNameField_type_info = new String[]{'isNameField',SOAP_M_URI,null,'0','1','false'}; private String[] isSortingDisabled_type_info = new String[]{'isSortingDisabled',SOAP_M_URI,null,'0','1','false'}; private String[] label_type_info = new String[]{'label',SOAP_M_URI,null,'0','1','false'}; private String[] length_type_info = new String[]{'length',SOAP_M_URI,null,'0','1','false'}; private String[] lookupFilter_type_info = new String[]{'lookupFilter',SOAP_M_URI,null,'0','1','false'}; private String[] maskChar_type_info = new String[]{'maskChar',SOAP_M_URI,null,'0','1','false'}; private String[] maskType_type_info = new String[]{'maskType',SOAP_M_URI,null,'0','1','false'}; private String[] metadataRelationshipControllingField_type_info = new String[]{'metadataRelationshipControllingField',SOAP_M_URI,null,'0','1','false'}; private String[] populateExistingRows_type_info = new String[]{'populateExistingRows',SOAP_M_URI,null,'0','1','false'}; private String[] precision_type_info = new String[]{'precision',SOAP_M_URI,null,'0','1','false'}; private String[] referenceTargetField_type_info = new String[]{'referenceTargetField',SOAP_M_URI,null,'0','1','false'}; private String[] referenceTo_type_info = new String[]{'referenceTo',SOAP_M_URI,null,'0','1','false'}; private String[] relationshipLabel_type_info = new String[]{'relationshipLabel',SOAP_M_URI,null,'0','1','false'}; private String[] relationshipName_type_info = new String[]{'relationshipName',SOAP_M_URI,null,'0','1','false'}; private String[] relationshipOrder_type_info = new String[]{'relationshipOrder',SOAP_M_URI,null,'0','1','false'}; private String[] reparentableMasterDetail_type_info = new String[]{'reparentableMasterDetail',SOAP_M_URI,null,'0','1','false'}; private String[] required_type_info = new String[]{'required',SOAP_M_URI,null,'0','1','false'}; private String[] restrictedAdminField_type_info = new String[]{'restrictedAdminField',SOAP_M_URI,null,'0','1','false'}; private String[] scale_type_info = new String[]{'scale',SOAP_M_URI,null,'0','1','false'}; private String[] securityClassification_type_info = new String[]{'securityClassification',SOAP_M_URI,null,'0','1','false'}; private String[] startingNumber_type_info = new String[]{'startingNumber',SOAP_M_URI,null,'0','1','false'}; private String[] stripMarkup_type_info = new String[]{'stripMarkup',SOAP_M_URI,null,'0','1','false'}; private String[] summarizedField_type_info = new String[]{'summarizedField',SOAP_M_URI,null,'0','1','false'}; private String[] summaryFilterItems_type_info = new String[]{'summaryFilterItems',SOAP_M_URI,null,'0','-1','false'}; private String[] summaryForeignKey_type_info = new String[]{'summaryForeignKey',SOAP_M_URI,null,'0','1','false'}; private String[] summaryOperation_type_info = new String[]{'summaryOperation',SOAP_M_URI,null,'0','1','false'}; private String[] trackFeedHistory_type_info = new String[]{'trackFeedHistory',SOAP_M_URI,null,'0','1','false'}; private String[] trackHistory_type_info = new String[]{'trackHistory',SOAP_M_URI,null,'0','1','false'}; private String[] trackTrending_type_info = new String[]{'trackTrending',SOAP_M_URI,null,'0','1','false'}; private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'}; private String[] unique_type_info = new String[]{'unique',SOAP_M_URI,null,'0','1','false'}; private String[] valueSet_type_info = new String[]{'valueSet',SOAP_M_URI,null,'0','1','false'}; private String[] visibleLines_type_info = new String[]{'visibleLines',SOAP_M_URI,null,'0','1','false'}; private String[] writeRequiresMasterRead_type_info = new String[]{'writeRequiresMasterRead',SOAP_M_URI,null,'0','1','false'}; private String[] displayLocationInDecimal_type_info = new String[]{'displayLocationInDecimal',SOAP_M_URI,null,'0','1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] field_order_type_info = new String[]{'fullName','businessOwnerGroup','businessOwnerUser','businessStatus','caseSensitive','customDataType','defaultValue','deleteConstraint','deprecated','description','displayFormat','encryptionScheme','escapeMarkup','externalDeveloperName','externalId','fieldManageability','formula','formulaTreatBlanksAs','inlineHelpText','isAIPredictionField','isConvertLeadDisabled','isFilteringDisabled','isNameField','isSortingDisabled','label','length','lookupFilter','maskChar','maskType','metadataRelationshipControllingField','populateExistingRows','precision','referenceTargetField','referenceTo','relationshipLabel','relationshipName','relationshipOrder','reparentableMasterDetail','required','restrictedAdminField','scale','securityClassification','startingNumber','stripMarkup','summarizedField','summaryFilterItems','summaryForeignKey','summaryOperation','trackFeedHistory','trackHistory','trackTrending','type_x','unique','valueSet','visibleLines','writeRequiresMasterRead','displayLocationInDecimal'}; } public virtual class Metadata { public String fullName; } public class ValueSet{ public String controllingField; public Boolean restricted; public MetadataService.ValueSetValuesDefinition valueSetDefinition; public String valueSetName; public MetadataService.ValueSettings[] valueSettings; private String[] controllingField_type_info = new String[]{'controllingField',SOAP_M_URI,null,'0','1','false'}; private String[] restricted_type_info = new String[]{'restricted',SOAP_M_URI,null,'0','1','false'}; private String[] valueSetDefinition_type_info = new String[]{'valueSetDefinition',SOAP_M_URI,null,'0','1','false'}; private String[] valueSetName_type_info = new String[]{'valueSetName',SOAP_M_URI,null,'0','1','false'}; private String[] valueSettings_type_info = new String[]{'valueSettings',SOAP_M_URI,null,'0','-1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] field_order_type_info = new String[]{'controllingField','restricted','valueSetDefinition','valueSetName','valueSettings'}; } public class ValueSetValuesDefinition { public Boolean sorted; public MetadataService.StandardValue[] value; private String[] sorted_type_info = new String[]{'sorted',SOAP_M_URI,null,'1','1','false'}; private String[] value_type_info = new String[]{'value',SOAP_M_URI,null,'0','-1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] field_order_type_info = new String[]{'sorted','value'}; } public class StandardValue extends CustomValue { public String type = 'StandardValue'; public String fullName; private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'}; public String color; public Boolean default_x; public String description; public Boolean isActive; public String label; private String[] color_type_info = new String[]{'color',SOAP_M_URI,null,'0','1','false'}; private String[] default_x_type_info = new String[]{'default',SOAP_M_URI,null,'1','1','false'}; private String[] description_type_info = new String[]{'description',SOAP_M_URI,null,'0','1','false'}; private String[] isActive_type_info = new String[]{'isActive',SOAP_M_URI,null,'0','1','false'}; private String[] label_type_info = new String[]{'label',SOAP_M_URI,null,'0','1','false'}; public Boolean allowEmail; public Boolean closed; public Boolean converted; public Boolean cssExposed; public String forecastCategory; public String groupingString; public Boolean highPriority; public Integer probability; public String reverseRole; public Boolean reviewed; public Boolean won; private String[] allowEmail_type_info = new String[]{'allowEmail',SOAP_M_URI,null,'0','1','false'}; private String[] closed_type_info = new String[]{'closed',SOAP_M_URI,null,'0','1','false'}; private String[] converted_type_info = new String[]{'converted',SOAP_M_URI,null,'0','1','false'}; private String[] cssExposed_type_info = new String[]{'cssExposed',SOAP_M_URI,null,'0','1','false'}; private String[] forecastCategory_type_info = new String[]{'forecastCategory',SOAP_M_URI,null,'0','1','false'}; private String[] groupingString_type_info = new String[]{'groupingString',SOAP_M_URI,null,'0','1','false'}; private String[] highPriority_type_info = new String[]{'highPriority',SOAP_M_URI,null,'0','1','false'}; private String[] probability_type_info = new String[]{'probability',SOAP_M_URI,null,'0','1','false'}; private String[] reverseRole_type_info = new String[]{'reverseRole',SOAP_M_URI,null,'0','1','false'}; private String[] reviewed_type_info = new String[]{'reviewed',SOAP_M_URI,null,'0','1','false'}; private String[] won_type_info = new String[]{'won',SOAP_M_URI,null,'0','1','false'}; private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'}; private String[] type_att_info = new String[]{'xsi:type'}; private String[] field_order_type_info = new String[]{'fullName','color','default_x','description','isActive','label', 'allowEmail','closed','converted','cssExposed','forecastCategory','groupingString','highPriority','probability','reverseRole','reviewed','won'}; }
Now we can see that all the elements returned in the response xml is present in the apex classes with corresponding propertyName_type_info variables. Now I am receiving
System.CalloutException: Web service callout failed: Unable to parse
callout response. Apex type not found for element fullNameHowever, my apex classes have fullName property as well as its type_info variable as well. Any idea what’s causing this issue?
Answer
This is a very similar scenario to what is occurring in Tooling API in Apex – polymorphism, generic query() callout? and is caused by an underlying limitation in Wsdl2Apex and WebServiceCallout.invoke()
.
The Metadata API readMetadata
web method returns a generic ReadResult with records of type tns:Metadata
:
<xsd:complexType name="ReadResult">
<xsd:sequence>
<xsd:element name="records" minOccurs="0" maxOccurs="unbounded" type="tns:Metadata"/>
</xsd:sequence>
</xsd:complexType>
Which is fine, except in this case you don’t get tns:Metadata
records back. You get tns:CustomField
records back that are an extension of tns:Metadata
and include a sequence of elements specific to custom fields.
WebServiceCallout.invoke
doesn’t know how to unpack the specific CustomField complex type when it was just expecting Metadata.
Instead, you need to create a classes to do this and then utilize them in a dedicated version of the readMetadata method.
It looks like you are using the apex-mdapi implementation here for readMetadata. This attempts to overcome the limitation above by passing in target metadata type with the type_x
parameter and then adjusting the final infoArray
parameter on WebServiceCallout.invoke to have a response type that matches what will come back from the WebService.
This will be a readCustomFieldResponse_element
in your case and the corresponding ReadCustomFieldResult.
This is the point where I believe the issue is. Your CustomField needs to match that of your current API version. Each element that comes back needs to have a corresponding propertyName_type_info.
Attribution
Source : Link , Question Author : Santanu Halder , Answer Author : Daniel Ballinger