英文:
Apache Camel Salesforce Component: Are 'Minor' Relationships Supported?
问题
我正在将数据集成需求从Jitterbit迁移到Camel。
但是我在Camel Salesforce组件方面遇到了严重的问题。涉及的SOQL查询如下:
SELECT Account.Owner.Id, Lookup(User)
Account.Owner.Name, Lookup(User)
Id,
Name,
Owner.Id, Lookup(User)
Owner.Name, Lookup(User)
QualifyingRep__r.Name, Lookup(User)
Solution_Architect__r.Name, Lookup(User)
StageName,
Type,
(SELECT
Id,
Name,
Product2.Name, Lookup(Product)
Quantity,
TotalPrice,
UnitPrice
FROM OpportunityLineItems
),
(SELECT
Id,
CurrencyIsoCode,
SplitAmount,
SplitOwner.Id, Lookup(User)
SplitOwner.Name, Lookup(User)
SplitPercentage,
SplitType.MasterLabel Lookup()
FROM OpportunitySplits
)
FROM Opportunity
WHERE StageName = 'Closed Won';
我已经添加了Lookup(User)
来标注存在的"minor"关系。
返回的JSON如下:
{
"attributes": {
"referenceId": null,
"type": "Opportunity",
"url": "/services/data/v49.0/sobjects/Opportunity/<guid>"
},
"Type": "New Revenue",
"StageName": "Closed Won",
"Account": {
"attributes": {
"referenceId": null,
"type": "Account",
"url": "/services/data/v49.0/sobjects/Account/<guid>"
}
},
"OpportunityLineItems": {
"done": true,
"totalSize": 5,
"nextRecordsUrl": null,
"records": [
{
"attributes": {
"referenceId": null,
"type": "OpportunityLineItem",
"url": "/services/data/v49.0/sobjects/OpportunityLineItem/<guid>"
},
"Quantity": 1.0,
"UnitPrice": 11990.0,
"TotalPrice": 11990.0,
"Name": "XXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYY",
"Id": "<guid>"
},
{
"attributes": {
"referenceId": null,
"type": "OpportunityLineItem",
"url": "/services/data/v49.0/sobjects/OpportunityLineItem/<guid>"
},
"CurrencyIsoCode": "USD",
"Quantity": 1.0,
"UnitPrice": 2758.0,
"TotalPrice": 2758.0,
"Name": "XXXXXXXXXXXXXXXXXXXXXX ZZZZZZZZZZZZZZ",
"Id": "<guid>"
}
]
},
"OpportunitySplits": {
"done": true,
"totalSize": 2,
"nextRecordsUrl": null,
"records": [
{
"attributes": {
"referenceId": null,
"type": "OpportunitySplit",
"url": "/services/data/v49.0/sobjects/OpportunitySplit/<guid>"
},
"CurrencyIsoCode": "USD",
"SplitPercentage": 100.0,
"SplitAmount": 23392.0,
"Id": "<guid>"
},
{
"attributes": {
"referenceId": null,
"type": "OpportunitySplit",
"url": "/services/data/v49.0/sobjects/OpportunitySplit/<guid>"
},
"CurrencyIsoCode": "USD",
"SplitPercentage": 0.0,
"SplitAmount": 0.0,
"Id": "<guid>"
}
]
},
"Name": "XXXXXXXXXXXXXXXXXXXXXX",
"Id": "<guid>"
}
注意: 查询结果应该包含多个名称,但没有一个名称被返回。这是一个严重问题,因为集成的目的是在另一个系统中计算佣金(我们必须确切地知道谁需要支付)。
在使用camel-salesforce-maven-plugin
生成DTO时,也会出现同样的问题 - 这些关系在那里也不受支持。事实上,我最初是在这里注意到了这个问题,当我迁移将Salesforce DTO转换为目标DTO时。而不是Opportunity.Account.OwnerId
返回一个User
对象,它返回一个String
对象。
我提出这个问题是因为Opportunity
DTO同时返回Account
对象和AccountId
(以String
形式)。如果所有生成的DTO都遵循这个模式,就不会有问题。
我相信Jitterbit使用Salesforce SOAP API - 这一切都是在幕后进行的,所以我不能确定。有一件事情是肯定的,Salesforce中定义的所有关系在Jitterbit中都是可用的,所以我对Camel Salesforce组件中发生的情况感到困惑。
是否有什么我需要做的来让DTO中生成所有关系,并且当然要让查询返回所有请求的内容?
更新
我已经在POSTMAN中使用了一个简化的查询进行了测试:
{{instance_url}}/services/data/{{api_version}}/query?q=SELECT Id, Name, Account.Owner.Name FROM Opportunity WHERE StageName = 'Closed Won' AND id = '<guid>'
返回的JSON如下:
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "Opportunity",
"url": "/services/data/v49.0/sobjects/Opportunity/<guid>"
},
"Id": "<guid>",
"Name": "XXXXXXXXXXXXXXXXXXXXXXX",
"Account": {
"attributes": {
"type": "Account",
"url": "/services/data/v49.0/sobjects/Account/<guid>"
},
"Owner": {
"attributes": {
"type": "User",
"url": "/services/data/v49.0/sobjects/User/<guid>"
},
"Name": "<user name>"
}
}
}
]
}
虽然被大量删除,但Account.Owner.Name
路径显然存在,这让
英文:
I am in the process of migrating from Jitterbit to Camel for our data integration needs.
But I'm facing a serious issue with the Camel Salesforce Component. The SOQL query in question is:
SELECT Account.Owner.Id, Lookup(User)
Account.Owner.Name, Lookup(User)
Id,
Name,
Owner.Id, Lookup(User)
Owner.Name, Lookup(User)
QualifyingRep__r.Name, Lookup(User)
Solution_Architect__r.Name, Lookup(User)
StageName,
Type,
(SELECT
Id,
Name,
Product2.Name, Lookup(Product)
Quantity,
TotalPrice,
UnitPrice
FROM OpportunityLineItems
),
(SELECT
Id,
CurrencyIsoCode,
SplitAmount,
SplitOwner.Id, Lookup(User)
SplitOwner.Name, Lookup(User)
SplitPercentage,
SplitType.MasterLabel Lookup()
FROM OpportunitySplits
)
FROM Opportunity
WHERE StageName = 'Closed Won'
I have added Lookup(User)
to annotate the 'minor' relationship where these exist.
The JSON returned is:
{
"attributes": {
"referenceId": null,
"type": "Opportunity",
"url": "/services/data/v49.0/sobjects/Opportunity/<guid>"
},
"Type": "New Revenue",
"StageName": "Closed Won",
"Account": {
"attributes": {
"referenceId": null,
"type": "Account",
"url": "/services/data/v49.0/sobjects/Account/<guid>"
}
},
"OpportunityLineItems": {
"done": true,
"totalSize": 5,
"nextRecordsUrl": null,
"records": [
{
"attributes": {
"referenceId": null,
"type": "OpportunityLineItem",
"url": "/services/data/v49.0/sobjects/OpportunityLineItem/<guid>"
},
"Quantity": 1.0,
"UnitPrice": 11990.0,
"TotalPrice": 11990.0,
"Name": "XXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYY",
"Id": "<guid>"
},
{
"attributes": {
"referenceId": null,
"type": "OpportunityLineItem",
"url": "/services/data/v49.0/sobjects/OpportunityLineItem/<guid>"
},
"CurrencyIsoCode": "USD",
"Quantity": 1.0,
"UnitPrice": 2758.0,
"TotalPrice": 2758.0,
"Name": "XXXXXXXXXXXXXXXXXXXXXX ZZZZZZZZZZZZZZ",
"Id": "<guid>"
}
]
},
"OpportunitySplits": {
"done": true,
"totalSize": 2,
"nextRecordsUrl": null,
"records": [
{
"attributes": {
"referenceId": null,
"type": "OpportunitySplit",
"url": "/services/data/v49.0/sobjects/OpportunitySplit/<guid>"
},
"CurrencyIsoCode": "USD",
"SplitPercentage": 100.0,
"SplitAmount": 23392.0,
"Id": "<guid>"
},
{
"attributes": {
"referenceId": null,
"type": "OpportunitySplit",
"url": "/services/data/v49.0/sobjects/OpportunitySplit/<guid>"
},
"CurrencyIsoCode": "USD",
"SplitPercentage": 0.0,
"SplitAmount": 0.0,
"Id": "<guid>"
}
]
},
"Name": "XXXXXXXXXXXXXXXXXXXXXX",
"Id": "<guid>"
}
NB: The query result should be scattered with names but not a single one is returned. This is a show-stopper because the purpose of the integration is to calculate commissions in another system (we absolutely must know who to pay).
The same thing occurs with the camel-salesforce-maven-plugin
when generating the DTOs - these relationships are not supported there either. In fact, I first noticed the problem here, when migrating the conversion of the Salesforce DTO to the target DTO. Instead of Opportunity.Account.OwnerId
returning a User
object, it returns a String
.
I raise this because Opportunity
DTO has both Account
and AccountId
returning an Account
object and a String
respectively. If all the generated DTOs followed this pattern there would be no issue.
I believe that Jitterbit uses the Salesforce SOAP API - it all happens behind the scenes so I can't be sure. One thing is certain, all the relationships defined in Salesforce are available in Jitterbit, so I'm puzzled by what's happening in the Camel Salesforce Component.
Is there something I need to do to have all the relationships generated in the DTOs, and of course for the query to return everything requested?
Update
I've tested this in POSTMAN using a simplified query:
{{instance_url}}/services/data/{{api_version}}/query?q=SELECT Id, Name, Account.Owner.Name FROM Opportunity WHERE StageName = 'Closed Won' AND id = '<guid>'
The JSON returned is:
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "Opportunity",
"url": "/services/data/v49.0/sobjects/Opportunity/<guid>"
},
"Id": "<guid>",
"Name": "XXXXXXXXXXXXXXXXXXXXXXX",
"Account": {
"attributes": {
"type": "Account",
"url": "/services/data/v49.0/sobjects/Account/<guid>"
},
"Owner": {
"attributes": {
"type": "User",
"url": "/services/data/v49.0/sobjects/User/<guid>"
},
"Name": "<user name>"
}
}
}
]
}
Whilst it's heavily redacted, the Account.Owner.Name
path is clearly there, suggesting to me that this is a Camel Salesforce component issue.
答案1
得分: 0
在这种情况下,解决方案是确保所有的DTO(数据传输对象)都被正确生成。
首先,确保插件已列出正确的对象名称:
<includes>
<include>Account</include>
<include>Invoice__c</include>
<include>Opportunity</include>
<include>OpportunityLineItem</include>
<include>OpportunitySplit</include>
<include>OpportunitySplitType</include>
<include>Product2</include>
<include>User</include>
</includes>
在我的情况下,第一次使用了 Invoice
和 Product
。
然后,逐行比较查询,并确保生成的DTO支持所有的关联关系。这需要手动添加一些关联关系。
例如,需要将 Invoice 添加到 Opportunity 中:
@XStreamAlias("Invoice_2014__r")
private Invoice__c Invoice_2014__r;
/**
* @return the Invoice_2014__r
*/
@JsonProperty("Invoice_2014__r")
public Invoice__c getInvoice_2014__r() {
return Invoice_2014__r;
}
/**
* @param Invoice_2014__r the Invoice_2014__r to set
*/
@JsonProperty("Invoice_2014__r")
public void setInvoice_2014__r(Invoice__c Invoice_2014__r) {
this.Invoice_2014__r = Invoice_2014__r;
}
当DTO完全支持查询时,一切都按预期工作。
我不明白为什么DTO需要手动干预,因为所有必要的关联关系都已在Workbench(https://workbench.developerforce.com)中定义并可见。
英文:
In this case the solution was to ensure that all the DTOs were generated properly.
In the first instance, make sure that the plugin has listed the correct object names:
<includes>
<include>Account</include>
<include>Invoice__c</include>
<include>Opportunity</include>
<include>OpportunityLineItem</include>
<include>OpportunitySplit</include>
<include>OpportunitySplitType</include>
<include>Product2</include>
<include>User</include>
</includes>
In my case I had used Invoice
and Product
first time around.
I then compared the query line by line and ensured that the generated DTOs supported all the relationships. This required some hand-cranking where relationships were missing.
For example, it was necessary to add Invoice to Opportunity:
@XStreamAlias("Invoice_2014__r")
private Invoice__c Invoice_2014__r;
/**
* @return the Invoice_2014__r
*/
@JsonProperty("Invoice_2014__r")
public Invoice__c getInvoice_2014__r() {
return Invoice_2014__r;
}
/**
* @param Invoice_2014__r the Invoice_2014__r to set
*/
@JsonProperty("Invoice_2014__r")
public void setInvoice_2014__r(Invoice__c Invoice_2014__r) {
this.Invoice_2014__r = Invoice_2014__r;
}
When the DTOs fully supported the query, everything worked as expected.
I do not understand why the DTOs required manual intervention, as all the necessary relationships are defined and observable through the Workbench (https://workbench.developerforce.com).
专注分享java语言的经验与见解,让所有开发者获益!
评论