Custom Logging, @Future, Transaction Control











up vote
5
down vote

favorite












I have a similar question to these two: Custom Logging and Future Methods
Custom Exception Handling & Logging



But my question this time is: can I put the @Future annotation on the Logger Class? Why would this not allow me to process DML even if an exception is thrown?



Scenario:
I have a custom Logger class that inserts a custom record with a error message.
The logger class is called at the end of every catch statement.
The only way for the Logger class to insert a new record is if we do not re-throw the caught exception.
I do not want to do this because if there is an exception, this indicates something is broken which should halt the entire process.
This leading me to never be able to insert a new Log error record.



My thought is: if the logger method runs in the future, is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?



For example:



global with sharing class NFLogger {
private enum LogLevel {Error, Info}

@Future
public static void logError(String tags, String errorMessage){
logMessage(logLevel.Error, tags, errorMessage, null);
}

@Future
public static void logError(String tags, String errorMessage, String ex){
logMessage(logLevel.Error, tags, errorMessage, ex);
}

@Future
public static void logInfo(String tags, String infoMessage){
logMessage(logLevel.Info, tags, infoMessage, null);
}

private static void logMessage(LogLevel level, String tags, String message, String ex){
try {
system.debug('Level = ' + level + ', tags = ' + tags + ', message = ' + message + ', system exception = ' + ex);
LogMessage__c newMessage = new LogMessage__c(level__c = level.name(), tags__c = tags, message__c = message, exception__c = ex);
insert newMessage;
}
catch (Exception e){
//intentionally "we suppress" any exception
//we need to guarantee that logMessage will never throw any exceptions
system.debug('in the catch of NFLogger');
}
}
}


APEX:



    ...
try{
TokenGenerator tg = new TokenGenerator();
String tokenizedPayload = tg.getTokenizedPayloadForSingleLead(pLead, nfId); //WEBSERVICE
return new pageReference('/apex/DLPEmailLinkUpdateSvc?id='+pLead+'&tokencred='+tokenizedPayload+'&data='+data+'&ptype=lead');
} catch (Exception ex) {
Apexpages.addMessages(ex);
NFLogger.logError('SendDLPRequestLead, tokenizer', 'There has been an error in the SendDLPRequestLead on Lead: ' + pLead, ex);
throw ex;
}









