分类 默认分类 下的文章

2GP Managed Package

Salesforce 第二代管控包(Second-Generation Managed Packages)是Salesforce最新推广的最佳实践。通过Salesforce CLI,我们可以很方便的制作和部署第二代管控包。本文只是简略的将核心步骤展示出来:

涉及的各种环境

整个第二代管控包需要用到4类org:

  1. Dev Hub Org:承载所有二代包。可以将各个命名空间的二代包链接到这个org。最好是PBO
  2. Namespace Org:一般是Developer org,在其中申请相应的命名空间,由于命名空间一旦申请便与该org永久绑定且不可修改,申请时请慎重。
  3. Scratch Orgs:在开发测试中使用。
  4. Production Orgs:按照和使用包的生产环境。

2GP Packages.drawio.svg
相关org关系示意图。

10步完成制作

  1. 创建一个 SFDX 项目

    sfdx force:project:create --outputdir expense-manager-workspace --projectname expenser-app
  2. 授权Dev Hub环境,该环境必须启用Dev Hub功能和未锁定包和第二代管控包功能

    sfdx auth:web:login -d -a devHub
  3. 创建一个草稿环境(scratch org)并在其中开发包

    sfdx force:org:create -f config/project-scratch-def.json -u scratchOrg1
  4. 保证所有要打包的组件都已经在当前的项目文件夹内
  5. sfdx-project.json文件中,使用命名空间属性指定命名空间。例如:“namespace”:“exp-mgr”
  6. 从 SFDX 项目文件夹,直接创建管控包:

    sfdx force:package:create --name "Expense Manager" --path force-app --packagetype Managed
  7. 检查项目文件夹中的sfdx-project.json文件,CLI 会自动更新项目文件,使其包含上一步创建的包的信息:

    {
    "packageDirectories": [
       {
          "path": "force-app",
          "default": true,
          "package": "Expense Manager",
          "versionName": "ver 0.1",
          "versionNumber": "0.1.0.NEXT"
       }
    ],
    "namespace": "exp-mgr",
    "sfdcLoginUrl": "https://login.salesforce.com",
    "sourceApiVersion": "51.0",
    "packageAliases": {
       "Expense Manager": "0Hoxxx"
    }
    }
  8. 创建一个包的版本,Salesforce CLI会自动处理包的版本号等

    sfdx force:package:version:create --package "Expense Manager" --installationkey test1234 --wait 10
  9. 在另一个创建好的草稿环境中,安装并测试这个版本的包:

    sfdx force:package:install --package "Expense [email protected]" --targetusername MyTestOrg1 
    --installationkey test1234 --wait 10 --publishwait 10
  10. 安装包后,打开scratch org查看包:

    sfdx force:org:open --targetusername MyTestOrg1
\frac{a}{b^2}

参考:

  1. Salesforce DX Developer Guide
  2. Link a Namespace to a Dev Hub Org
  3. Create and Register Your Namespace for Second-Generation Managed Packages
  4. Workflow for Second-Generation Managed Packages

有时候我们需要在Salesforce页面下载存放为Attachment的文件;或者我们需要把存成Attachment的图片显示在页面上。

内部站点

如果我们文件为Attachment,在Salesforce Internal (即使用Salesforce账户登录的,非Digital Experience, Site.com),则可以使用

 <a href="{!URLFOR($Action.Attachment.Download, attachmentId)}">File Name</a>

下载文件。

或者使用

<img src="{!URLFOR($Action.Attachment.Download, attachmentId)}" />

显示图片。

如果是File,则可以使用Url.getFileFieldURL(entityId, fieldName)

Site.com

Site.com上的则不能用上面的方法,使用的话会直接报错。这时可以通过Salesforce提供的文件下载api /servlet/servlet.FileDownload?file=xxxx~18,不过要注意,一定要使用Salesorce Internal Url,使用Site.com的相关url肯定也会报错。

  1. 首先在后台获取 Salesforce Instance Url 或 Org Domain Url。例如:
    String orgUrl = Url.getOrgDomainUrl().toExternalForm()
  2. 将其传到前台,拼接成下载地址:
    <a href="{!orgUrl + '/servlet/servlet.FileDownload?file=' + attachment.Id}">File Name</a>

