- 完成REQ-010-17(性能优化和限流处理)的所有6个阶段 - 创建ADR文档:0026-performance-optimization.md - 创建Prompt文档:027-performance-optimization.md - 创建会话记录:20260119-performance-optimization.md - 创建变更记录:20260119-performance-optimization.md - 创建复盘报告:20260119-performance-optimization-retro.md - 更新index.md和CHANGELOG.md - 完成REQ-010-2(基础实体类和Mapper创建)的前3个阶段 - 更新ADR文档:0011-entity-mapper-create.md - 创建Prompt文档:002-entity-mapper-create.md - 更新index.md 所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
21 KiB
21 KiB
Salesforce SOAP API Java 客户端参考文档
唯一真源文档
本文档是 Salesforce SOAP API Java 客户端的唯一真源文档,包含四个核心模块的完整说明、使用指南和最佳实践。
📋 文档信息
- 文档版本: v1.0.0
- 创建日期: 2026-01-18
- 最后更新: 2026-01-18
- 维护者: Datai Team
- 文档路径:
docs/reference-code/com/docs/index.md
🎯 概述
本文档提供了 Salesforce 官方提供的四个 WSDL 对应的 Java 源代码的完整说明,包括:
- com.sforce.soap.apex - Apex SOAP API
- com.sforce.soap.metadata - Metadata API
- com.sforce.soap.tooling - Tooling API
- com.sforce.soap.partner - Partner API
这些模块位于 docs/reference-code/com/sforce/soap/ 目录下,提供了与 Salesforce 进行交互的完整 Java 客户端实现。
📚 模块导航
1. Apex SOAP API 模块
文档: apex-module.md
用途: 提供 Apex 代码编译、执行和测试功能
核心功能:
- Apex 代码编译和执行
- 测试执行和结果管理
- 代码覆盖率分析
- Flow 覆盖率检查
- 日志记录和调试
主要类:
SoapConnection- SOAP 连接类RunTestsRequest- 测试请求类RunTestsResult- 测试结果类ExecuteAnonymousResult- 匿名执行结果类
适用场景:
- CI/CD 集成
- 代码质量检查
- 动态代码执行
- Flow 测试
2. Metadata API 模块
用途: 提供元数据管理功能,用于创建、读取、更新和删除 Salesforce 元数据
核心功能:
- 元数据类型定义(数百种)
- 部署操作
- 异步操作管理
- 删除操作
主要类:
CustomObject- 自定义对象定义CustomField- 自定义字段定义ApexClass- Apex 类定义DeployOptions- 部署选项配置DeployResult- 部署结果
适用场景:
- 元数据部署
- 元数据检索
- CI/CD 集成
- 元数据管理
- 分析和报告
3. Tooling API 模块
用途: 提供开发工具功能,用于访问和操作 Salesforce 的开发工具
核心功能:
- 元数据操作
- 开发工具功能
- AI 和智能功能
- 动作和自动化
- 访问和安全
主要类:
ToolingConnection- Tooling API 连接类ApexCodeCoverage- Apex 代码覆盖率ApexTestQueueItem- Apex 测试队列项FlowTestCoverage- Flow 测试覆盖率AIApplication- AI 应用程序
适用场景:
- 开发工具集成
- 测试和质量保证
- CI/CD 集成
- AI 和智能功能
- 元数据管理
4. Partner API 模块
用途: 提供数据交互功能,用于 CRUD 操作、查询和数据同步
核心功能:
- CRUD 操作
- 批量操作
- 查询功能
- 描述功能
- 认证和会话
- 高级功能
主要类:
Connector- Partner API 连接类SObject- 动态对象类QueryResult- 查询结果类SaveResult- 保存结果类DescribeSObjectResult- 对象描述结果类
适用场景:
- 数据同步
- 数据集成
- 自定义应用开发
- 报表和分析
- 数据管理
🔧 快速开始
环境要求
- Java 8 或更高版本
- Salesforce WSC (Web Services Connector) 库
- 有效的 Salesforce 账户和 API 访问权限
依赖配置
Maven 依赖
<dependencies>
<!-- Salesforce WSC -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-wsc</artifactId>
<version>58.0.0</version>
</dependency>
<!-- Salesforce Partner API -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-partner-api</artifactId>
<version>58.0.0</version>
</dependency>
<!-- Salesforce Metadata API -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-metadata-api</artifactId>
<version>58.0.0</version>
</dependency>
<!-- Salesforce Tooling API -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-tooling-api</artifactId>
<version>58.0.0</version>
</dependency>
<!-- Salesforce Apex API -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-apex-api</artifactId>
<version>58.0.0</version>
</dependency>
</dependencies>
Gradle 依赖
dependencies {
implementation 'com.force.api:force-wsc:58.0.0'
implementation 'com.force.api:force-partner-api:58.0.0'
implementation 'com.force.api:force-metadata-api:58.0.0'
implementation 'com.force.api:force-tooling-api:58.0.0'
implementation 'com.force.api:force-apex-api:58.0.0'
}
📖 使用指南
1. Partner API 使用示例
建立连接
import com.sforce.soap.partner.*;
import com.sforce.ws.*;
// 创建连接配置
ConnectorConfig config = new ConnectorConfig();
config.setUsername("your-username");
config.setPassword("your-password");
config.setAuthEndpoint("https://login.salesforce.com/services/Soap/u/58.0");
// 创建连接
PartnerConnection connection = new PartnerConnection(config);
// 获取会话信息
System.out.println("Session ID: " + config.getSessionId());
System.out.println("Server URL: " + config.getServiceEndpoint());
创建记录
// 创建 Account 对象
SObject account = new SObject();
account.setType("Account");
account.setField("Name", "Acme Corporation");
account.setField("Industry", "Technology");
account.setField("Phone", "555-1234");
// 执行创建
SaveResult[] results = connection.create(new SObject[]{account});
// 处理结果
for (SaveResult result : results) {
if (result.isSuccess()) {
System.out.println("创建成功,ID: " + result.getId());
} else {
for (Error error : result.getErrors()) {
System.out.println("错误: " + error.getMessage());
}
}
}
查询记录
// 执行 SOQL 查询
QueryResult queryResult = connection.query(
"SELECT Id, Name, Industry, Phone FROM Account WHERE Industry = 'Technology'"
);
// 处理结果
for (SObject record : queryResult.getRecords()) {
String id = record.getId();
String name = record.getField("Name").toString();
String industry = record.getField("Industry").toString();
String phone = record.getField("Phone").toString();
System.out.println("ID: " + id);
System.out.println("Name: " + name);
System.out.println("Industry: " + industry);
System.out.println("Phone: " + phone);
}
// 处理分页
while (!queryResult.isDone()) {
queryResult = connection.queryMore(queryResult.getQueryLocator());
// 处理更多记录
}
更新记录
// 创建要更新的对象
SObject account = new SObject();
account.setType("Account");
account.setId("001xx000003IAC");
account.setField("Phone", "555-5678");
account.setField("Industry", "Finance");
// 执行更新
SaveResult[] results = connection.update(new SObject[]{account});
// 处理结果
for (SaveResult result : results) {
if (result.isSuccess()) {
System.out.println("更新成功");
} else {
for (Error error : result.getErrors()) {
System.out.println("错误: " + error.getMessage());
}
}
}
删除记录
// 执行删除
DeleteResult[] results = connection.delete(new String[]{"001xx000003IAC"});
// 处理结果
for (DeleteResult result : results) {
if (result.isSuccess()) {
System.out.println("删除成功");
} else {
for (Error error : result.getErrors()) {
System.out.println("错误: " + error.getMessage());
}
}
}
2. Metadata API 使用示例
建立连接
import com.sforce.soap.metadata.*;
import com.sforce.ws.*;
// 创建连接配置
ConnectorConfig config = new ConnectorConfig();
config.setUsername("your-username");
config.setPassword("your-password");
config.setAuthEndpoint("https://login.salesforce.com/services/Soap/m/58.0");
// 创建连接
MetadataConnection connection = new MetadataConnection(config);
创建自定义对象
// 创建自定义对象
CustomObject customObject = new CustomObject();
customObject.setFullName("MyCustomObject__c");
customObject.setLabel("My Custom Object");
customObject.setPluralLabel("My Custom Objects");
customObject.setDeploymentStatus("Deployed");
customObject.setSharingModel("ReadWrite");
// 添加字段
CustomField nameField = new CustomField();
nameField.setFullName("MyCustomObject__c.Name__c");
nameField.setType("Text");
nameField.setLabel("Name");
CustomField emailField = new CustomField();
emailField.setFullName("MyCustomObject__c.Email__c");
emailField.setType("Email");
emailField.setLabel("Email Address");
emailField.setRequired(true);
customObject.setFields(new CustomField[]{nameField, emailField});
// 部署元数据
AsyncResult result = connection.create(new Metadata[]{customObject});
// 等待部署完成
while (!result.isDone()) {
Thread.sleep(1000);
result = connection.checkStatus(result.getId());
}
if (result.getState() == AsyncRequestState.Completed) {
System.out.println("部署成功");
} else {
System.out.println("部署失败: " + result.getMessage());
}
部署元数据
// 创建部署选项
DeployOptions options = new DeployOptions();
options.setCheckOnly(false);
options.setTestLevel("RunLocalTests");
options.setRollbackOnError(true);
// 读取 zip 文件
File zipFile = new File("metadata.zip");
byte[] zipBytes = Files.readAllBytes(zipFile.toPath());
// 执行部署
AsyncResult result = connection.deploy(zipBytes, options);
// 等待部署完成
while (!result.isDone()) {
Thread.sleep(1000);
result = connection.checkStatus(result.getId());
}
// 获取部署结果
DeployResult deployResult = connection.checkDeployStatus(result.getId());
if (deployResult.isSuccess()) {
System.out.println("部署成功");
System.out.println("部署的组件数: " + deployResult.getNumberComponentsDeployed());
} else {
System.out.println("部署失败");
for (DeployMessage message : deployResult.getMessages()) {
System.out.println("错误: " + message.getProblem());
}
}
3. Tooling API 使用示例
建立连接
import com.sforce.soap.tooling.*;
import com.sforce.ws.*;
// 创建连接配置
ConnectorConfig config = new ConnectorConfig();
config.setUsername("your-username");
config.setPassword("your-password");
config.setAuthEndpoint("https://login.salesforce.com/services/Soap/T/58.0");
// 创建连接
ToolingConnection connection = new ToolingConnection(config);
查询代码覆盖率
// 执行 SOQL 查询
QueryResult queryResult = connection.query(
"SELECT ApexClassOrTriggerName, Coverage, NumLinesCovered, NumLinesUncovered " +
"FROM ApexCodeCoverage " +
"ORDER BY Coverage DESC"
);
// 处理结果
for (SObject record : queryResult.getRecords()) {
ApexCodeCoverage coverage = (ApexCodeCoverage) record;
String name = coverage.getApexClassOrTriggerName();
double coveragePercent = coverage.getCoverage();
int linesCovered = coverage.getNumLinesCovered();
int linesUncovered = coverage.getNumLinesUncovered();
System.out.println("类名: " + name);
System.out.println("覆盖率: " + coveragePercent + "%");
System.out.println("覆盖行数: " + linesCovered);
System.out.println("未覆盖行数: " + linesUncovered);
}
查询 Flow 测试覆盖率
// 执行 SOQL 查询
QueryResult queryResult = connection.query(
"SELECT FlowName, Coverage, NumElementsCovered, NumElementsNotCovered " +
"FROM FlowTestCoverage " +
"ORDER BY Coverage DESC"
);
// 处理结果
for (SObject record : queryResult.getRecords()) {
FlowTestCoverage coverage = (FlowTestCoverage) record;
String flowName = coverage.getFlowName();
double coveragePercent = coverage.getCoverage();
int elementsCovered = coverage.getNumElementsCovered();
int elementsNotCovered = coverage.getNumElementsNotCovered();
System.out.println("Flow 名称: " + flowName);
System.out.println("覆盖率: " + coveragePercent + "%");
System.out.println("覆盖元素数: " + elementsCovered);
System.out.println("未覆盖元素数: " + elementsNotCovered);
}
4. Apex API 使用示例
建立连接
import com.sforce.soap.apex.*;
import com.sforce.ws.*;
// 创建连接配置
ConnectorConfig config = new ConnectorConfig();
config.setUsername("your-username");
config.setPassword("your-password");
config.setAuthEndpoint("https://login.salesforce.com/services/Soap/s/58.0");
// 创建连接
SoapConnection connection = new SoapConnection(config);
执行匿名代码
// 执行匿名 Apex 代码
String code = "Account acc = new Account(Name='Test Account'); insert acc;";
ExecuteAnonymousResult result = connection.executeAnonymous(code);
// 处理结果
if (result.isSuccess()) {
System.out.println("执行成功");
} else {
System.out.println("执行失败");
System.out.println("编译问题: " + result.getCompileProblem());
System.out.println("异常消息: " + result.getExceptionMessage());
System.out.println("异常堆栈: " + result.getExceptionStackTrace());
}
运行测试
// 创建测试请求
RunTestsRequest request = new RunTestsRequest();
request.setAllTests(true);
// 执行测试
RunTestsResult result = connection.runTests(request);
// 处理结果
System.out.println("测试总数: " + result.getNumTestsRun());
System.out.println("失败数: " + result.getNumFailures());
System.out.println("代码覆盖率: " + result.getCodeCoverage());
// 处理失败的测试
for (RunTestFailure failure : result.getFailures()) {
System.out.println("失败的测试: " + failure.getName());
System.out.println("错误消息: " + failure.getMessage());
System.out.println("堆栈跟踪: " + failure.getStackTrace());
}
// 处理成功的测试
for (RunTestSuccess success : result.getSuccesses()) {
System.out.println("成功的测试: " + success.getName());
System.out.println("执行时间: " + success.getTime() + "ms");
}
⚠️ 注意事项
API 限制
-
Partner API
- 每日 API 调用限制:根据许可证类型而定
- 单次查询记录数限制:50,000 条
- 批量操作限制:200 条记录
-
Metadata API
- 部署文件大小限制:39 MB
- 单次部署组件数限制:10,000 个
- 异步操作超时:10 分钟
-
Tooling API
- 每日 API 调用限制:根据许可证类型而定
- SOQL 查询限制:50,000 条记录
- 并发请求限制:根据许可证类型而定
-
Apex API
- 每日 API 调用限制:根据许可证类型而定
- 执行时间限制:60 秒
- 堆栈深度限制:1,000 层
权限要求
- 需要适当的 API 权限
- 需要对象和字段的 CRUD 权限
- 某些操作需要系统管理员权限
错误处理
- 实现完善的错误处理机制
- 记录详细的错误日志
- 实现重试逻辑
- 处理网络超时和连接问题
性能优化
- 使用批量操作减少 API 调用
- 只查询需要的字段
- 使用适当的过滤条件
- 实现缓存机制
- 监控 API 调用性能
🎓 最佳实践
1. 连接管理
// 使用连接池
public class SalesforceConnectionPool {
private static final Map<String, PartnerConnection> connectionPool = new ConcurrentHashMap<>();
public static PartnerConnection getConnection(String username, String password) {
return connectionPool.computeIfAbsent(username, key -> {
try {
ConnectorConfig config = new ConnectorConfig();
config.setUsername(username);
config.setPassword(password);
config.setAuthEndpoint("https://login.salesforce.com/services/Soap/u/58.0");
return new PartnerConnection(config);
} catch (ConnectionException e) {
throw new RuntimeException("创建连接失败", e);
}
});
}
public static void closeConnection(String username) {
PartnerConnection connection = connectionPool.remove(username);
if (connection != null) {
try {
connection.logout();
} catch (ConnectionException e) {
// 忽略登出错误
}
}
}
}
2. 批量操作
// 批量创建记录
public void createAccounts(List<Account> accounts) throws ConnectionException {
final int BATCH_SIZE = 200;
for (int i = 0; i < accounts.size(); i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, accounts.size());
List<Account> batch = accounts.subList(i, end);
SObject[] sObjects = batch.stream()
.map(this::convertToSObject)
.toArray(SObject[]::new);
SaveResult[] results = connection.create(sObjects);
for (SaveResult result : results) {
if (!result.isSuccess()) {
// 处理错误
}
}
}
}
3. 错误处理
// 统一错误处理
public class SalesforceErrorHandler {
public static void handleSaveResult(SaveResult result) {
if (!result.isSuccess()) {
for (Error error : result.getErrors()) {
log.error("保存失败 - ID: {}, 错误代码: {}, 消息: {}, 字段: {}",
result.getId(),
error.getStatusCode(),
error.getMessage(),
String.join(", ", error.getFields())
);
}
}
}
public static void handleConnectionException(ConnectionException e) {
if (e instanceof ApiFault) {
ApiFault fault = (ApiFault) e;
log.error("API 错误 - 异常代码: {}, 消息: {}",
fault.getExceptionCode(),
fault.getExceptionMessage()
);
} else {
log.error("连接错误", e);
}
}
}
4. 重试机制
// 带重试的 API 调用
public class SalesforceRetryHandler {
private static final int MAX_RETRIES = 3;
private static final long RETRY_DELAY_MS = 1000;
public static <T> T executeWithRetry(Callable<T> callable) throws Exception {
int retryCount = 0;
Exception lastException = null;
while (retryCount < MAX_RETRIES) {
try {
return callable.call();
} catch (ConnectionException e) {
lastException = e;
retryCount++;
if (retryCount < MAX_RETRIES) {
log.warn("API 调用失败,{} 秒后重试 (第 {} 次)",
RETRY_DELAY_MS / 1000, retryCount);
Thread.sleep(RETRY_DELAY_MS);
}
}
}
throw new Exception("API 调用失败,已达到最大重试次数", lastException);
}
}
5. 日志记录
// API 调用日志记录
public class SalesforceLogger {
public static void logApiCall(String apiName, String operation, Object params) {
log.info("API 调用 - 名称: {}, 操作: {}, 参数: {}",
apiName, operation, params);
}
public static void logApiResult(String apiName, String operation,
boolean success, Object result) {
if (success) {
log.info("API 调用成功 - 名称: {}, 操作: {}, 结果: {}",
apiName, operation, result);
} else {
log.error("API 调用失败 - 名称: {}, 操作: {}, 结果: {}",
apiName, operation, result);
}
}
}
🔗 相关资源
官方文档
开发工具
社区资源
📝 更新日志
v1.0.0 (2026-01-18)
- 初始版本发布
- 包含四个核心模块的完整说明
- 提供使用示例和最佳实践
- 添加注意事项和错误处理指南
📧 联系方式
如有问题或建议,请联系:
- 维护者: Datai Team
- 邮箱: support@datai.com
- 文档路径:
docs/reference-code/com/docs/index.md
注意: 本文档是唯一真源文档,所有关于 Salesforce SOAP API Java 客户端的使用说明和最佳实践都应以此文档为准。如有任何疑问,请参考本文档或联系维护者。