mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-05 06:41:42 +08:00
6.2 KiB
6.2 KiB
WSDL to Apex Generation Guide
Overview
Salesforce can automatically generate Apex classes from WSDL (Web Services Description Language) files, enabling integration with SOAP-based web services.
Step-by-Step Process
1. Obtain the WSDL File
Get the WSDL from your external system. Common sources:
- API documentation portal
- Endpoint URL with
?wsdlsuffix (e.g.,https://api.example.com/service?wsdl) - Direct download from vendor
2. Review WSDL for Compatibility
Salesforce WSDL2Apex has limitations. Check for:
Supported:
- Document/literal and RPC/encoded styles
- Simple types (string, integer, boolean, date, etc.)
- Complex types (objects with properties)
- Arrays and lists
- Basic SOAP headers
Not Supported / Problematic:
- Very large WSDLs (may hit Apex class size limits)
- Certain complex inheritance patterns
- Some advanced XSD features
- WS-Security (requires manual implementation)
3. Generate Apex Classes
- Navigate to Setup → Apex Classes
- Click Generate from WSDL
- Click Choose File and upload the WSDL
- Review the parse results
- Modify class names if needed (keep them short to avoid limits)
- Click Generate Apex code
4. Generated Class Structure
For a WSDL defining CustomerService with operation getCustomer:
AsyncCustomerService.cls - Async version of service
CustomerService.cls - Main stub class with methods
GetCustomerRequest.cls - Request wrapper
GetCustomerResponse.cls - Response wrapper
Customer.cls - Data type from schema
Address.cls - Nested data type
5. Configure Endpoint Access
Option A: Named Credential (Recommended)
- Create Named Credential in Setup
- Set endpoint to SOAP service URL
- Configure authentication (Basic, Certificate, OAuth)
- In Apex:
stub.endpoint_x = 'callout:MyNamedCredential';
Option B: Remote Site Setting
- Create Remote Site Setting with domain
- In Apex:
stub.endpoint_x = 'https://api.example.com/service';
6. Basic Usage Example
public class CustomerServiceCaller {
public static Customer getCustomer(String customerId) {
// Instantiate the generated stub
CustomerService.CustomerServicePort stub = new CustomerService.CustomerServicePort();
// Configure endpoint (Named Credential)
stub.endpoint_x = 'callout:CustomerServiceNC';
// Set timeout (max 120 seconds)
stub.timeout_x = 120000;
// Create request
GetCustomerRequest request = new GetCustomerRequest();
request.customerId = customerId;
// Make the call
GetCustomerResponse response = stub.getCustomer(request);
return response.customer;
}
}
7. Error Handling
try {
GetCustomerResponse response = stub.getCustomer(request);
// Process response
} catch (CalloutException e) {
// Network error, timeout, SSL issues
System.debug('Callout failed: ' + e.getMessage());
} catch (Exception e) {
// SOAP fault (error from service)
// The exception message contains SOAP fault details
System.debug('SOAP error: ' + e.getMessage());
}
8. Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
Web service callout failed |
Network/SSL issue | Check Remote Site Setting, verify endpoint |
Read timed out |
Service slow to respond | Increase timeout_x (max 120000ms) |
Apex class size limit |
WSDL too large | Split WSDL, use fewer operations |
Unable to parse callout response |
Response doesn't match WSDL | Check service version, update WSDL |
Methods defined as Webservice |
Conflict with reserved keywords | Rename operations in WSDL or generated class |
9. Testing SOAP Callouts
Use Test.setMock() with WebServiceMock:
@isTest
public class CustomerServiceTest {
@isTest
static void testGetCustomer() {
// Set mock
Test.setMock(WebServiceMock.class, new CustomerServiceMock());
// Call service
Test.startTest();
Customer result = CustomerServiceCaller.getCustomer('CUST001');
Test.stopTest();
// Assert
System.assertEquals('Test Customer', result.name);
}
// Mock implementation
public class CustomerServiceMock implements WebServiceMock {
public void doInvoke(
Object stub,
Object request,
Map<String, Object> response,
String endpoint,
String soapAction,
String requestName,
String responseNS,
String responseName,
String responseType
) {
// Create mock response
GetCustomerResponse mockResponse = new GetCustomerResponse();
mockResponse.customer = new Customer();
mockResponse.customer.name = 'Test Customer';
response.put('response_x', mockResponse);
}
}
}
10. Async SOAP Calls
For calls from triggers or after DML:
public class CustomerSyncQueueable implements Queueable, Database.AllowsCallouts {
private String customerId;
public CustomerSyncQueueable(String customerId) {
this.customerId = customerId;
}
public void execute(QueueableContext context) {
try {
Customer customer = CustomerServiceCaller.getCustomer(customerId);
// Process result
} catch (Exception e) {
// Log error
}
}
}
// Usage in trigger:
System.enqueueJob(new CustomerSyncQueueable(accountId));
Best Practices
- Always use Named Credentials for authentication instead of hardcoding credentials
- Set appropriate timeouts - default may be too short
- Implement error handling - SOAP services can fail in many ways
- Log requests and responses for debugging
- Use async patterns when calling from DML contexts
- Test with mocks - don't call real services in tests
- Monitor governor limits - especially for large responses
Limitations
- Maximum 100 callouts per transaction
- Maximum 120 second timeout per callout
- Response body limit: 6MB
- Apex code size limits may prevent large WSDL imports
- Some WSDL features not supported (WS-Security, MTOM, etc.)