Итерация посредника по сравнению с коннектором Salesforce и queryMore quering дубликаты

У меня возникла проблема с использованием queryMore из коннектора Salesforce в wso2esb. Мне нужно получить все записи из учетных записей, затем объединить их в одно сообщение и продолжить его обработку (преобразовать в csv и сохранить).

Документация для соединителя говорит, что я должен использовать

    <salesforce.query>
        <batchSize>200</batchSize>
        <queryString>select id,name from Account</queryString>
    </salesforce.query>
    <!-- Execute the following to get the other batches -->
    <iterate xmlns:sfdc="http://wso2.org/salesforce/adaptor" continueParent="true" expression="//sfdc:iterator">
        <target>
            <sequence>
                <salesforce.queryMore>
                    <batchSize>200</batchSize>
                </salesforce.queryMore>
            </sequence>
        </target>
    </iterate>

но это никогда не увеличивает «queryLocator» и снова и снова запрашивает один и тот же пакет.

Я попытался улучшить его следующим образом:

<salesforce.query>
       <batchSize>200</batchSize>
       <queryString>select id,name from Account limit 2042</queryString>
</salesforce.query>

<property name="MujQueryLocator" expression="get-property('salesforce.query.queryLocator')" scope="operation" type="STRING"/>
<log level="custom">
  <property name="FirstQuery" expression="get-property('salesforce.query.queryLocator')"/>
  <property xmlns:ns="urn:partner.soap.sforce.com" name="FirstQ --" expression="//ns:result/ns:queryLocator/text()"/>
   <property name="MyLocator" expression="get-property('operation','MujQueryLocator')"/>
</log>

<iterate xmlns:sfdc="http://wso2.org/salesforce/adaptor" continueParent="true" expression="//sfdc:iterator" sequential="true">
   <target>
       <sequence>
           <property name="salesforce.query.queryLocator" expression="get-property('operation','MujQueryLocator')" scope="default" type="STRING"/>

  <log level="custom">
      <property name=" BEFORE QueryMore" expression="get-property('salesforce.query.queryLocator')"/>
      <property xmlns:ns="urn:partner.soap.sforce.com" name=" second " expression="//ns:result/ns:queryLocator/text()"/>
      <property name="Muj locator -- " expression="get-property('operation','MujQueryLocator')"/>
  </log>

<salesforce.queryMore>
     <batchSize>200</batchSize>
</salesforce.queryMore>

<property xmlns:ns="urn:partner.soap.sforce.com" name="MujQueryLocator" expression="//ns:result/ns:queryLocator/text()" scope="operation" type="STRING"/>

<log level="custom">
  <property name="AFTER QueryMore" expression="get-property('salesforce.query.queryLocator')"/>
  <property xmlns:ns="urn:partner.soap.sforce.com" name="AFTER QM" expression="//ns:result/ns:queryLocator/text()"/>
  <property name="AFTER MyQueryLocator " expression="get-property('operation','MujQueryLocator')"/>
</log>

 <property xmlns:ns="urn:partner.soap.sforce.com" name="salesforce.query.queryLocator" expression="//ns:result/ns:queryLocator/text()" scope="default" type="STRING"/>

<log level="full"/>
                            <loopback/>
                        </sequence>
                    </target>
                </iterate>
                <respond/>
            </inSequence>
            <outSequence>
                <aggregate>
                    <completeCondition>
                        <messageCount min="-1" max="-1"/>
                    </completeCondition>
                    <onComplete xmlns:ns="urn:partner.soap.sforce.com" expression="//ns:queryResponse|//ns:queryMoreResponse">
                        <enrich>
                            <source clone="true" xpath="//ns:records"/>
                            <target type="body" action="child"/>
                        </enrich>
                        <!-- HERE I WANTED FURTHER PROCESSING OF WHOLE MESSAGE>
                    </onComplete>
                </aggregate>
            </outSequence>

С этого момента queryLocator увеличивается, но не всегда, поэтому он выполняет один и тот же запрос несколько раз и, следовательно, генерирует дублирующиеся данные. В агрегированном сообщении содержится только один из ответов, и он никогда не запрашивает все записи в учетной записи. Смотрите журнал:

[2015-08-11 17:16:49,240]  INFO - LogMediator Connection = Login to Salesforce .....

[2015-08-11 17:16:50,869]  INFO - EndAFTERintContext EndAFTERint : AnonymousEndAFTERint currently SUSPENDED will now be marked active since it processed its last message

[2015-08-11 17:16:52,553]  INFO - LogMediator PrvniQuery = 01gb0000023KfHsAAK-200, PrvniQuery vytazena -- = 01gb0000023KfHsAAK-200, MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:52,572]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:52,588]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:52,722]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:52,847]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:52,982]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:53,107]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:53,247]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-200,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-200

[2015-08-11 17:16:53,274]  INFO - LogMediator --> AFTER QueryMore = 01gb0000023KfHsAAK-400, -- AFTER QM in msg = 01gb0000023KfHsAAK-400, MyQueryLocator  = 01gb0000023KfHsAAK-400

