26
Using the Tooling API to Generate Apex SOAP Web Service Clients Daniel Ballinger Senior Developer @FishOfPrey

Using the Tooling API to Generate Apex SOAP Web Service Clients

Embed Size (px)

DESCRIPTION

Join us as we review the capabilities of the existing WSDL-to-Apex code generation feature, and explain how we built a tool to provide expanded features using the Tooling API. The resulting tool has greater support for more WSDL features, generates test cases and the associated mocks to maximize code coverage, and optionally includes HttpRequest versions of the callouts.

Citation preview

Page 1: Using the Tooling API to Generate Apex SOAP Web Service Clients

Using the Tooling API to Generate Apex SOAP Web Service ClientsDaniel Ballinger

Senior Developer

@FishOfPrey

Page 2: Using the Tooling API to Generate Apex SOAP Web Service Clients

Daniel BallingerSenior Developer @FishOfPrey

Page 3: Using the Tooling API to Generate Apex SOAP Web Service Clients

Have you ever seen…

Supported WSDL Featureshttp://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex.htm#supported_wsdls_topic-title

Feature Limits

Apex and Deployment

Apex Generation FailedThe total size of apex code in this application after removing comments exceeds the maximum character size of 3000000

Apex Generation FailedClass name 'toolingSoapSforceCom' already in use. Please delete this class or specify a new class name

