afv-library/skills/integration-connectivity-generate/assets/soap/wsdl2apex-guide.md

214 lines
6.2 KiB
Markdown

# 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 `?wsdl` suffix (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
1. Navigate to **Setup → Apex Classes**
2. Click **Generate from WSDL**
3. Click **Choose File** and upload the WSDL
4. Review the parse results
5. Modify class names if needed (keep them short to avoid limits)
6. 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)**
1. Create Named Credential in Setup
2. Set endpoint to SOAP service URL
3. Configure authentication (Basic, Certificate, OAuth)
4. In Apex: `stub.endpoint_x = 'callout:MyNamedCredential';`
**Option B: Remote Site Setting**
1. Create Remote Site Setting with domain
2. In Apex: `stub.endpoint_x = 'https://api.example.com/service';`
### 6. Basic Usage Example
```apex
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
```apex
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`:
```apex
@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:
```apex
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
1. **Always use Named Credentials** for authentication instead of hardcoding credentials
2. **Set appropriate timeouts** - default may be too short
3. **Implement error handling** - SOAP services can fail in many ways
4. **Log requests and responses** for debugging
5. **Use async patterns** when calling from DML contexts
6. **Test with mocks** - don't call real services in tests
7. **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.)