参考文档

  1. Visualforce Developer Guide: $Action
  2. Apex Reference Guide: URLClass
  3. stackexchange: How to get salesforce instance url
  4. Salesforce Developer Forum: Download Attachment from Sites??
  5. Salesforce Developer Forum: How to get downloadable link for attachment?

如果你遇到了诸如

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

的错误,说明内存超标。

可以通过下面方法解决:

  1. 直接在node允许的时候加相关参数:

    $ node --max-old-space-size=4096 yourFile.js

    这里将程序可用的最大内存空间增加到了4GB,一般情况下够用了。也可以根据自己的情况更改。

  2. 将相关参数作为环境变量添加进系统;

a. Linux/macOS:

export NODE_OPTIONS=--max-old-space-size=4096

b. Window

$env:NODE_OPTIONS="--max-old-space-size=8192"

半连接和反链接是SOQL里面一个宝,只要用的好,天天下班早

Semi-Join | 半连接

半连接(Semi-Join)指的是在SOQL语句的对比子句里面(也就是WHERE部分),使用子查询(subquery)的情况。

可能用到半连接的情况可能有:

  1. 获取某些具有特定阶段或者截至日期Opportunity的Account下面所有Contact信息
  2. 获取具有激活的Contract的Account下面所有的Opportunity信息

写法
有两种半连接:1)使用Id字段,2)使用外键(Lookup/Master-Detail关系等)

  1. 使用Id字段的半连接例子:

    SELECT Id, Name 
    FROM Account 
    WHERE Id IN 
      ( SELECT AccountId
     FROM Opportunity
     WHERE StageName = 'Closed Lost' 
      )
  2. 使用外键的半连接例子:

    SELECT Id
    FROM Task 
    WHERE WhoId IN 
      (
     SELECT Id
     FROM Contact
     WHERE MailingCity = 'Twin Falls'
      )

Anti-Join | 反连接

反连接(Anti-Join)与半连接非常类似,只是不同于半连接使用的比较关键字为IN, 反连接使用的比较关键字为NOT IN。其余部分包括写法、限制等是一致的,不再赘述。

两种写法

  1. 使用Id字段的半连接例子:

    ELECT Id, (Select Id, Amount, CloseDate FROM Opportunities)
    FROM Account
    WHERE Id NOT IN
      (
     SELECT AccountId
     FROM Contact
     WHERE LastName LIKE 'Trump%'
      )
  2. 使用外键的半连接例子:

    SELECT Id, Name, Phone, Email
    FROM Contact
    WHERE AccountId NOT IN 
      (
     SELECT AccountId
     FROM Opportunity
     WHERE CloseDate < Last_Week
      )

限制

  1. 在主语句的WHERE分句中,不能超过2INNOT IN语句
  2. 不能在半连接或者反连接前使用NOT操作符。若有这种情况,可以考虑把半连接转换为反连接,或者反连接转换为全连接
  3. 必须是Id字段或者外键,诸如... Where Account.Id IN (...)是非法的
  4. 子查询的查询字段必须与主查询对应的字段SObject一致,是且必须是对应的外键
  5. 子查询的字段条数不受限制,但是主查询条数仍收到限制
  6. 半连接或者反连接不能嵌套使用,即不能在半连接/反连接中再使用半连接或者反连接
  7. 子查询不能使用OR
  8. 子查询不支持COUNT, 'FOR UPDATE, ORDER BY, LIMIT`
  9. 下列对象不支持:

    • ActivityHistory
    • Attachments
    • Event
    • EventAttendee
    • Note
    • OpenActivity
    • Tags (AccountTag, ContactTag, and all other tag objects)
    • Task

详情可以查看SOQL and SOSL Reference以下章节:
Semi-Joins with IN and Anti-Joins with NOT IN