Uncommitted Work Pending - Working around DML then WebService












3














I am working with Salesforce Connect and I am storing my token and expiration times in an encrypted custom setting. My connection is through the client credentials Oauth 2 flow.



When a user queries an external object, it makes sense to me in the initial method of salesforce connect DataSource.Connection class to:




  1. Update the custom settings fields if there is no information or the
    token has expired.


  2. Use the custom settings to get the access token if the token has not expired.



This would be fine, however within the same transaction, in the query method of the DataSource.Connection class, webservice callouts to fetch the external objects with the newly updated token must occur. This results in an "uncommitted work pending" error as we would expect because webservice callouts cannot be made after DML statements.



Future methods don't seem to be a plausible solution here because if the token is expired I need those custom settings to be updated at that time otherwise the rest callout will fail.



I thought calling a new instance of another class with a method to update the custom setting might be considered a new transactions, but my assumption was wrong.



I could have users request a token every rest call and store them within the class and not within the custom setting, but that seems so absurdly excessive where as the custom setting would allow multiple users to utilize the same token and only make a token callout when necessary since it's a client connection anyways.



Recommendations?










share|improve this question



























    3














    I am working with Salesforce Connect and I am storing my token and expiration times in an encrypted custom setting. My connection is through the client credentials Oauth 2 flow.



    When a user queries an external object, it makes sense to me in the initial method of salesforce connect DataSource.Connection class to:




    1. Update the custom settings fields if there is no information or the
      token has expired.


    2. Use the custom settings to get the access token if the token has not expired.



    This would be fine, however within the same transaction, in the query method of the DataSource.Connection class, webservice callouts to fetch the external objects with the newly updated token must occur. This results in an "uncommitted work pending" error as we would expect because webservice callouts cannot be made after DML statements.



    Future methods don't seem to be a plausible solution here because if the token is expired I need those custom settings to be updated at that time otherwise the rest callout will fail.



    I thought calling a new instance of another class with a method to update the custom setting might be considered a new transactions, but my assumption was wrong.



    I could have users request a token every rest call and store them within the class and not within the custom setting, but that seems so absurdly excessive where as the custom setting would allow multiple users to utilize the same token and only make a token callout when necessary since it's a client connection anyways.



    Recommendations?










    share|improve this question

























      3












      3








      3







      I am working with Salesforce Connect and I am storing my token and expiration times in an encrypted custom setting. My connection is through the client credentials Oauth 2 flow.



      When a user queries an external object, it makes sense to me in the initial method of salesforce connect DataSource.Connection class to:




      1. Update the custom settings fields if there is no information or the
        token has expired.


      2. Use the custom settings to get the access token if the token has not expired.



      This would be fine, however within the same transaction, in the query method of the DataSource.Connection class, webservice callouts to fetch the external objects with the newly updated token must occur. This results in an "uncommitted work pending" error as we would expect because webservice callouts cannot be made after DML statements.



      Future methods don't seem to be a plausible solution here because if the token is expired I need those custom settings to be updated at that time otherwise the rest callout will fail.



      I thought calling a new instance of another class with a method to update the custom setting might be considered a new transactions, but my assumption was wrong.



      I could have users request a token every rest call and store them within the class and not within the custom setting, but that seems so absurdly excessive where as the custom setting would allow multiple users to utilize the same token and only make a token callout when necessary since it's a client connection anyways.



      Recommendations?










      share|improve this question













      I am working with Salesforce Connect and I am storing my token and expiration times in an encrypted custom setting. My connection is through the client credentials Oauth 2 flow.



      When a user queries an external object, it makes sense to me in the initial method of salesforce connect DataSource.Connection class to:




      1. Update the custom settings fields if there is no information or the
        token has expired.


      2. Use the custom settings to get the access token if the token has not expired.



      This would be fine, however within the same transaction, in the query method of the DataSource.Connection class, webservice callouts to fetch the external objects with the newly updated token must occur. This results in an "uncommitted work pending" error as we would expect because webservice callouts cannot be made after DML statements.



      Future methods don't seem to be a plausible solution here because if the token is expired I need those custom settings to be updated at that time otherwise the rest callout will fail.



      I thought calling a new instance of another class with a method to update the custom setting might be considered a new transactions, but my assumption was wrong.



      I could have users request a token every rest call and store them within the class and not within the custom setting, but that seems so absurdly excessive where as the custom setting would allow multiple users to utilize the same token and only make a token callout when necessary since it's a client connection anyways.



      Recommendations?







      rest-api webservices oauth2 dml salesforce-connect






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 27 at 21:19









      S.B.

      42319




      42319






















          1 Answer
          1






          active

          oldest

          votes


















          4















          I could have users request a token every rest call and store them within the class and not within the custom setting




          You can take the advantages of both approaches. Set up your callout so you can use a token from within memory. If you need to update your setting, move that DML to the end of your transaction.



          Pseudo-code:



          String token = MySetting__c.getOrgDefaults__c.Token__c;

          // if the token is blank or expired, get a new one
          // and reassign the value in your token variable

          // make your callout using the valid token

          // if the token was blank or expired, update your setting





          share|improve this answer





















          • Now that's what I call thinking. Thanks!
            – S.B.
            Dec 27 at 21:31











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "459"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f244825%2funcommitted-work-pending-working-around-dml-then-webservice%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4















          I could have users request a token every rest call and store them within the class and not within the custom setting




          You can take the advantages of both approaches. Set up your callout so you can use a token from within memory. If you need to update your setting, move that DML to the end of your transaction.



          Pseudo-code:



          String token = MySetting__c.getOrgDefaults__c.Token__c;

          // if the token is blank or expired, get a new one
          // and reassign the value in your token variable

          // make your callout using the valid token

          // if the token was blank or expired, update your setting





          share|improve this answer





















          • Now that's what I call thinking. Thanks!
            – S.B.
            Dec 27 at 21:31
















          4















          I could have users request a token every rest call and store them within the class and not within the custom setting




          You can take the advantages of both approaches. Set up your callout so you can use a token from within memory. If you need to update your setting, move that DML to the end of your transaction.



          Pseudo-code:



          String token = MySetting__c.getOrgDefaults__c.Token__c;

          // if the token is blank or expired, get a new one
          // and reassign the value in your token variable

          // make your callout using the valid token

          // if the token was blank or expired, update your setting





          share|improve this answer





















          • Now that's what I call thinking. Thanks!
            – S.B.
            Dec 27 at 21:31














          4












          4








          4







          I could have users request a token every rest call and store them within the class and not within the custom setting




          You can take the advantages of both approaches. Set up your callout so you can use a token from within memory. If you need to update your setting, move that DML to the end of your transaction.



          Pseudo-code:



          String token = MySetting__c.getOrgDefaults__c.Token__c;

          // if the token is blank or expired, get a new one
          // and reassign the value in your token variable

          // make your callout using the valid token

          // if the token was blank or expired, update your setting





          share|improve this answer













          I could have users request a token every rest call and store them within the class and not within the custom setting




          You can take the advantages of both approaches. Set up your callout so you can use a token from within memory. If you need to update your setting, move that DML to the end of your transaction.



          Pseudo-code:



          String token = MySetting__c.getOrgDefaults__c.Token__c;

          // if the token is blank or expired, get a new one
          // and reassign the value in your token variable

          // make your callout using the valid token

          // if the token was blank or expired, update your setting






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 27 at 21:27









          Adrian Larson

          104k19112235




          104k19112235












          • Now that's what I call thinking. Thanks!
            – S.B.
            Dec 27 at 21:31


















          • Now that's what I call thinking. Thanks!
            – S.B.
            Dec 27 at 21:31
















          Now that's what I call thinking. Thanks!
          – S.B.
          Dec 27 at 21:31




          Now that's what I call thinking. Thanks!
          – S.B.
          Dec 27 at 21:31


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Salesforce Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f244825%2funcommitted-work-pending-working-around-dml-then-webservice%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          RAC Tourist Trophy