share|improve this question


























    up vote
    5
    down vote

    favorite












    I have a similar question to these two: Custom Logging and Future Methods
    Custom Exception Handling & Logging



    But my question this time is: can I put the @Future annotation on the Logger Class? Why would this not allow me to process DML even if an exception is thrown?



    Scenario:
    I have a custom Logger class that inserts a custom record with a error message.
    The logger class is called at the end of every catch statement.
    The only way for the Logger class to insert a new record is if we do not re-throw the caught exception.
    I do not want to do this because if there is an exception, this indicates something is broken which should halt the entire process.
    This leading me to never be able to insert a new Log error record.



    My thought is: if the logger method runs in the future, is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?



    For example:



    global with sharing class NFLogger {
    private enum LogLevel {Error, Info}

    @Future
    public static void logError(String tags, String errorMessage){
    logMessage(logLevel.Error, tags, errorMessage, null);
    }

    @Future
    public static void logError(String tags, String errorMessage, String ex){
    logMessage(logLevel.Error, tags, errorMessage, ex);
    }

    @Future
    public static void logInfo(String tags, String infoMessage){
    logMessage(logLevel.Info, tags, infoMessage, null);
    }

    private static void logMessage(LogLevel level, String tags, String message, String ex){
    try {
    system.debug('Level = ' + level + ', tags = ' + tags + ', message = ' + message + ', system exception = ' + ex);
    LogMessage__c newMessage = new LogMessage__c(level__c = level.name(), tags__c = tags, message__c = message, exception__c = ex);
    insert newMessage;
    }
    catch (Exception e){
    //intentionally "we suppress" any exception
    //we need to guarantee that logMessage will never throw any exceptions
    system.debug('in the catch of NFLogger');
    }
    }
    }


    APEX:



        ...
    try{
    TokenGenerator tg = new TokenGenerator();
    String tokenizedPayload = tg.getTokenizedPayloadForSingleLead(pLead, nfId); //WEBSERVICE
    return new pageReference('/apex/DLPEmailLinkUpdateSvc?id='+pLead+'&tokencred='+tokenizedPayload+'&data='+data+'&ptype=lead');
    } catch (Exception ex) {
    Apexpages.addMessages(ex);
    NFLogger.logError('SendDLPRequestLead, tokenizer', 'There has been an error in the SendDLPRequestLead on Lead: ' + pLead, ex);
    throw ex;
    }









    share|improve this question
























      up vote
      5
      down vote

      favorite









      up vote
      5
      down vote

      favorite











      I have a similar question to these two: Custom Logging and Future Methods
      Custom Exception Handling & Logging



      But my question this time is: can I put the @Future annotation on the Logger Class? Why would this not allow me to process DML even if an exception is thrown?



      Scenario:
      I have a custom Logger class that inserts a custom record with a error message.
      The logger class is called at the end of every catch statement.
      The only way for the Logger class to insert a new record is if we do not re-throw the caught exception.
      I do not want to do this because if there is an exception, this indicates something is broken which should halt the entire process.
      This leading me to never be able to insert a new Log error record.



      My thought is: if the logger method runs in the future, is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?



      For example:



      global with sharing class NFLogger {
      private enum LogLevel {Error, Info}

      @Future
      public static void logError(String tags, String errorMessage){
      logMessage(logLevel.Error, tags, errorMessage, null);
      }

      @Future
      public static void logError(String tags, String errorMessage, String ex){
      logMessage(logLevel.Error, tags, errorMessage, ex);
      }

      @Future
      public static void logInfo(String tags, String infoMessage){
      logMessage(logLevel.Info, tags, infoMessage, null);
      }

      private static void logMessage(LogLevel level, String tags, String message, String ex){
      try {
      system.debug('Level = ' + level + ', tags = ' + tags + ', message = ' + message + ', system exception = ' + ex);
      LogMessage__c newMessage = new LogMessage__c(level__c = level.name(), tags__c = tags, message__c = message, exception__c = ex);
      insert newMessage;
      }
      catch (Exception e){
      //intentionally "we suppress" any exception
      //we need to guarantee that logMessage will never throw any exceptions
      system.debug('in the catch of NFLogger');
      }
      }
      }


      APEX:



          ...
      try{
      TokenGenerator tg = new TokenGenerator();
      String tokenizedPayload = tg.getTokenizedPayloadForSingleLead(pLead, nfId); //WEBSERVICE
      return new pageReference('/apex/DLPEmailLinkUpdateSvc?id='+pLead+'&tokencred='+tokenizedPayload+'&data='+data+'&ptype=lead');
      } catch (Exception ex) {
      Apexpages.addMessages(ex);
      NFLogger.logError('SendDLPRequestLead, tokenizer', 'There has been an error in the SendDLPRequestLead on Lead: ' + pLead, ex);
      throw ex;
      }









      share|improve this question













      I have a similar question to these two: Custom Logging and Future Methods
      Custom Exception Handling & Logging



      But my question this time is: can I put the @Future annotation on the Logger Class? Why would this not allow me to process DML even if an exception is thrown?



      Scenario:
      I have a custom Logger class that inserts a custom record with a error message.
      The logger class is called at the end of every catch statement.
      The only way for the Logger class to insert a new record is if we do not re-throw the caught exception.
      I do not want to do this because if there is an exception, this indicates something is broken which should halt the entire process.
      This leading me to never be able to insert a new Log error record.



      My thought is: if the logger method runs in the future, is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?



      For example:



      global with sharing class NFLogger {
      private enum LogLevel {Error, Info}

      @Future
      public static void logError(String tags, String errorMessage){
      logMessage(logLevel.Error, tags, errorMessage, null);
      }

      @Future
      public static void logError(String tags, String errorMessage, String ex){
      logMessage(logLevel.Error, tags, errorMessage, ex);
      }

      @Future
      public static void logInfo(String tags, String infoMessage){
      logMessage(logLevel.Info, tags, infoMessage, null);
      }

      private static void logMessage(LogLevel level, String tags, String message, String ex){
      try {
      system.debug('Level = ' + level + ', tags = ' + tags + ', message = ' + message + ', system exception = ' + ex);
      LogMessage__c newMessage = new LogMessage__c(level__c = level.name(), tags__c = tags, message__c = message, exception__c = ex);
      insert newMessage;
      }
      catch (Exception e){
      //intentionally "we suppress" any exception
      //we need to guarantee that logMessage will never throw any exceptions
      system.debug('in the catch of NFLogger');
      }
      }
      }


      APEX:



          ...
      try{
      TokenGenerator tg = new TokenGenerator();
      String tokenizedPayload = tg.getTokenizedPayloadForSingleLead(pLead, nfId); //WEBSERVICE
      return new pageReference('/apex/DLPEmailLinkUpdateSvc?id='+pLead+'&tokencred='+tokenizedPayload+'&data='+data+'&ptype=lead');
      } catch (Exception ex) {
      Apexpages.addMessages(ex);
      NFLogger.logError('SendDLPRequestLead, tokenizer', 'There has been an error in the SendDLPRequestLead on Lead: ' + pLead, ex);
      throw ex;
      }






      apex exception logging try-catch






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 28 at 16:31









      Olivia

      1,264421




      1,264421






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          5
          down vote













          Nope, you can't do that with a future method, or with a Queueable, or Batch Apex, because all of those asynchronous invocations are enqueued for execution after the transaction's over - and that enqueueing is rolled back when an unhandled exception is thrown just like DML is.



          There is, however, one way you can get those logs out that's rollback-proof: Platform Events.




          Unlike custom objects, platform events aren’t processed within database transactions in the Lightning platform. As a result, published platform events can’t be rolled back.




          If what you really want is to throw an exception and roll back the transaction, but also persist some logging information, publish a Platform Event in your handler. Then, the trigger associated with your Platform Event can do the work needed to persist the log details into the database. That persisting takes place in a separate transaction, as the Automated Process user, and is not subject to the rollback of your original transaction.



          That said, I'm not convinced that letting an unhandled exception propagate is the correct choice in the situations you're showing in your code. In backend code, yes. But - acknowledging that there are many schools of thought on exceptions across the software development world - I don't like unhandled exceptions in my UI code (Visualforce and Lightning controllers).



          The user experience is not ideal in those cases, so I prefer to catch and handle them by presenting a user-friendly message. In Lightning, however, that does entail re-raising an AuraHandledException.






          share|improve this answer























          • I was just writing about Platform Events :P
            – Pranay Jaiswal
            Nov 28 at 16:40










          • Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
            – Pranay Jaiswal
            Nov 28 at 16:46








          • 1




            @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
            – David Reed
            Nov 28 at 17:09






          • 1




            the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
            – cropredy
            Nov 28 at 17:56


















          up vote
          2
          down vote













          For your question:




          is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?




          One of the approaches you can address this scenario is using try-catch-finally as finally block is always guaranteed to be executed as long as it's not an uncatchable exception. So your exceptions are handled, and only then you log the message by keeping your flow synchronous in nature without getting into complexities of handling this asynchronously.




          Code in the finally block always executes regardless of whether an exception was thrown or the type of exception that was thrown. Because the finally block always executes, use it for cleanup code, such as for freeing up resources.




          Sample below.



          Based on a quick test, this approach will work if you are handling the exception in the catch block and not rethrowing it.



          Boolean isException = false;
          Exception myEx;
          try {
          ....
          } catch (Exception e) {
          isException = true;
          myEx = e;
          // handle exception
          } finally {
          // verify if exception occurred, then take the call
          if(isException) {
          // log messages
          }
          }





          share|improve this answer



















          • 1




            +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
            – Pranay Jaiswal
            Nov 28 at 16:48






          • 1




            Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
            – David Reed
            Nov 28 at 16:54












          • @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
            – Jayant Das
            Nov 28 at 16:57






          • 1




            The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
            – David Reed
            Nov 28 at 17:01






          • 1




            I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
            – Jayant Das
            Nov 28 at 17:18











          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',
          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%2f240850%2fcustom-logging-future-transaction-control%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          5
          down vote













          Nope, you can't do that with a future method, or with a Queueable, or Batch Apex, because all of those asynchronous invocations are enqueued for execution after the transaction's over - and that enqueueing is rolled back when an unhandled exception is thrown just like DML is.



          There is, however, one way you can get those logs out that's rollback-proof: Platform Events.




          Unlike custom objects, platform events aren’t processed within database transactions in the Lightning platform. As a result, published platform events can’t be rolled back.




          If what you really want is to throw an exception and roll back the transaction, but also persist some logging information, publish a Platform Event in your handler. Then, the trigger associated with your Platform Event can do the work needed to persist the log details into the database. That persisting takes place in a separate transaction, as the Automated Process user, and is not subject to the rollback of your original transaction.



          That said, I'm not convinced that letting an unhandled exception propagate is the correct choice in the situations you're showing in your code. In backend code, yes. But - acknowledging that there are many schools of thought on exceptions across the software development world - I don't like unhandled exceptions in my UI code (Visualforce and Lightning controllers).



          The user experience is not ideal in those cases, so I prefer to catch and handle them by presenting a user-friendly message. In Lightning, however, that does entail re-raising an AuraHandledException.






          share|improve this answer























          • I was just writing about Platform Events :P
            – Pranay Jaiswal
            Nov 28 at 16:40










          • Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
            – Pranay Jaiswal
            Nov 28 at 16:46








          • 1




            @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
            – David Reed
            Nov 28 at 17:09






          • 1




            the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
            – cropredy
            Nov 28 at 17:56















          up vote
          5
          down vote













          Nope, you can't do that with a future method, or with a Queueable, or Batch Apex, because all of those asynchronous invocations are enqueued for execution after the transaction's over - and that enqueueing is rolled back when an unhandled exception is thrown just like DML is.



          There is, however, one way you can get those logs out that's rollback-proof: Platform Events.




          Unlike custom objects, platform events aren’t processed within database transactions in the Lightning platform. As a result, published platform events can’t be rolled back.




          If what you really want is to throw an exception and roll back the transaction, but also persist some logging information, publish a Platform Event in your handler. Then, the trigger associated with your Platform Event can do the work needed to persist the log details into the database. That persisting takes place in a separate transaction, as the Automated Process user, and is not subject to the rollback of your original transaction.



          That said, I'm not convinced that letting an unhandled exception propagate is the correct choice in the situations you're showing in your code. In backend code, yes. But - acknowledging that there are many schools of thought on exceptions across the software development world - I don't like unhandled exceptions in my UI code (Visualforce and Lightning controllers).



          The user experience is not ideal in those cases, so I prefer to catch and handle them by presenting a user-friendly message. In Lightning, however, that does entail re-raising an AuraHandledException.






          share|improve this answer























          • I was just writing about Platform Events :P
            – Pranay Jaiswal
            Nov 28 at 16:40










          • Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
            – Pranay Jaiswal
            Nov 28 at 16:46








          • 1




            @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
            – David Reed
            Nov 28 at 17:09






          • 1




            the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
            – cropredy
            Nov 28 at 17:56













          up vote
          5
          down vote










          up vote
          5
          down vote









          Nope, you can't do that with a future method, or with a Queueable, or Batch Apex, because all of those asynchronous invocations are enqueued for execution after the transaction's over - and that enqueueing is rolled back when an unhandled exception is thrown just like DML is.



          There is, however, one way you can get those logs out that's rollback-proof: Platform Events.




          Unlike custom objects, platform events aren’t processed within database transactions in the Lightning platform. As a result, published platform events can’t be rolled back.




          If what you really want is to throw an exception and roll back the transaction, but also persist some logging information, publish a Platform Event in your handler. Then, the trigger associated with your Platform Event can do the work needed to persist the log details into the database. That persisting takes place in a separate transaction, as the Automated Process user, and is not subject to the rollback of your original transaction.



          That said, I'm not convinced that letting an unhandled exception propagate is the correct choice in the situations you're showing in your code. In backend code, yes. But - acknowledging that there are many schools of thought on exceptions across the software development world - I don't like unhandled exceptions in my UI code (Visualforce and Lightning controllers).



          The user experience is not ideal in those cases, so I prefer to catch and handle them by presenting a user-friendly message. In Lightning, however, that does entail re-raising an AuraHandledException.






          share|improve this answer














          Nope, you can't do that with a future method, or with a Queueable, or Batch Apex, because all of those asynchronous invocations are enqueued for execution after the transaction's over - and that enqueueing is rolled back when an unhandled exception is thrown just like DML is.



          There is, however, one way you can get those logs out that's rollback-proof: Platform Events.




          Unlike custom objects, platform events aren’t processed within database transactions in the Lightning platform. As a result, published platform events can’t be rolled back.




          If what you really want is to throw an exception and roll back the transaction, but also persist some logging information, publish a Platform Event in your handler. Then, the trigger associated with your Platform Event can do the work needed to persist the log details into the database. That persisting takes place in a separate transaction, as the Automated Process user, and is not subject to the rollback of your original transaction.



          That said, I'm not convinced that letting an unhandled exception propagate is the correct choice in the situations you're showing in your code. In backend code, yes. But - acknowledging that there are many schools of thought on exceptions across the software development world - I don't like unhandled exceptions in my UI code (Visualforce and Lightning controllers).



          The user experience is not ideal in those cases, so I prefer to catch and handle them by presenting a user-friendly message. In Lightning, however, that does entail re-raising an AuraHandledException.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 28 at 16:42

























          answered Nov 28 at 16:39









          David Reed

          28k61746




          28k61746












          • I was just writing about Platform Events :P
            – Pranay Jaiswal
            Nov 28 at 16:40










          • Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
            – Pranay Jaiswal
            Nov 28 at 16:46








          • 1




            @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
            – David Reed
            Nov 28 at 17:09






          • 1




            the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
            – cropredy
            Nov 28 at 17:56


















          • I was just writing about Platform Events :P
            – Pranay Jaiswal
            Nov 28 at 16:40










          • Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
            – Pranay Jaiswal
            Nov 28 at 16:46








          • 1




            @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
            – David Reed
            Nov 28 at 17:09






          • 1




            the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
            – cropredy
            Nov 28 at 17:56
















          I was just writing about Platform Events :P
          – Pranay Jaiswal
          Nov 28 at 16:40




          I was just writing about Platform Events :P
          – Pranay Jaiswal
          Nov 28 at 16:40












          Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
          – Pranay Jaiswal
          Nov 28 at 16:46






          Just to add in some edge cases, Future methods do get called out even if there was an exception in Trigger context. smgoodyear.com/2015/12/04/…
          – Pranay Jaiswal
          Nov 28 at 16:46






          1




          1




          @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
          – David Reed
          Nov 28 at 17:09




          @PranayJaiswal That's quite interesting, I need to spend some time going through that use case. I wonder if there was some hidden retry mechanism in the data loader that produced the result.
          – David Reed
          Nov 28 at 17:09




          1




          1




          the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
          – cropredy
          Nov 28 at 17:56




          the retry mechanism in data loader is allOrNone=false and that SFDC will auto-retry the successes in the batch per this bit of doc. This will cause re-executions if you don't guard against this.
          – cropredy
          Nov 28 at 17:56












          up vote
          2
          down vote













          For your question:




          is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?




          One of the approaches you can address this scenario is using try-catch-finally as finally block is always guaranteed to be executed as long as it's not an uncatchable exception. So your exceptions are handled, and only then you log the message by keeping your flow synchronous in nature without getting into complexities of handling this asynchronously.




          Code in the finally block always executes regardless of whether an exception was thrown or the type of exception that was thrown. Because the finally block always executes, use it for cleanup code, such as for freeing up resources.




          Sample below.



          Based on a quick test, this approach will work if you are handling the exception in the catch block and not rethrowing it.



          Boolean isException = false;
          Exception myEx;
          try {
          ....
          } catch (Exception e) {
          isException = true;
          myEx = e;
          // handle exception
          } finally {
          // verify if exception occurred, then take the call
          if(isException) {
          // log messages
          }
          }





          share|improve this answer



















          • 1




            +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
            – Pranay Jaiswal
            Nov 28 at 16:48






          • 1




            Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
            – David Reed
            Nov 28 at 16:54












          • @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
            – Jayant Das
            Nov 28 at 16:57






          • 1




            The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
            – David Reed
            Nov 28 at 17:01






          • 1




            I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
            – Jayant Das
            Nov 28 at 17:18















          up vote
          2
          down vote













          For your question:




          is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?




          One of the approaches you can address this scenario is using try-catch-finally as finally block is always guaranteed to be executed as long as it's not an uncatchable exception. So your exceptions are handled, and only then you log the message by keeping your flow synchronous in nature without getting into complexities of handling this asynchronously.




          Code in the finally block always executes regardless of whether an exception was thrown or the type of exception that was thrown. Because the finally block always executes, use it for cleanup code, such as for freeing up resources.




          Sample below.



          Based on a quick test, this approach will work if you are handling the exception in the catch block and not rethrowing it.



          Boolean isException = false;
          Exception myEx;
          try {
          ....
          } catch (Exception e) {
          isException = true;
          myEx = e;
          // handle exception
          } finally {
          // verify if exception occurred, then take the call
          if(isException) {
          // log messages
          }
          }





          share|improve this answer



















          • 1




            +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
            – Pranay Jaiswal
            Nov 28 at 16:48






          • 1




            Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
            – David Reed
            Nov 28 at 16:54












          • @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
            – Jayant Das
            Nov 28 at 16:57






          • 1




            The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
            – David Reed
            Nov 28 at 17:01






          • 1




            I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
            – Jayant Das
            Nov 28 at 17:18













          up vote
          2
          down vote










          up vote
          2
          down vote









          For your question:




          is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?




          One of the approaches you can address this scenario is using try-catch-finally as finally block is always guaranteed to be executed as long as it's not an uncatchable exception. So your exceptions are handled, and only then you log the message by keeping your flow synchronous in nature without getting into complexities of handling this asynchronously.




          Code in the finally block always executes regardless of whether an exception was thrown or the type of exception that was thrown. Because the finally block always executes, use it for cleanup code, such as for freeing up resources.




          Sample below.



          Based on a quick test, this approach will work if you are handling the exception in the catch block and not rethrowing it.



          Boolean isException = false;
          Exception myEx;
          try {
          ....
          } catch (Exception e) {
          isException = true;
          myEx = e;
          // handle exception
          } finally {
          // verify if exception occurred, then take the call
          if(isException) {
          // log messages
          }
          }





          share|improve this answer














          For your question:




          is it possible for the process to run, all exceptions are thrown, the process is halted, AND THEN my log message DML happens outside of the transaction?




          One of the approaches you can address this scenario is using try-catch-finally as finally block is always guaranteed to be executed as long as it's not an uncatchable exception. So your exceptions are handled, and only then you log the message by keeping your flow synchronous in nature without getting into complexities of handling this asynchronously.




          Code in the finally block always executes regardless of whether an exception was thrown or the type of exception that was thrown. Because the finally block always executes, use it for cleanup code, such as for freeing up resources.




          Sample below.



          Based on a quick test, this approach will work if you are handling the exception in the catch block and not rethrowing it.



          Boolean isException = false;
          Exception myEx;
          try {
          ....
          } catch (Exception e) {
          isException = true;
          myEx = e;
          // handle exception
          } finally {
          // verify if exception occurred, then take the call
          if(isException) {
          // log messages
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 28 at 17:19

























          answered Nov 28 at 16:43









          Jayant Das

          11.1k2523




          11.1k2523








          • 1




            +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
            – Pranay Jaiswal
            Nov 28 at 16:48






          • 1




            Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
            – David Reed
            Nov 28 at 16:54












          • @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
            – Jayant Das
            Nov 28 at 16:57






          • 1




            The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
            – David Reed
            Nov 28 at 17:01






          • 1




            I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
            – Jayant Das
            Nov 28 at 17:18














          • 1




            +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
            – Pranay Jaiswal
            Nov 28 at 16:48






          • 1




            Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
            – David Reed
            Nov 28 at 16:54












          • @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
            – Jayant Das
            Nov 28 at 16:57






          • 1




            The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
            – David Reed
            Nov 28 at 17:01






          • 1




            I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
            – Jayant Das
            Nov 28 at 17:18








          1




          1




          +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
          – Pranay Jaiswal
          Nov 28 at 16:48




          +1 , I believe finally was made for such things, that should happen even if there is abnormal in execution.
          – Pranay Jaiswal
          Nov 28 at 16:48




          1




          1




          Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
          – David Reed
          Nov 28 at 16:54






          Do future methods invoked in finally blocks get executed if an exception is re-thrown? I can't make that happen with a simple test class.
          – David Reed
          Nov 28 at 16:54














          @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
          – Jayant Das
          Nov 28 at 16:57




          @DavidReed - I haven't really tried it. But if doesn't then that will be interesting find. My PoV here is that if at all there's a piece of code that we always want to be executed after exception handling, then use finally and let that be synchronous. I am recommending to take away asynchronous approach completely here.
          – Jayant Das
          Nov 28 at 16:57




          1




          1




          The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
          – David Reed
          Nov 28 at 17:01




          The overall point may be that re-throwing is a pattern that has relatively limited utility on the Salesforce platform.
          – David Reed
          Nov 28 at 17:01




          1




          1




          I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
          – Jayant Das
          Nov 28 at 17:18




          I quickly verified this, if you handle the exception, this approach works fine, but if you rethrow an exception, it doesn't.
          – Jayant Das
          Nov 28 at 17:18


















          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%2f240850%2fcustom-logging-future-transaction-control%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

          Quarter-circle Tiles

          build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

          Mont Emei