Uncommitted Work Pending - Working around DML then WebService
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:
Update the custom settings fields if there is no information or the
token has expired.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
add a comment |
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:
Update the custom settings fields if there is no information or the
token has expired.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
add a comment |
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:
Update the custom settings fields if there is no information or the
token has expired.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
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:
Update the custom settings fields if there is no information or the
token has expired.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
rest-api webservices oauth2 dml salesforce-connect
asked 5 hours ago
S.B.
42319
42319
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
add a comment |
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
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
add a comment |
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
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
answered 4 hours ago
Adrian Larson♦
104k19112235
104k19112235
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
add a comment |
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
Now that's what I call thinking. Thanks!
– S.B.
4 hours ago
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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