Using the Tooling API to Generate Apex SOAP Web Service Clients Daniel Ballinger Senior Developer @FishOfPrey
Daniel Ballinger Senior Developer @FishOfPrey
Have you ever seen… Feature Limits Apex and Deployment No file chosen Choose File Error: Failed to parse wsdl: Unknown element: import No file chosen Choose File Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported Apex Generation Failed Unsupported WSDL. Found more than one part for message XAVRequestMessage Apex Generation Failed Unsupported schema type: {http://www.w3.org/2001/XMLSchema}anyType Apex Generation Failed The total size of apex code in this application after removing comments exceeds the maximum character size of 3000000 Apex Generation Failed Class name 'toolingSoapSforceCom' already in use. Please delete this class or specify a new class name Supported WSDL Features http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex.htm#supported_wsdls_topic-title
In This Session •The FuseIT SFDC Explorer tool • Existing Salesforce WSDL functionality •Demo custom WSDL to Apex tooling •How it was made
The FuseIT SFDC Explorer Tool – FusesFriend • Features • Windows only for the full tool • Basic web version of WSDL tooling – Session management – Schema Explorer + Tooling API – SOQL queries – Running Test Cases – Debug Log Monitoring – Data Export Retrieval – Anonymous Apex – Code Coverage – WSDL import to Apex http://www.fuseit.com/explorer
Unsupported feature Existing Wsdl2Apex Experience WSDL > 1 MB <xsd:import> <xsd:include> Existing Class Name Manually Edit WSDL Superfluous bindings Download single WSDL Generate from WSDL Upload single WSDL Namespaces to Classes Generate Apex Code Call Generated Code
Shaving the [WSDL] Yak “Yak shaving is what you are doing when you're doing some stupid, fiddly little task that bears no obvious relationship to what you're supposed to be working on, but yet a chain of twelve causal relations links what you're doing to the original meta-task.” Scott Hanselman Photo by Dennis Jarvis CC BY-SA 3.0
Demo SFDC Explorer Basic
The IT Crowd – Series 1 Episode 2: Fire!
Code Coverage Testing for Generated Code •Need to implement WebServiceMock Interface • Invoke each web service method •Handle Request and Response types •Supporting Types
Demo SFDC Explorer Web Service Mock
The Metadata API – Handling larger WSDLs Class name 'Metadata' already in use. Please edit WSDL to remove repeated names • CustomObject et al. extend Metadata and need elements from it to work correctly. <xs:extension base="Metadata"> • 330 KB WSDL Apex Character Limit Metadata 590,915 Remaining • 590,915 characters / 6740 lines without comments • Approximately 20% of 3,000,000 character Apex limit
Method filtering functionality •Reduces amount of generated code •Reduces testing requirements for dead code • Potentially skips unsupported features • Optionally remove supporting Apex classes
Demo SFDC Explorer Method filtering
How it works Deploy to Salesforce • Tooling API to deploy all associated Apex classes at once Transform to Apex • T4 (Text Template Transformation Toolkit)Templates to convert the object model into Apex Build Apex Model • C# Object Model of Apex Classes, Members and Methods Parse WSDL • Import all WSDL data and extract required elements
.NET Representation of Apex Class model ApexClass public class ListMetadataQuery { public String folder; public String type_x; private String[] folder_type_info = new String[]{'folder','http://soap.sforce.com/2006/04/metadata','string','0','1','false'}; private String[] type_x_type_info = 1 InnerApexClasses * Members * Methods new String[]{'type','http://soap.sforce.com/2006/04/metadata','string','1','1','false'}; private String[] apex_schema_type_info = ApexClassCollection ApexMember new String[]{'http://soap.sforce.com/2006/04/metadata','true','false'}; private String[] field_order_type_info = new String[]{'folder','type_x'}; StringArrayApexMember ApexMethod ApexMethodParameter ApexMethodHttp ReturnType ReturnVoid ReturnPrimitive ReturnClassType Type Infos Inner Classes Namespace Collection Parameters * ReturnType 1 ApexClasses 0..* Outer class for each Namespace Created for the Port/Service Each Request/Response public class soapSforceCom200604Metadata { public class CallOptions_element { // ... } // ... public class MetadataPort { // ... public fp[] listMetadata(lmq[] q,Double asOfVersion) { // ... } } public class SessionHeader_element { // ... } } }
Tooling API deployment Existing ID • Create a MetadataContainer with a unique name • Create a collection of ApexClassMember referencing the MetadataContainerId • Create a ContainerAsyncRequest var cr = new ContainerAsyncRequest(); cr.MetadataContainerId = New – no existing ID • Call create and collect the SaveResults • Or create an empty stub class to get an MIeDta adantda Cuosntea ithneer McoenttaadianetarC=onnetwaiMneetradataContainer(); List<ApexClass> apexClassesToInsert = new List<ApexClass>(); // Add ApexClass records with T4 generated Body ApexClass classToInsert = new ApexClass() { Name = "HelloDF" }; classToInsert.Body = "public class " + classToInsert.Name + " { public class Add{ }}"; apexClasses.Add(classToInsert); – Option to Validate Only (IsCheckOnly) • Keep retrieving until the State is no longer Queued. • Delete MetadataContainer toUpdate = new List<ApexClassMember>(); foreach(ApexClass ac in classesToUpsert) { var acm = new ApexClassMember(); acm.ContentEntityId = ac.Id; // 01p… acm.Body = ac.Body; // T4 Template output acm.FullName = ac.Name; // class name acm.MetadataContainerId = metadataContainerId.CaseSafeID; // toUpdate.max length Add(acm); 32 characters! container.Name = "UAC " + DateTime.Now.Ticks; SaveResult[] containerResults = toolingService.create(new sObject[] { container }); if (!containerResults[0].success) { SaveResult[] saveResults = toolingService.create(apexClassesToInsert.ToArray()); if (saveResults != null) { throw new ToolingCreateException(container, containerResults[0]); } foreach (SaveResult sr in saveResults) { if (!sr.success) { throw new ToolingCreateException(apexClassesToInsert.ToArray(), saveResults); Id metadataContainerId = new Id(containerResults[0].id); } sObject[] toCreate = toUpdate.ToArray(); SaveResult[] cResult = toolingService.create(apexClassMembersToCreate); foreach (SaveResult sr in cResult) { if (!sr.success) { throw new ToolingCreateException(toCreate, cResult); } } metadataContainerId.CaseSafeID; cr.IsCheckOnly = false; SaveResult[] cars = this.create(new sObject[]{cr}); if (! cars[0].success) { throw new ToolingCreateException(cr,cars[0]); } ContainerAsyncRequest retrieve = WaitForClassToUpdate(containerAsyncResults); if (retrieve.State == "Failed") { throw ApexUpdateException.FromDeployDetails (retrieve.DeployDetails); } DeleteResult[] dr = this.delete(new string[] { metadataContainerId.CaseSafeID }); } } }
WSDL Variation http://www.superbwallpapers.com/photography/snowflakes-10358/ If you have a unique WSDL: • http://www.fuseit.com/wsdlhelp • Please provide the WSDL details
Summary •Manually dealing with WSDL import errors is time consuming and error prone • Extended SOAP support for several common WSDL issues: – Increased support – <xsd:import> <xsd:include> <xsd:extension> – Generate basic code coverage – Method filtering to reduce Apex
Q&A + What Next • Download: the free FuseIT SFDC Explorer Tool (or get the web version) http://www.fuseit.com/explorer • Idea: Run anonymous apex as if it were a test case http://goo.gl/Aci1ys • Salesforce: The now open source WSDL2Apex generator http://goo.gl/tUcnVj • Session: Building Callouts Without WSDL2Apex and Apex Parsers Tuesday, 4:00 PM - 4:30 PM | Moscone Center West | Mobile Theater www.fuseit.com @FishOfPrey www.fishofprey.com @GirishaArora Girisha Arora
Show Flow Dreamforce 2104 Breakout Session Show Flow Template Notes Session Title 1:30pm session Presentation Device: Laptop with HDMI out Customer Speaker: Daniel Ballinger Salesforce Speakers: n/a Demo Device Demo Driver: Deck Owner/Filename: 1:15 PM Doors open 1:30 PM Start :01 Welcome and Intros :03 Overview of topic - Common WSDL2Apex errors, things we'll cover :05 Introduce the FuseIT SFDC Explorer Tool :09 Existing Wsdl2Apex flow Run through current process - devs goal isn't to be editing WSDLs :13 Demo - Importing a WSDL to Apex basic example :15 The need manually do code coverage for generated code :19 Demo - Generating WebServiceMock and Code Coverage :21 Dealing with big WSDLS - Metadata API :25 Demo - Selective Metadata methods. Anon call sample :28 How it works - High level steps + Apex Class model :30 How it works - Tooling API Deployment :32 Demo - Tooling API code sample :34 Summary – recap what was covered :39 Q&A :39 Wrap-up, Thank yous and Close :40 Walking off Stage
Bonus Slides
Handling Extensions • <xsd:extension base=“”/> • Copy fields from base type to the sub class. • Use extends in the future • Metadata API • AccountOwnerSharingRule extends • OwnerSharingRule extends • BaseSharingRule extends • Metadata
HTTP Requests • When WebServiceCallout.invoke() fails • A template for supporting more complex callouts • Access full fault messages SOAPFault Information for Apex https://success.salesforce.com/ideaView?id=08730000000BqG9AAK
Apex Class Drifting with WSDL changes

Using the Tooling API to Generate Apex SOAP Web Service Clients

  • 1.
    Using the ToolingAPI to Generate Apex SOAP Web Service Clients Daniel Ballinger Senior Developer @FishOfPrey
  • 2.
    Daniel Ballinger SeniorDeveloper @FishOfPrey
  • 3.
    Have you everseen… Feature Limits Apex and Deployment No file chosen Choose File Error: Failed to parse wsdl: Unknown element: import No file chosen Choose File Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported Apex Generation Failed Unsupported WSDL. Found more than one part for message XAVRequestMessage Apex Generation Failed Unsupported schema type: {http://www.w3.org/2001/XMLSchema}anyType Apex Generation Failed The total size of apex code in this application after removing comments exceeds the maximum character size of 3000000 Apex Generation Failed Class name 'toolingSoapSforceCom' already in use. Please delete this class or specify a new class name Supported WSDL Features http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex.htm#supported_wsdls_topic-title
  • 4.
    In This Session •The FuseIT SFDC Explorer tool • Existing Salesforce WSDL functionality •Demo custom WSDL to Apex tooling •How it was made
  • 5.
    The FuseIT SFDCExplorer Tool – FusesFriend • Features • Windows only for the full tool • Basic web version of WSDL tooling – Session management – Schema Explorer + Tooling API – SOQL queries – Running Test Cases – Debug Log Monitoring – Data Export Retrieval – Anonymous Apex – Code Coverage – WSDL import to Apex http://www.fuseit.com/explorer
  • 6.
    Unsupported feature ExistingWsdl2Apex Experience WSDL > 1 MB <xsd:import> <xsd:include> Existing Class Name Manually Edit WSDL Superfluous bindings Download single WSDL Generate from WSDL Upload single WSDL Namespaces to Classes Generate Apex Code Call Generated Code
  • 7.
    Shaving the [WSDL]Yak “Yak shaving is what you are doing when you're doing some stupid, fiddly little task that bears no obvious relationship to what you're supposed to be working on, but yet a chain of twelve causal relations links what you're doing to the original meta-task.” Scott Hanselman Photo by Dennis Jarvis CC BY-SA 3.0
  • 8.
  • 9.
    The IT Crowd– Series 1 Episode 2: Fire!
  • 10.
    Code Coverage Testingfor Generated Code •Need to implement WebServiceMock Interface • Invoke each web service method •Handle Request and Response types •Supporting Types
  • 11.
    Demo SFDC ExplorerWeb Service Mock
  • 12.
    The Metadata API– Handling larger WSDLs Class name 'Metadata' already in use. Please edit WSDL to remove repeated names • CustomObject et al. extend Metadata and need elements from it to work correctly. <xs:extension base="Metadata"> • 330 KB WSDL Apex Character Limit Metadata 590,915 Remaining • 590,915 characters / 6740 lines without comments • Approximately 20% of 3,000,000 character Apex limit
  • 13.
    Method filtering functionality •Reduces amount of generated code •Reduces testing requirements for dead code • Potentially skips unsupported features • Optionally remove supporting Apex classes
  • 14.
    Demo SFDC ExplorerMethod filtering
  • 15.
    How it works Deploy to Salesforce • Tooling API to deploy all associated Apex classes at once Transform to Apex • T4 (Text Template Transformation Toolkit)Templates to convert the object model into Apex Build Apex Model • C# Object Model of Apex Classes, Members and Methods Parse WSDL • Import all WSDL data and extract required elements
  • 16.
    .NET Representation ofApex Class model ApexClass public class ListMetadataQuery { public String folder; public String type_x; private String[] folder_type_info = new String[]{'folder','http://soap.sforce.com/2006/04/metadata','string','0','1','false'}; private String[] type_x_type_info = 1 InnerApexClasses * Members * Methods new String[]{'type','http://soap.sforce.com/2006/04/metadata','string','1','1','false'}; private String[] apex_schema_type_info = ApexClassCollection ApexMember new String[]{'http://soap.sforce.com/2006/04/metadata','true','false'}; private String[] field_order_type_info = new String[]{'folder','type_x'}; StringArrayApexMember ApexMethod ApexMethodParameter ApexMethodHttp ReturnType ReturnVoid ReturnPrimitive ReturnClassType Type Infos Inner Classes Namespace Collection Parameters * ReturnType 1 ApexClasses 0..* Outer class for each Namespace Created for the Port/Service Each Request/Response public class soapSforceCom200604Metadata { public class CallOptions_element { // ... } // ... public class MetadataPort { // ... public fp[] listMetadata(lmq[] q,Double asOfVersion) { // ... } } public class SessionHeader_element { // ... } } }
  • 17.
    Tooling API deployment Existing ID • Create a MetadataContainer with a unique name • Create a collection of ApexClassMember referencing the MetadataContainerId • Create a ContainerAsyncRequest var cr = new ContainerAsyncRequest(); cr.MetadataContainerId = New – no existing ID • Call create and collect the SaveResults • Or create an empty stub class to get an MIeDta adantda Cuosntea ithneer McoenttaadianetarC=onnetwaiMneetradataContainer(); List<ApexClass> apexClassesToInsert = new List<ApexClass>(); // Add ApexClass records with T4 generated Body ApexClass classToInsert = new ApexClass() { Name = "HelloDF" }; classToInsert.Body = "public class " + classToInsert.Name + " { public class Add{ }}"; apexClasses.Add(classToInsert); – Option to Validate Only (IsCheckOnly) • Keep retrieving until the State is no longer Queued. • Delete MetadataContainer toUpdate = new List<ApexClassMember>(); foreach(ApexClass ac in classesToUpsert) { var acm = new ApexClassMember(); acm.ContentEntityId = ac.Id; // 01p… acm.Body = ac.Body; // T4 Template output acm.FullName = ac.Name; // class name acm.MetadataContainerId = metadataContainerId.CaseSafeID; // toUpdate.max length Add(acm); 32 characters! container.Name = "UAC " + DateTime.Now.Ticks; SaveResult[] containerResults = toolingService.create(new sObject[] { container }); if (!containerResults[0].success) { SaveResult[] saveResults = toolingService.create(apexClassesToInsert.ToArray()); if (saveResults != null) { throw new ToolingCreateException(container, containerResults[0]); } foreach (SaveResult sr in saveResults) { if (!sr.success) { throw new ToolingCreateException(apexClassesToInsert.ToArray(), saveResults); Id metadataContainerId = new Id(containerResults[0].id); } sObject[] toCreate = toUpdate.ToArray(); SaveResult[] cResult = toolingService.create(apexClassMembersToCreate); foreach (SaveResult sr in cResult) { if (!sr.success) { throw new ToolingCreateException(toCreate, cResult); } } metadataContainerId.CaseSafeID; cr.IsCheckOnly = false; SaveResult[] cars = this.create(new sObject[]{cr}); if (! cars[0].success) { throw new ToolingCreateException(cr,cars[0]); } ContainerAsyncRequest retrieve = WaitForClassToUpdate(containerAsyncResults); if (retrieve.State == "Failed") { throw ApexUpdateException.FromDeployDetails (retrieve.DeployDetails); } DeleteResult[] dr = this.delete(new string[] { metadataContainerId.CaseSafeID }); } } }
  • 18.
    WSDL Variation http://www.superbwallpapers.com/photography/snowflakes-10358/ If you have a unique WSDL: • http://www.fuseit.com/wsdlhelp • Please provide the WSDL details
  • 19.
    Summary •Manually dealingwith WSDL import errors is time consuming and error prone • Extended SOAP support for several common WSDL issues: – Increased support – <xsd:import> <xsd:include> <xsd:extension> – Generate basic code coverage – Method filtering to reduce Apex
  • 20.
    Q&A + WhatNext • Download: the free FuseIT SFDC Explorer Tool (or get the web version) http://www.fuseit.com/explorer • Idea: Run anonymous apex as if it were a test case http://goo.gl/Aci1ys • Salesforce: The now open source WSDL2Apex generator http://goo.gl/tUcnVj • Session: Building Callouts Without WSDL2Apex and Apex Parsers Tuesday, 4:00 PM - 4:30 PM | Moscone Center West | Mobile Theater www.fuseit.com @FishOfPrey www.fishofprey.com @GirishaArora Girisha Arora
  • 22.
    Show Flow Dreamforce2104 Breakout Session Show Flow Template Notes Session Title 1:30pm session Presentation Device: Laptop with HDMI out Customer Speaker: Daniel Ballinger Salesforce Speakers: n/a Demo Device Demo Driver: Deck Owner/Filename: 1:15 PM Doors open 1:30 PM Start :01 Welcome and Intros :03 Overview of topic - Common WSDL2Apex errors, things we'll cover :05 Introduce the FuseIT SFDC Explorer Tool :09 Existing Wsdl2Apex flow Run through current process - devs goal isn't to be editing WSDLs :13 Demo - Importing a WSDL to Apex basic example :15 The need manually do code coverage for generated code :19 Demo - Generating WebServiceMock and Code Coverage :21 Dealing with big WSDLS - Metadata API :25 Demo - Selective Metadata methods. Anon call sample :28 How it works - High level steps + Apex Class model :30 How it works - Tooling API Deployment :32 Demo - Tooling API code sample :34 Summary – recap what was covered :39 Q&A :39 Wrap-up, Thank yous and Close :40 Walking off Stage
  • 23.
  • 24.
    Handling Extensions •<xsd:extension base=“”/> • Copy fields from base type to the sub class. • Use extends in the future • Metadata API • AccountOwnerSharingRule extends • OwnerSharingRule extends • BaseSharingRule extends • Metadata
  • 25.
    HTTP Requests •When WebServiceCallout.invoke() fails • A template for supporting more complex callouts • Access full fault messages SOAPFault Information for Apex https://success.salesforce.com/ideaView?id=08730000000BqG9AAK
  • 26.
    Apex Class Driftingwith WSDL changes

Editor's Notes

  • #2 Using the Tooling API to Generate Apex SOAP Web Service Clients Extending the capabilities of WSDL2apex
  • #3 Nelson Since 2007 Active on Salesforce StackExchange Integration with SOAP based web services lead to this talk. Tools needed for repeatedly handling SOAP based web services. FuseIT – ISV Partner Sitecore CMS HP TRIM
  • #4 Some of the errors you might encounter when generating Apex code for from a WSDL http://www.fuseit.com/Solutions/SFDC-Explorer/WSDL-Parsing-Errors.aspx Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported Error: Failed to parse wsdl: Found more than one wsdl:portType. WSDL with multiple portType not supported Failed to parse wsdl: Failed to parse WSDL: Unable to find binding Error: Failed to parse wsdl: Found schema import. External schema import not supported Apex Generation Failed Unable to find schema for element Error: Failed to parse wsdl: type not specified for attribute Apex Generation Failed: No type specified for element Error: need to modify WSDL with import tags or include tags Enterprise wsdl error: Unsupported schema type: {http://www.w3.org/2001/XMLSchema}anyType
  • #5 Overview of what the FuseIT SFDC Explorer tool is. First step is a quick review of the existing functionality and highlighting some of the limitations therein. Provides a  grounding for comparison. A walkthrough of the free tool we have built. To make working with SOAP based Web Services easier.    Avoid the need to manipulate the WSDL before importing into Salesforce  Improve support for WSDL features  Reduce the amount of generated code that isn't otherwise used.  Provide basic code coverage for the generated code so you don't have to.  Use the existing Salesforce WebServiceCallout.invoke where possible  Optionally support direct HTTP requests    Built out of necessity when dealing with an evolving webservice.
  • #6 Fuses Friend Note that this is not a full IDE replacement tool. Intended to be supplementary to existing tools such as Mavens Mate and the Developer Console. Built both as a test bed for G4S functionality and as a tool for day to day development needs. Free as in free beer.
  • #7 Run through the steps using the existing built in tool: Support for importing another WSDL <wsdl:import> (different namespace) or schema <xsd:include> (same namespace). Requires a single complete WSDL  Pain of trying to manually stitch the WSDL into one file. Removing extra SOAP 1.2 bindings that won’t be used. Note the 1MB file limit. Time consuming to manually prune the file size down. Don't want to be handling a WSDL with frequent changes. Reading a 1MB xml file isn’t much fun. a megabyte of data can roughly be - a typical English book volume in plain text format (500 pages × 2000 characters per page)
  • #8 Time spent manipulating the WSDL so you can call the web service from Apex Installing tooling to manipulate complex XML documents, Creating XSDs Researching the differences between SOAP 1.1 and 1.2 http://xkcd.com/974/
  • #9 Callout the actual error. Quick sample call against Salesforce with the same WSDL Import the unmodified WSDL using SFDC Explorer. Show that the UPSSecurity_hns is correctly generated. Don't generate the test classes at this stage.
  • #10 http://www.channel4.com/programmes/the-it-crowd Generated hundreds or thousands lines of code in seconds Now before we can deploy or package that code we need to write test cases to at the minimum ensure code coverage.
  • #11 Avoid writing basic code to test code that was generated.
  • #12 Generate Test classes Run test classes directly after deployment. Partner API – 3000+ lines of apex Anonymous Apex Code for Partner API: partnerSoapSforceCom.Soap partnerAPI = new partnerSoapSforceCom.Soap(); partnerAPI.SessionHeader = new partnerSoapSforceCom.SessionHeader_element(); partnerAPI.SessionHeader.sessionId = UserInfo.getSessionId(); partnerAPI.endpoint_x = URL.getSalesforceBaseUrl().toExternalForm() + '/services/Soap/u/31.0'; partnerSoapSforceCom.QueryResult qr = partnerAPI.query('select Id from Account limit 1'); System.debug(qr);
  • #13 171 cases of <xsd:extension base”…”>  (excluding comments and @isTest annotated classes) Size Without Comments: 590,915 characters – 6740 lines Org limited to 3,000,000 characters v31.0 Summer 14 One fifth of available Apex character used before it is called or tested! Note the character count exceeds the quoted 100,000 limit from the docs. Acknowledge existence of Andrew Fawcett's Apex Wrapper Salesforce Metadata API. It's more about the exercise than the end result. 
  • #14 Option to
  • #15 CSV of generated methods. Listed in the generated classes for future regens. Option to exclude or comment out unreferenced code Use csv to define the methods to generate for.  Actively filter the list of methods to generate.  Choose if you also want to generate additional http requests.  View the return types.  soapSforceCom200604Metadata.MetadataPort service = new soapSforceCom200604Metadata.MetadataPort(); service.SessionHeader = new soapSforceCom200604Metadata.SessionHeader_element(); service.SessionHeader.sessionId = UserInfo.getSessionId(); service.endpoint_x = URL.getSalesforceBaseUrl().toExternalForm() + '/services/Soap/m/31.0'; System.debug(service.endpoint_x); List<soapSforceCom200604Metadata.ListMetadataQuery> queries = new List<soapSforceCom200604Metadata.ListMetadataQuery>(); soapSforceCom200604Metadata.ListMetadataQuery queryWorkflow = new soapSforceCom200604Metadata.ListMetadataQuery(); queryWorkflow.type_x = 'Workflow'; queries.add(queryWorkflow); soapSforceCom200604Metadata.ListMetadataQuery queryValidationRule = new soapSforceCom200604Metadata.ListMetadataQuery(); queryValidationRule.type_x = 'ValidationRule'; queries.add(queryValidationRule); double asOfVersion = 31.0; soapSforceCom200604Metadata.FileProperties[] fileProperties = service.listMetadata(queries, asOfVersion); for(soapSforceCom200604Metadata.FileProperties fileProperty : fileProperties) { System.debug(fileProperty.fullName); }
  • #16 Parse WSDL imports and includes. Apex Model in C# classes T4 Transform Model into Apex Classes Deploy using the Tooling API Compiled code that generates Apex code.
  • #17 Outer classes represent the namespace. Inner classes the service proxy and the request/response types. String [] members for the _type_info arguments for Web Service Invoke. Param_type_info - XML Element Name, Namespace, XML Base Type, min, max, nillable Apex_schema_type_info – Namespace, 'true' if elementFormDefault="qualified" , 'true' if attributeFormDefault="qualified" TODO: Improve visibility on projector. Fine lines and Text.
  • #18 Don’t really have the concept of an upsert for an Apex Class. Outline the advantage of putting all the apex classes in one go for dependencies. Deploy all at once. Brief Description of how the Tooling API is used to deploy multiple Apex classes in one go to allow for dependencies. Validate only for existing Apex classes
  • #19 Each new WSDL seems to have a unique way of applying the spec. Share your WSDLs with us to improve support Not a silver bullet solution. Can’t fix invalid XML or handle missing elements. There are features that WebServiceCallout.invoke can’t handle and will require HTTP callouts instead.
  • #20 <xsd:extension base=“”/> Copy fields from base type to the sub class. Increase WSDL support – import/include/extension Generate basic Code Coverage Method filtering to reduce Apex characters <xsd:import> - namespace <xsd:include> - schema <xsd:extension> - inheritance Unsupported PortTypes/Bindings Generated Code Coverage Reserved Keywords Source WSDL > 1 MB CalloutException fault response
  • #21 G4S as a freely available tool for working against developer edition orgs. http://www.fuseit.com/en/Solutions/G4S.aspx
  • #25 Meta Data API. AccountOwnerSharingRule <xsd:extension base="tns:OwnerSharingRule"> <xsd:extension base="tns:BaseSharingRule"> <xsd:extension base="tns:Metadata">
  • #26 soapSforceComSchemasClassExamplefau.ExampleFaultWebServices service = new soapSforceComSchemasClassExamplefau.ExampleFaultWebServices(); service.SessionHeader = new soapSforceComSchemasClassExamplefau.SessionHeader_element(); service.SessionHeader.sessionId = UserInfo.getSessionId(); string result = service.basicStringMethod('hello'); soapSforceComSchemasClassExamplefau.ExampleFaultWebServices service = new soapSforceComSchemasClassExamplefau.ExampleFaultWebServices(); service.SessionHeader = new soapSforceComSchemasClassExamplefau.SessionHeader_element(); service.SessionHeader.sessionId = UserInfo.getSessionId(); //string result = service.basicStringMethod('hello'); string result = service.basicStringMethod_Http('hello');
  • #27 Small changes in the WSDL can cause generated classes to change ordering. Makes finding the actual changes harder. Handled by Sorting generated Apex Classes by name Wsdl sorting for source control. The native Wsdl2Apex generator can generate with vastly different ordering from WSDL changes. V30 to v31. Spring to Summer 2014