Apache Camel Salesforce 组件:是否支持“次要”关系?

huangapple 未分类评论74阅读模式
英文:

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 = &#39;Closed Won&#39;

I have added Lookup(User) to annotate the 'minor' relationship where these exist.

The JSON returned is:

{
	&quot;attributes&quot;: {
		&quot;referenceId&quot;: null,
		&quot;type&quot;: &quot;Opportunity&quot;,
		&quot;url&quot;: &quot;/services/data/v49.0/sobjects/Opportunity/&lt;guid&gt;&quot;
	},
	&quot;Type&quot;: &quot;New Revenue&quot;,
	&quot;StageName&quot;: &quot;Closed Won&quot;,
	&quot;Account&quot;: {
		&quot;attributes&quot;: {
			&quot;referenceId&quot;: null,
			&quot;type&quot;: &quot;Account&quot;,
			&quot;url&quot;: &quot;/services/data/v49.0/sobjects/Account/&lt;guid&gt;&quot;
		}
	},
	&quot;OpportunityLineItems&quot;: {
		&quot;done&quot;: true,
		&quot;totalSize&quot;: 5,
		&quot;nextRecordsUrl&quot;: null,
		&quot;records&quot;: [
			{
				&quot;attributes&quot;: {
					&quot;referenceId&quot;: null,
					&quot;type&quot;: &quot;OpportunityLineItem&quot;,
					&quot;url&quot;: &quot;/services/data/v49.0/sobjects/OpportunityLineItem/&lt;guid&gt;&quot;
				},
				&quot;Quantity&quot;: 1.0,
				&quot;UnitPrice&quot;: 11990.0,
				&quot;TotalPrice&quot;: 11990.0,
				&quot;Name&quot;: &quot;XXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYY&quot;,
				&quot;Id&quot;: &quot;&lt;guid&gt;&quot;
			},
			{
				&quot;attributes&quot;: {
					&quot;referenceId&quot;: null,
					&quot;type&quot;: &quot;OpportunityLineItem&quot;,
					&quot;url&quot;: &quot;/services/data/v49.0/sobjects/OpportunityLineItem/&lt;guid&gt;&quot;
				},
				&quot;CurrencyIsoCode&quot;: &quot;USD&quot;,
				&quot;Quantity&quot;: 1.0,
				&quot;UnitPrice&quot;: 2758.0,
				&quot;TotalPrice&quot;: 2758.0,
				&quot;Name&quot;: &quot;XXXXXXXXXXXXXXXXXXXXXX ZZZZZZZZZZZZZZ&quot;,
				&quot;Id&quot;: &quot;&lt;guid&gt;&quot;
			}
		]
	},
	&quot;OpportunitySplits&quot;: {
		&quot;done&quot;: true,
		&quot;totalSize&quot;: 2,
		&quot;nextRecordsUrl&quot;: null,
		&quot;records&quot;: [
			{
				&quot;attributes&quot;: {
					&quot;referenceId&quot;: null,
					&quot;type&quot;: &quot;OpportunitySplit&quot;,
					&quot;url&quot;: &quot;/services/data/v49.0/sobjects/OpportunitySplit/&lt;guid&gt;&quot;
				},
				&quot;CurrencyIsoCode&quot;: &quot;USD&quot;,
				&quot;SplitPercentage&quot;: 100.0,
				&quot;SplitAmount&quot;: 23392.0,
				&quot;Id&quot;: &quot;&lt;guid&gt;&quot;
			},
			{
				&quot;attributes&quot;: {
					&quot;referenceId&quot;: null,
					&quot;type&quot;: &quot;OpportunitySplit&quot;,
					&quot;url&quot;: &quot;/services/data/v49.0/sobjects/OpportunitySplit/&lt;guid&gt;&quot;
				},
				&quot;CurrencyIsoCode&quot;: &quot;USD&quot;,
				&quot;SplitPercentage&quot;: 0.0,
				&quot;SplitAmount&quot;: 0.0,
				&quot;Id&quot;: &quot;&lt;guid&gt;&quot;
			}
		]
	},
	&quot;Name&quot;: &quot;XXXXXXXXXXXXXXXXXXXXXX&quot;,
	&quot;Id&quot;: &quot;&lt;guid&gt;&quot;
}

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 = &#39;Closed Won&#39; AND id = &#39;&lt;guid&gt;&#39;

The JSON returned is:

{
    &quot;totalSize&quot;: 1,
    &quot;done&quot;: true,
    &quot;records&quot;: [
        {
            &quot;attributes&quot;: {
                &quot;type&quot;: &quot;Opportunity&quot;,
                &quot;url&quot;: &quot;/services/data/v49.0/sobjects/Opportunity/&lt;guid&gt;&quot;
            },
            &quot;Id&quot;: &quot;&lt;guid&gt;&quot;,
            &quot;Name&quot;: &quot;XXXXXXXXXXXXXXXXXXXXXXX&quot;,
            &quot;Account&quot;: {
                &quot;attributes&quot;: {
                    &quot;type&quot;: &quot;Account&quot;,
                    &quot;url&quot;: &quot;/services/data/v49.0/sobjects/Account/&lt;guid&gt;&quot;
                },
                &quot;Owner&quot;: {
                    &quot;attributes&quot;: {
                        &quot;type&quot;: &quot;User&quot;,
                        &quot;url&quot;: &quot;/services/data/v49.0/sobjects/User/&lt;guid&gt;&quot;
                    },
                    &quot;Name&quot;: &quot;&lt;user name&gt;&quot;
                }
            }
        }
    ]
}

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>

在我的情况下,第一次使用了 InvoiceProduct

然后,逐行比较查询,并确保生成的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:

&lt;includes&gt;
	&lt;include&gt;Account&lt;/include&gt;
	&lt;include&gt;Invoice__c&lt;/include&gt;
	&lt;include&gt;Opportunity&lt;/include&gt;
	&lt;include&gt;OpportunityLineItem&lt;/include&gt;
	&lt;include&gt;OpportunitySplit&lt;/include&gt;
	&lt;include&gt;OpportunitySplitType&lt;/include&gt;
	&lt;include&gt;Product2&lt;/include&gt;
	&lt;include&gt;User&lt;/include&gt;
&lt;/includes&gt;

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(&quot;Invoice_2014__r&quot;)
private Invoice__c Invoice_2014__r;

/**
 * @return the Invoice_2014__r
 */
@JsonProperty(&quot;Invoice_2014__r&quot;)
public Invoice__c getInvoice_2014__r() {
	return Invoice_2014__r;
}

/**
 * @param Invoice_2014__r the Invoice_2014__r to set
 */
@JsonProperty(&quot;Invoice_2014__r&quot;)
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).

huangapple
  • 本文由 发表于 2020年8月14日 21:28:05
  • 转载请务必保留本文链接:https://java.coder-hub.com/63413718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定