[2015-08-11 17:16:53,281]  INFO - LogMediator To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:112d95e0-df2c-4d39-acdc-88f0a3e82249, Direction: request, Envelope: <?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:sf="urn:sobject.partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><LimitInfoHeader><limitInfo><current>3390</current><limit>15000</limit><type>API REQUESTS</type></limitInfo></LimitInfoHeader></soapenv:Header><soapenv:Body><queryMoreResAFTERnse><result xsi:type="QueryResult"><done>false</done><queryLocator>01gb0000023KfHsAAK-400</queryLocator><records /records><size>2042</size></result></queryMoreResAFTERnse></soapenv:Body></soapenv:Envelope>

[2015-08-11 17:16:53,419]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-400,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-400

[2015-08-11 17:16:53,576]  INFO - LogMediator  BEFORE QueryMore = 01gb0000023KfHsAAK-400,  BEFORE QM in msg = , MyQueryLocator  = 01gb0000023KfHsAAK-400

[2015-08-11 17:16:53,674]  INFO - LogMediator --> AFTER QueryMore = 01gb0000023KfHsAAK-400, -- AFTER QM in msg = 01gb0000023KfHsAAK-400, MyQueryLocator  = 01gb0000023KfHsAAK-400

...again message for 01gb0000023KfHsAAK-400

[2015-08-11 17:16:53,810]  INFO - LogMediator --> AFTER QueryMore = 01gb0000023KfHsAAK-400, -- AFTER QM in msg = 01gb0000023KfHsAAK-400, MyQueryLocator  = 01gb0000023KfHsAAK-400

...again message for 01gb0000023KfHsAAK-400

[2015-08-11 17:16:53,810]  INFO - LogMediator --> AFTER QueryMore = 01gb0000023KfHsAAK-400, -- AFTER QM in msg -- = 01gb0000023KfHsAAK-400, MyQueryLocator  = 01gb0000023KfHsAAK-400

....
.....after some time and repeats it increments to 01gb0000023KfHsAAK-600
...and so on

Еще одна вещь, которую я не знаю, это как объединить ответы из salesforce.query и из формы salesforce.queryПодробнее

ESB версии 4.8.1

Кто-нибудь может объяснить мне такое поведение? Спасибо


person Vojta    schedule 12.08.2015    source источник


Ответы (3)


Из вашего описания я понимаю, что вы хотите сделать цикл "делать-пока". Недавно я столкнулся с похожей ситуацией, и единственным решением, которое я нашел, было создание службы, которая в конце отправляет сообщение самому себе.

В моем случае я использовал это сообщение для передачи некоторых параметров пейджинга (начальная запись и размер страницы), которые в случае Salesforce эквивалентны параметрам batchSize и локатору запроса.

Псевдокод для прокси примерно такой:

if ( first call ) then
    do "query" api call;
else
    set "salesforce.query.queryLocator" property from request data;
    do "query more" api call;
end if;

process query results;

if ( "salesforce.query.done" property is not 'true') then
   create continuation message using the value of
   'salesforce.query.queryLocator' property;
   send one-way message to ESB;
end if;

Обратите внимание, что этот подход работает только в сценариях, в которых последовательность передачи запускается запланированной задачей или клиентом, который используется только для запуска первого вызова.

person Philippe Sevestre    schedule 18.08.2015

С ESB 490 и последним коннектором Salesforce вы можете добиться этого с помощью посредника-итератора. Найдите образец.

     <salesforce.init>
        <username>[email protected]</username>
        <password>xxxxxx</password>
<loginUrl>https://login.salesforce.com/services/Soap/u/34.0</loginUrl>
        <blocking>true</blocking>
     </salesforce.init>
     <log level="custom">
        <property name="salesforce" value="logged in, executing query"/>
     </log>
     <salesforce.query>
        <batchSize>20</batchSize>
        <queryString>select id,name from Account</queryString>
     </salesforce.query>
     <property name="opt.salesforce.query.queryLocator"
               expression="$ctx:salesforce.query.queryLocator"
               scope="operation"
               type="STRING"/>

     <iterate xmlns:sfdc="http://wso2.org/salesforce/adaptor"
              expression="//sfdc:iterator"
              sequential="true">
        <target>
           <sequence>
              <property name="salesforce.query.queryLocator"
                        expression="get-property('operation','opt.salesforce.query.queryLocator')"
                        type="STRING"/>
              <log level="custom">
                 <property name="Before ......................"
                           expression="$ctx:salesforce.query.queryLocator"/>
              </log>
              <salesforce.queryMore>
                 <batchSize>20</batchSize>
              </salesforce.queryMore>
              <property name="opt.salesforce.query.queryLocator"
                        expression="$ctx:salesforce.query.queryLocator"
                        scope="operation"
                        type="STRING"/>
              <log level="custom">
                 <property name="After ......................"
                           expression="$ctx:salesforce.query.queryLocator"/>
              </log>
           </sequence>
        </target>
     </iterate>
person Malaka Silva    schedule 09.05.2016

Да вы правы. И это единственное решение до esb 490. В esb 490 были введены блокирующие вызовы, и благодаря этому мы можем поддерживать do-while с помощью итератора.

Предложенный вами метод (рекурсивные вызовы) имеет ограничение на количество вызовов querymore, что не относится к посреднику итератора.

person Malaka Silva    schedule 11.05.2016