Apex Generation FailedUnsupported schema type: {http://www.w3.org/2001/XMLSchema}anyType

Apex Generation FailedUnsupported WSDL. Found more than one part for message XAVRequestMessage

No file chosen

Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported

Choose File

No file chosen

Error: Failed to parse wsdl: Unknown element: import

Choose File

Page 4: Using the Tooling API to Generate Apex SOAP Web Service Clients

In This Session• The FuseIT SFDC Explorer tool

• Existing Salesforce WSDL functionality

• Demo custom WSDL to Apex tooling

• How it was made

Page 5: Using the Tooling API to Generate Apex SOAP Web Service Clients

• Windows only for the full tool• Basic web version of WSDL tooling

The FuseIT SFDC Explorer Tool – FusesFriend• Features

– 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

FREE

Page 6: Using the Tooling API to Generate Apex SOAP Web Service Clients

Unsupported feature

WSDL > 1 MB

<xsd:import><xsd:include>

Existing Class Name

Manually Edit WSDL

Superfluous bindings

Existing Wsdl2Apex Experience

Download single WSDL

Generate from WSDL

Upload single WSDL

Namespaces to Classes

Generate Apex Code

Call Generated

Code

Page 7: Using the Tooling API to Generate Apex SOAP Web Service Clients

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

Page 8: Using the Tooling API to Generate Apex SOAP Web Service Clients

Demo SFDC Explorer Basic

Page 9: Using the Tooling API to Generate Apex SOAP Web Service Clients

CodeCoverage

The IT Crowd – Series 1 Episode 2: Fire!

Page 10: Using the Tooling API to Generate Apex SOAP Web Service Clients

Code Coverage Testing for Generated Code• Need to implement WebServiceMock Interface

• Invoke each web service method

• Handle Request and Response types

• Supporting Types

Page 11: Using the Tooling API to Generate Apex SOAP Web Service Clients

Demo SFDC Explorer Web Service Mock

Page 12: Using the Tooling API to Generate Apex SOAP Web Service Clients

Class name 'Metadata' already in use. Please edit WSDL to remove repeated names

The Metadata API – Handling larger WSDLs

• CustomObject et al. extend Metadata and need elements from it to work correctly.<xs:extension base="Metadata">

• 330 KB WSDL

Metadata 590,915

Remain-ing

Apex Character Limit

• 590,915 characters / 6740 lineswithout comments

• Approximately 20% of 3,000,000 character Apex limit

Page 13: Using the Tooling API to Generate Apex SOAP Web Service Clients

Method filtering functionality• Reduces amount of generated code

• Reduces testing requirements for dead code

• Potentially skips unsupported features

• Optionally remove supporting Apex classes

Page 14: Using the Tooling API to Generate Apex SOAP Web Service Clients

DemoSFDC Explorer Method filtering

Page 15: Using the Tooling API to Generate Apex SOAP Web Service Clients

How it works

• Tooling API to deploy all associated Apex classes at once

Deploy to Salesforce

• T4 (Text Template Transformation Toolkit)Templates to convert the object model into Apex

Transform to Apex

• C# Object Model of Apex Classes, Members and Methods

Build Apex Model

• Import all WSDL data and extract required elements

Parse WSDL

Page 16: Using the Tooling API to Generate Apex SOAP Web Service Clients

.NET Representation of Apex Class model

ApexClass

ApexMemberApexClassCollection

StringArrayApexMember

ApexMethod

ApexMethodParameter

ApexMethodHttpReturnType

ReturnPrimitive ReturnClassTypeReturnVoid

Type Infos

Inner ClassesNamespace Collection

* Members1 InnerApexClasses * Methods

Parameters

*

ReturnType

1

ApexClasses

0..*

Outer class for each NamespaceCreated for the Port/ServiceEach Request/Response

public class soapSforceCom200604Metadata { public class CallOptions_element { // ... } // ... public class MetadataPort { // ... public fp[] listMetadata(lmq[] q,Double asOfVersion) { // ... } } public class SessionHeader_element { // ... }}

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 =

new String[]{'type','http://soap.sforce.com/2006/04/metadata','string','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[]{'folder','type_x'};}

Page 17: Using the Tooling API to Generate Apex SOAP Web Service Clients

Tooling API deploymentExisting ID• Create a MetadataContainer with a unique name

• Create a collection of ApexClassMember referencing the MetadataContainerId

• Create a ContainerAsyncRequest – Option to Validate Only (IsCheckOnly)

• Keep retrieving until the State is no longer Queued.

• Delete MetadataContainer

New – no existing ID• Call create and collect the SaveResults• Or create an empty stub class to get an ID and use the MetadataContainerMetadataContainer container = new MetadataContainer();

// max length 32 characters!container.Name = "UAC " + DateTime.Now.Ticks;

SaveResult[] containerResults = toolingService.create(new sObject[] { container });

if (!containerResults[0].success) { throw new ToolingCreateException(container, containerResults[0]); }Id metadataContainerId = new Id(containerResults[0].id);

var toUpdate = new List<ApexClassMember>(); foreach(ApexClass ac in classesToUpsert) {

var acm = new ApexClassMember();acm.ContentEntityId = ac.Id; // 01p…acm.Body = ac.Body; // T4 Template

outputacm.FullName = ac.Name; // class nameacm.MetadataContainerId =

metadataContainerId.CaseSafeID;toUpdate.Add(acm);

}

sObject[] toCreate = toUpdate.ToArray(); SaveResult[] cResult = 

toolingService.create(apexClassMembersToCreate);foreach (SaveResult sr in cResult) {

if (!sr.success) {

throw new ToolingCreateException(toCreate,

cResult); }}

var cr = new ContainerAsyncRequest(); cr.MetadataContainerId =

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 });

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);

SaveResult[] saveResults = toolingService.create(apexClassesToInsert.ToArray());if (saveResults != null) {

foreach (SaveResult sr in saveResults) {if (!sr.success) {

throw new ToolingCreateException(apexClassesToInsert.ToArray(), saveResults);}

}}

Page 18: Using the Tooling API to Generate Apex SOAP Web Service Clients

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

Page 19: Using the Tooling API to Generate Apex SOAP Web Service Clients

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

Page 20: Using the Tooling API to Generate Apex SOAP Web Service Clients

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 generatorhttp://goo.gl/tUcnVj

• Session: Building Callouts Without WSDL2Apex and Apex ParsersTuesday, 4:00 PM - 4:30 PM | Moscone Center West | Mobile Theater

www.fuseit.com@FishOfPrey

www.fishofprey.com@GirishaAroraGirisha Arora

Page 21: Using the Tooling API to Generate Apex SOAP Web Service Clients
Page 22: Using the Tooling API to Generate Apex SOAP Web Service Clients

Show FlowDreamforce 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  

   :03Overview 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  

Page 23: Using the Tooling API to Generate Apex SOAP Web Service Clients

Bonus Slides

Page 24: Using the Tooling API to Generate Apex SOAP Web Service Clients

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

Page 25: Using the Tooling API to Generate Apex SOAP Web Service Clients

HTTP Requests• When WebServiceCallout.invoke() fails• A template for supporting more complex callouts• Access full fault messages

SOAPFault Information for Apexhttps://success.salesforce.com/ideaView?id=08730000000BqG9AAK

Page 26: Using the Tooling API to Generate Apex SOAP Web Service Clients

Apex Class Drifting with WSDL changes