platform-salesforce-connect-adapter-generate
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSalesforce Connect — Custom Apex Adapter
Salesforce Connect — 自定义Apex适配器
Route the user through building a complete custom Salesforce Connect Apex adapter: two Apex classes, metadata deployment, and registration. Do not guess at the user's API shape — ask before generating.
引导用户构建完整的Salesforce Connect自定义Apex适配器:包含两个Apex类、元数据部署和注册步骤。请勿猜测用户的API结构——生成前先询问相关信息。
Scope
范围
In scope: Generating and Apex classes, Named Credential metadata, deployment via sf CLI, and step-by-step Setup registration guidance for any REST API.
DataSource.ConnectionDataSource.ProviderOut of scope: Configuring standard adapters (OData, Snowflake, GraphQL — those have their own flows). Generating the External Data Source metadata file (not deployable via sf CLI — must be registered manually in Setup). Writing Apex that calls external APIs outside the Salesforce Connect framework (use platform-apex-generate or integration-connectivity-generate).
包含范围: 生成和 Apex类、Named Credential元数据、通过sf CLI进行部署,以及针对任意REST API的分步Setup注册指导。
DataSource.ConnectionDataSource.Provider排除范围: 配置标准适配器(OData、Snowflake、GraphQL——这些有各自的流程);生成外部数据源元数据文件(无法通过sf CLI部署——必须在Setup中手动注册);编写Salesforce Connect框架外调用外部API的Apex代码(请使用platform-apex-generate或integration-connectivity-generate)。
Before starting
开始前准备
Confirm two things. If either is missing, ask before proceeding.
1. Is this actually a Salesforce Connect use case?
| The user wants to… | Right tool |
|---|---|
| Query external data live without copying it — read-only or read-write, appears as Salesforce records | This skill |
| Copy or sync data into Salesforce on a schedule | platform-data-manage |
| Connect to OData, GraphQL, DynamoDB, Athena, or Cross-Org | Standard adapter setup — no Apex needed, different flow |
| Connect to Snowflake via Salesforce's native Snowflake adapter (direct Snowflake protocol) | Built-in Snowflake adapter — no Apex needed |
| Access Snowflake (or any database) data via a REST or HTTP API | This skill — Snowflake REST endpoint → custom Apex adapter |
| Call an external API from Apex or Flow logic | platform-apex-generate or integration-connectivity-generate |
| Expose Salesforce data to an external system | integration-connectivity-generate |
| Receive real-time pushed data or subscribe to external events | Not Salesforce Connect — Connect is pull-only. Use Platform Events or Change Data Capture instead |
| Sync or copy data for analytics or bulk processing | Data Cloud or ETL — Connect is zero-copy virtualization only |
If the user has a standard adapter available, tell them — writing a custom adapter when a standard one fits is unnecessary work.
2. Do they have a Salesforce Connect license?
A custom adapter requires a Salesforce Connect license (one license per External Data Source). Without it, the External Data Source menu won't show the Apex option. If the user doesn't have one, tell them before going further.
确认以下两点。若缺少任意一项,请先询问用户再继续。
1. 这是否确实是Salesforce Connect的适用场景?
| 用户需求 | 合适工具 |
|---|---|
| 无需复制数据即可实时查询外部数据——只读或读写,以Salesforce记录形式展示 | 本技能 |
| 按计划将数据复制或同步到Salesforce | platform-data-manage |
| 连接到OData、GraphQL、DynamoDB、Athena或跨组织 | 标准适配器设置——无需Apex,流程不同 |
| 通过Salesforce原生Snowflake适配器连接到Snowflake(直接使用Snowflake协议) | 内置Snowflake适配器——无需Apex |
| 通过REST或HTTP API访问Snowflake(或任意数据库)数据 | 本技能 ——Snowflake REST端点 → 自定义Apex适配器 |
| 从Apex或Flow逻辑中调用外部API | platform-apex-generate或integration-connectivity-generate |
| 向外部系统暴露Salesforce数据 | integration-connectivity-generate |
| 接收实时推送数据或订阅外部事件 | 不属于Salesforce Connect——Connect仅支持拉取。请改用Platform Events或Change Data Capture |
| 同步或复制数据用于分析或批量处理 | Data Cloud或ETL——Connect仅支持零拷贝虚拟化 |
如果用户可使用标准适配器,请告知他们——当标准适配器适用时编写自定义适配器属于不必要的工作。
2. 用户是否拥有Salesforce Connect许可证?
自定义适配器需要Salesforce Connect许可证(每个外部数据源需一个许可证)。若无许可证,外部数据源菜单将不会显示Apex选项。若用户没有许可证,请在继续前告知他们。
Default org context (when running locally)
默认组织上下文(本地运行时)
If the user does not specify an org alias, use .
If the user does not specify an SFDX project path, use .
These are the defaults for local testing — always override if the user specifies their own.
demo-org~/salesforce-connect-apex-skill/sfconnect-demo/若用户未指定组织别名,使用。
若用户未指定SFDX项目路径,使用。
这些是本地测试的默认值——若用户指定了自己的配置,请始终覆盖默认值。
demo-org~/salesforce-connect-apex-skill/sfconnect-demo/Collect inputs before generating
生成前收集输入信息
Never generate code without these. If any are missing, ask:
| Input | Why it matters |
|---|---|
| API name and what it does | Names the classes and sets context for field mapping |
| Base URL | Becomes the Named Credential endpoint |
| Auth type | Determines Named Credential setup and |
| Key GET endpoint(s) + sample response | Defines the External Object schema — field names, types, nesting |
| Write support needed? | Determines whether to implement |
| Org type (DE, scratch, sandbox) | Sets |
If the user provides an OpenAPI spec, extract:
- All GET endpoints returning arrays → each becomes a
DataSource.Table - Response object properties → entries
DataSource.Column - /
id/ primary key → map touuidExternalId - Property types → use the field type mapping table below
在缺少以下信息时,切勿生成代码。若有缺失,请询问用户:
| 输入信息 | 重要性 |
|---|---|
| API名称及其功能 | 用于命名类并为字段映射设置上下文 |
| 基础URL | 将成为Named Credential的端点 |
| 认证类型 | 决定Named Credential的设置和 |
| 关键GET端点+示例响应 | 定义外部对象架构——字段名称、类型、嵌套结构 |
| 是否需要写入支持? | 决定是否实现 |
| 组织类型(DE、scratch、sandbox) | 设置 |
若用户提供OpenAPI规范,请提取以下信息:
- 所有返回数组的GET端点 → 每个端点对应一个
DataSource.Table - 响应对象属性 → 条目
DataSource.Column - /
id/主键 → 映射到uuidExternalId - 属性类型 → 使用下方的字段类型映射表
What to build
构建内容
Every custom Salesforce Connect adapter is exactly two Apex classes.
每个Salesforce Connect自定义适配器都包含恰好两个Apex类。
DataSource.Connection
DataSource.Connection
Handles communication with the external API. Exact signatures:
apex
override global DataSource.TableResult query(DataSource.QueryContext context)
override global List<DataSource.TableResult> search(DataSource.SearchContext context)
// Write support — only if API supports it:
global override List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext context)
global override List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext context)Key distinction: always operates on one table ( has a single ). can operate on multiple tables simultaneously ( has multiple instances) — handle each in a loop and return a result per table.
query()QueryContextTableSelectionsearch()SearchContextTableSelection处理与外部API的通信。精确方法签名:
apex
override global DataSource.TableResult query(DataSource.QueryContext context)
override global List<DataSource.TableResult> search(DataSource.SearchContext context)
// 写入支持——仅当API支持时实现:
global override List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext context)
global override List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext context)关键区别:始终针对单个表(包含单个)。可同时针对多个表(包含多个实例)——需循环处理每个表并返回对应结果。
query()QueryContextTableSelectionsearch()SearchContextTableSelectionDataSource.Provider
DataSource.Provider
Declares the adapter's capabilities and schema to Salesforce. Required methods:
- — return
getAuthenticationMode()for public APIs;ANONYMOUSorNAMED_PRINCIPALfor authenticated APIsPER_USER - — declare
getCapabilities(),QUERY; addSEARCH,ROW_CREATE,ROW_UPDATEonly if implementing writesROW_DELETE - — return
getConnection(ConnectionParams params)new YourConnection(params) - — called when the user clicks "Validate and Sync" in Setup; returns
sync()defining the External Object schema and columnsList<DataSource.Table>
The Provider class appears in Salesforce Setup as under the External Data Source type dropdown.
Custom-[ClassName]Critical: whenever you edit the Connection class, you must resave the Provider class too — even with no changes. Otherwise the adapter disappears from the Type picklist and existing External Object tabs break.
向Salesforce声明适配器的功能和架构。必填方法:
- —— 公共API返回
getAuthenticationMode();需认证的API返回ANONYMOUS或NAMED_PRINCIPALPER_USER - —— 声明
getCapabilities()、QUERY;仅当实现写入功能时添加SEARCH、ROW_CREATE、ROW_UPDATEROW_DELETE - —— 返回
getConnection(ConnectionParams params)new YourConnection(params) - —— 用户在Setup中点击“Validate and Sync”时调用;返回
sync()定义外部对象的架构和列List<DataSource.Table>
Provider类在Salesforce Setup的外部数据源类型下拉菜单中显示为****。
Custom-[ClassName]关键注意事项: 无论是否修改Provider类,每当编辑Connection类时,必须重新保存Provider类。否则适配器会从类型选择列表中消失,且现有外部对象标签会失效。
Field type mapping
字段类型映射
| External API type | Use this |
|---|---|
| string / text | |
| number / integer / decimal | |
| boolean | |
| date (ISO 8601) | |
| datetime / timestamp | |
| URL | |
| |
| phone | |
| enum / picklist | |
| nested object / JSON blob | Flatten to scalar fields, or |
| array | Derive a count field ( |
| string > 255 chars | Long text area — do not truncate; Salesforce maps it automatically |
Every must include these columns:
DataSource.Tableapex
DataSource.Column.text('ExternalId', 255) // unique key from external system — REQUIRED
DataSource.Column.text('Name', 255) // display label shown in Salesforce UI — REQUIRED
DataSource.Column.url('DisplayUrl') // link to the record in the external system — recommendedMissing is the most common reason an adapter deploys but records don't appear.
enables the clickable link icon in list views — populate it with the external record's URL.
ExternalIdDisplayUrl| 外部API类型 | 使用对应Salesforce类型 |
|---|---|
| string / text | |
| number / integer / decimal | |
| boolean | |
| date (ISO 8601) | |
| datetime / timestamp | |
| URL | |
| |
| phone | |
| enum / picklist | |
| nested object / JSON blob | 展平为标量字段,或使用 |
| array | 派生计数字段( |
| string > 255字符 | 长文本区域——请勿截断;Salesforce会自动映射 |
每个必须包含以下列:
DataSource.Tableapex
DataSource.Column.text('ExternalId', 255) // 外部系统的唯一键——必填
DataSource.Column.text('Name', 255) // Salesforce UI中显示的标签——必填
DataSource.Column.url('DisplayUrl') // 指向外部系统记录的链接——推荐缺少是适配器部署成功但记录不显示的最常见原因。
可在列表视图中启用可点击链接图标——需填充外部记录的URL。
ExternalIdDisplayUrlScenarios
场景示例
Four scenarios: (1) public read-only, (2) authenticated API key/OAuth, (3) read-write with upsert/delete, (4) paginated API. Full code patterns for each are in .
references/scenarios.mdKey differences by scenario:
| Scenario | Auth mode | Extra capabilities | Named Credential |
|---|---|---|---|
| Public read-only | | | Deploy as metadata |
| Authenticated | | | Create manually in Setup — never deploy credentials as metadata |
| Read-write | | Add | Per above |
| Paginated | Any | Any | Use |
四种场景:(1) 公共只读API,(2) 已认证API(API密钥/OAuth),(3) 支持读写(含upsert/delete),(4) 分页API。每个场景的完整代码模式见。
references/scenarios.md各场景关键差异:
| 场景 | 认证模式 | 额外功能 | Named Credential |
|---|---|---|---|
| 公共只读 | | | 作为元数据部署 |
| 已认证API | | | 在Setup中手动创建——切勿将凭据作为元数据部署 |
| 读写API | | 添加 | 同上 |
| 分页API | 任意 | 任意 | 使用 |
How to verify the adapter is working
验证适配器是否正常工作
Option 1 — SOQL via sf CLI (fastest, no UI needed)
选项1 — 通过sf CLI执行SOQL(最快,无需UI)
bash
sf data query \
--query "SELECT ExternalId, Name__c FROM [YourObject]__x LIMIT 5" \
--target-org [org-alias]If rows come back, the adapter is working. If 0 rows, check the troubleshooting steps below.
bash
sf data query \
--query "SELECT ExternalId, Name__c FROM [YourObject]__x LIMIT 5" \
--target-org [org-alias]若返回数据行,则适配器正常工作。若返回0行,请查看下方故障排除步骤。
Option 2 — Visualforce page (best for demos, works on any org)
选项2 — Visualforce页面(最适合演示,适用于所有组织)
Deploy a Visualforce page + Apex controller that queries and renders rows in an . Open at . More reliable than list views for testing — bypasses tab requirements, deployment status, and filter issues. See for the standard template.
[Object]__xapex:pageBlockTable[orgUrl]/apex/[PageName]references/scenarios.md部署一个Visualforce页面+Apex控制器,查询并在中渲染数据行。在打开页面。比列表视图测试更可靠——绕过标签要求、部署状态和过滤问题。标准模板见。
[Object]__xapex:pageBlockTable[orgUrl]/apex/[PageName]references/scenarios.mdOption 3 — List view (standard UI, but requires extra steps)
选项3 — 列表视图(标准UI,但需额外步骤)
For the list view to show records, all four of these must be true:
- External Object Deployment Status = Deployed (Object Manager → Edit)
- A tab exists for the External Object (Setup → Tabs → Custom Object Tabs → New)
- List view filter is set to All (not "Recently Viewed")
- Remote Site Setting exists for the external API URL
要让列表视图显示记录,必须满足以下四个条件:
- 外部对象部署状态 = 已部署(Object Manager → 编辑)
- 为外部对象创建了标签(Setup → 标签 → 自定义对象标签 → 新建)
- 列表视图过滤器设置为 全部(而非“最近查看”)
- 为外部API URL配置了远程站点设置
Troubleshooting: 0 records with no error
故障排除:返回0记录且无错误
| Symptom | Cause | Fix |
|---|---|---|
| SOQL returns 0 | Remote Site Setting missing | Setup → Remote Site Settings → New |
| SOQL returns 0 | Named Credential not found | Setup → Named Credentials → confirm |
| SOQL returns 0 | Org proxy blocks external URLs | Use loopback pattern or switch to an external DE org |
| List view shows 0 | Deployment Status = In Development | Object Manager → [Object]__x → Edit → Deployed |
| List view shows 0 | Filter is "Recently Viewed" | Change filter to "All" |
| App Launcher shows nothing | No tab created | Setup → Tabs → Custom Object Tabs → New |
| 症状 | 原因 | 修复方法 |
|---|---|---|
| SOQL返回0 | 缺少远程站点设置 | Setup → 远程站点设置 → 新建 |
| SOQL返回0 | 未找到Named Credential | Setup → Named Credentials → 确认 |
| SOQL返回0 | 组织代理阻止外部URL | 使用环回模式或切换到外部DE组织 |
| 列表视图显示0 | 部署状态 = 开发中 | Object Manager → [Object]__x → 编辑 → 已部署 |
| 列表视图显示0 | 过滤器为“最近查看” | 将过滤器更改为“全部” |
| 应用启动器无显示 | 未创建标签 | Setup → 标签 → 自定义对象标签 → 新建 |
What the agent deploys vs. what the developer does manually
代理部署内容 vs 开发者手动操作内容
Agent deploys (one sf project deploy start
command)
sf project deploy start代理部署(通过sf project deploy start
命令)
sf project deploy start| File | Notes |
|---|---|
| Always |
| Always |
| Public APIs only — skip for any API requiring credentials |
Do NOT generate . The External Data Source must be registered manually in Setup after deploying the Apex classes. The command cannot deploy custom Apex External Data Sources — the sf CLI will error with "Could not infer a metadata type." Tell the user to go to Setup → External Data Sources → New after deployment.
externalDataSources/[API].externalDataSource-meta.xmlsf project deploy startCorrect NamedCredential XML format (no element — the API name comes from the filename):
<name>xml
<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<label>My API</label>
<endpoint>https://api.example.com</endpoint>
<allowMergeFieldsInBody>false</allowMergeFieldsInBody>
<allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
<generateAuthorizationHeader>false</generateAuthorizationHeader>
<principalType>Anonymous</principalType>
<protocol>NoAuthentication</protocol>
</NamedCredential>Deploy command:
bash
sf project deploy start \
--source-dir force-app/main/default/ \
--target-org [org-alias]| 文件 | 说明 |
|---|---|
| 始终需要 |
| 始终需要 |
| 仅公共API —— 任何需要凭据的API均跳过 |
请勿生成。 外部数据源必须在部署Apex类后在Setup中手动注册。命令无法部署自定义Apex外部数据源——sf CLI会报错“Could not infer a metadata type.”。请告知用户部署完成后前往Setup → 外部数据源 → 新建。
externalDataSources/[API].externalDataSource-meta.xmlsf project deploy start正确的NamedCredential XML格式(无元素——API名称来自文件名):
<name>xml
<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<label>My API</label>
<endpoint>https://api.example.com</endpoint>
<allowMergeFieldsInBody>false</allowMergeFieldsInBody>
<allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
<generateAuthorizationHeader>false</generateAuthorizationHeader>
<principalType>Anonymous</principalType>
<protocol>NoAuthentication</protocol>
</NamedCredential>部署命令:
bash
sf project deploy start \
--source-dir force-app/main/default/ \
--target-org [org-alias]Developer does manually (always — no metadata equivalent exists)
开发者手动操作(始终需要——无等效元数据)
Validate and Sync triggers a live call to the external API to discover its schema and create External Object definitions. This cannot be scripted.
text
Setup → External Data Sources → [your data source] → Validate and Sync
Check the box next to each External Object → Sync
App Launcher → search [External Object name] → confirm records appearAlways end with: "Deployment complete. One step left: open the External Data Source in Salesforce Setup and click Validate and Sync."
Validate and Sync会触发对外部API的实时调用,以发现其架构并创建外部对象定义。此步骤无法脚本化。
text
Setup → 外部数据源 → [你的数据源] → Validate and Sync
勾选每个外部对象旁的复选框 → Sync
应用启动器 → 搜索[外部对象名称] → 确认记录显示始终以这句话结束:“部署完成。最后一步:在Salesforce Setup中打开外部数据源并点击Validate and Sync。”
Error handling rules
错误处理规则
Never let an exception propagate uncaught out of — Salesforce shows a generic error to the user with no context.
query()| Situation | Handle it by |
|---|---|
| HTTP 401 | |
| HTTP 429 / rate limit | Return empty rows; log via |
| HTTP 500 or network error | Return empty rows; do not rethrow |
| Null field in response | |
| Nested JSON that won't flatten | Return raw JSON string as a TEXT_TYPE field rather than failing the whole query |
切勿让异常未经捕获就从方法中抛出——Salesforce会向用户显示无上下文的通用错误。
query()| 场景 | 处理方式 |
|---|---|
| HTTP 401 | |
| HTTP 429 / 速率限制 | 返回空数据行;通过 |
| HTTP 500或网络错误 | 返回空数据行;请勿重新抛出异常 |
| 响应中存在空字段 | |
| 无法展平的嵌套JSON | 返回原始JSON字符串作为TEXT_TYPE字段,而非导致整个查询失败 |
Governor limits
governor限制
- Max 100 HTTP callouts per transaction — each call is one transaction
query() - Heap limit 6 MB (synchronous) — don't deserialize massive payloads; use server-side pagination
- CPU limit 10 seconds — avoid nested loops over large response arrays
- 每个事务最多100次HTTP调用——每次调用为一个事务
query() - 堆内存限制6 MB(同步)——请勿反序列化超大负载;使用服务器端分页
- CPU限制10秒——避免对大型响应数组使用嵌套循环
Setup prerequisites — in this exact order
设置前提条件——按以下精确顺序
1. Deploy Apex classes first
1. 先部署Apex类
The type only appears in the External Data Source type dropdown after at least one subclass is deployed in the org.
Salesforce Connect: Custom (Developed with Apex)DataSource.ProviderThis is not a permissions issue. It is a dependency — Salesforce discovers available Provider classes at runtime. No deployed Provider = no option in the dropdown.
Correct sequence — always:
- Deploy Apex classes first ()
sf project deploy start - Then go to Setup → External Data Sources → New → the Custom Apex type will appear
If the user says "I don't see the Custom Apex option in the dropdown", the answer is: deploy the classes first, then come back to Setup.
仅当组织中至少部署了一个子类后,类型才会显示在外部数据源类型下拉菜单中。
DataSource.ProviderSalesforce Connect: Custom (Developed with Apex)这并非权限问题,而是依赖关系——Salesforce在运行时发现可用的Provider类。未部署Provider类 → 下拉菜单中无此选项。
正确顺序——始终遵循:
- 先部署Apex类()
sf project deploy start - 然后前往Setup → 外部数据源 → 新建 → 自定义Apex类型将显示
若用户表示“我在下拉菜单中看不到自定义Apex选项”,解决方案是:先部署类,再返回Setup操作。
2. Add Remote Site Setting before testing
2. 测试前添加远程站点设置
The external API's base URL must be whitelisted or callouts fail silently — returns empty rows with no exception, no error message. Deploy as metadata or add at Setup → Remote Site Settings → New.
query()必须将外部API的基础URL加入白名单,否则调用会静默失败——返回空数据行,无异常、无错误消息。可作为元数据部署,或在Setup → 远程站点设置 → 新建中添加。
query()3. After Validate and Sync — set Deployment Status to Deployed
3. Validate and Sync后——将部署状态设置为已部署
After Validate and Sync, Salesforce creates the External Object with status "In Development". Records return 0 results in list views and SOQL until this is changed. No error is shown — another silent failure.
text
Setup → Object Manager → [YourObject]__x → Edit
Deployment Status → Deployed → SaveAlways tell the user this step after Validate and Sync completes.
Validate and Sync完成后,Salesforce创建的外部对象状态为**“开发中”**。在将状态更改前,列表视图和SOQL返回的记录数均为0。无错误提示——又是一个静默失败。
text
Setup → Object Manager → [YourObject]__x → 编辑
部署状态 → 已部署 → 保存Validate and Sync完成后,请务必告知用户此步骤。
4. Create a tab to surface the External Object in App Launcher
4. 创建标签以在应用启动器中显示外部对象
External Objects are invisible in the UI without a tab. Create one at:
text
Setup → Tabs → Custom Object Tabs → New → select [YourObject]__x → Save若无标签,外部对象在UI中不可见。在以下路径创建标签:
text
Setup → 标签 → 自定义对象标签 → 新建 → 选择[YourObject]__x → 保存Also required
其他必填项
- Salesforce Connect license — without it, all Connect adapter types including OData are hidden. If the user sees OData and Cross-Org in the dropdown, the license is already active.
- Salesforce Connect许可证 —— 若无许可证,所有Connect适配器类型(包括OData)都会隐藏。若用户在下拉菜单中看到OData和跨组织选项,则许可证已激活。
Anti-patterns
反模式
| Don't | Why | Do |
|---|---|---|
| Generate code without knowing the API shape | Wrong field types, wrong ExternalId mapping, broken adapter | Ask for API name, base URL, auth type, sample response first |
| Deploy ExternalDataSource as metadata | Not a deployable metadata type — sf CLI will error | Register the External Data Source manually in Setup after deploying the Apex classes |
Use | These methods don't exist — compile error | Use |
Put | On some API versions | Implement |
| Hardcode the API URL in Apex | Credentials exposed in source, callout blocked | Always use |
Return a single | | Loop over |
Skip COUNT handling in | List views fire COUNT queries; without detection they return wrong results | Check |
| Leave External Object in "In Development" | Records return 0 with no error — invisible to the user | After Validate and Sync: Object Manager → [Object]__x → Edit → Deployed |
| Skip the Remote Site Setting | Callout fires silently, returns empty rows, no exception | Deploy |
| 请勿操作 | 原因 | 正确操作 |
|---|---|---|
| 在未知API结构的情况下生成代码 | 字段类型错误、ExternalId映射错误、适配器失效 | 先询问API名称、URL、认证类型、示例响应 |
| 将ExternalDataSource作为元数据部署 | 并非可部署的元数据类型——sf CLI会报错 | 部署Apex类后在Setup中手动注册外部数据源 |
使用 | 这些方法不存在——编译错误 | 使用 |
仅在Provider类中实现 | 在某些API版本中 | 在Connection类中实现 |
| 在Apex中硬编码API URL | 凭据暴露在源码中、调用被阻止 | 始终使用 |
从 | | 循环遍历 |
在 | 列表视图会触发COUNT查询;若未处理则返回错误结果 | 检查 |
| 让外部对象处于“开发中”状态 | 记录返回0且无错误——对用户不可见 | Validate and Sync后:Object Manager → [Object]__x → 编辑 → 已部署 |
| 跳过远程站点设置 | 调用静默失败,返回空数据行,无异常 | 部署 |
Before shipping
交付前确认
Confirm: inputs collected (API name, URL, auth, sample response, write support) → code has + + on Connection, + on Provider, and on every table, COUNT handling in , mock data for tests, prefix on all endpoints → both files generated → deploy command given → post-deploy steps communicated (Named Credential setup, Remote Site Setting, External Data Source registered, Validate and Sync, Deployment Status → Deployed, tab created).
sync()query()search()getCapabilities()getConnection()ExternalIdnameColumnquery()callout:.cls-meta.xml确认:已收集输入信息(API名称、URL、认证方式、示例响应、写入支持)→ 代码在Connection类中包含++,在Provider类中包含+,每个表都有和,中包含COUNT处理,测试用模拟数据,所有端点使用前缀 → 生成了两个文件 → 提供了部署命令 → 传达了部署后步骤(Named Credential设置、远程站点设置、外部数据源注册、Validate and Sync、部署状态→已部署、创建标签)。
sync()query()search()getCapabilities()getConnection()ExternalIdnameColumnquery()callout:.cls-meta.xmlReference examples
参考示例
See for annotated study of the official Salesforce Connect adapter examples — GitHub Issues (full DML, picklist, cross-table relationships), Google Drive (OAuth + test mock), Google Books (pagination), StackOverflow (multiple tables), and Loopback (filter translation). Read before generating for a new user.
references/official-examples.md查看获取带注释的官方Salesforce Connect适配器示例——GitHub Issues(完整DML、选择列表、跨表关系)、Google Drive(OAuth+测试模拟)、Google Books(分页)、StackOverflow(多表)和Loopback(过滤器转换)。为新用户生成代码前请阅读这些示例。
references/official-examples.mdProject setup — if the developer has no SFDX project yet
项目设置——若开发者尚无SFDX项目
Before deploying, they need a project structure. If one doesn't exist, generate it first:
bash
sf project generate --name my-adapter --output-dir .
cd my-adapterThis creates and the required . All generated files go into this structure. The developer does not need VS Code, Agentforce Vibes, or any Salesforce IDE — just CLI installed and an org authenticated via .
force-app/main/default/classes/sfdx-project.jsonsfsf org login web --alias my-orgThis skill works with any coding agent that can read a context file — Claude Code, Cursor, Windsurf, GitHub Copilot, or any agent with the SKILL.md loaded. No Salesforce MCP server, no Agentforce Vibes, no internal Salesforce tooling required.
部署前需要项目结构。若不存在,请先生成:
bash
sf project generate --name my-adapter --output-dir .
cd my-adapter此命令会创建和所需的。所有生成的文件都放入此结构。开发者无需VS Code、Agentforce Vibes或任何Salesforce IDE——只需安装 CLI并通过认证组织。
force-app/main/default/classes/sfdx-project.jsonsfsf org login web --alias my-org本技能可与任何能读取上下文文件的编码代理配合使用——Claude Code、Cursor、Windsurf、GitHub Copilot,或任何加载了SKILL.md的代理。无需Salesforce MCP服务器、Agentforce Vibes或内部Salesforce工具。
Output format
输出格式
Generate files in this order, then give the deploy command:
force-app/main/default/classes/[API]DataSourceConnection.clsforce-app/main/default/classes/[API]DataSourceProvider.clsforce-app/main/default/classes/[API]DataSourceConnection.cls-meta.xmlforce-app/main/default/classes/[API]DataSourceProvider.cls-meta.xml- — public APIs only
force-app/main/default/namedCredentials/[API].namedCredential-meta.xml
One-line comment at top of each Apex class:
No other inline comments unless a logic choice is non-obvious.
// Salesforce Connect custom adapter for [API name]按以下顺序生成文件,然后提供部署命令:
force-app/main/default/classes/[API]DataSourceConnection.clsforce-app/main/default/classes/[API]DataSourceProvider.clsforce-app/main/default/classes/[API]DataSourceConnection.cls-meta.xmlforce-app/main/default/classes/[API]DataSourceProvider.cls-meta.xml- —— 仅公共API
force-app/main/default/namedCredentials/[API].namedCredential-meta.xml
每个Apex类顶部添加一行注释:
除非逻辑选择不明显,否则请勿添加其他内联注释。
// Salesforce Connect custom adapter for [API name]