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;
}
apex exception logging try-catch
add a comment |
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;
}
apex exception logging try-catch
add a comment |
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;
}
apex exception logging try-catch
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
apex exception logging try-catch
asked Nov 28 at 16:31
Olivia
1,264421
1,264421
add a comment |
add a comment |
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
.
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 isallOrNone=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
add a comment |
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
}
}
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 infinally
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
|
show 3 more comments
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
.
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 isallOrNone=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
add a comment |
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
.
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 isallOrNone=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
add a comment |
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
.
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
.
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 isallOrNone=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
add a comment |
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 isallOrNone=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
add a comment |
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
}
}
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 infinally
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
|
show 3 more comments
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
}
}
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 infinally
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
|
show 3 more comments
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
}
}
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
}
}
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 infinally
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
|
show 3 more comments
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 infinally
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
|
show 3 more comments
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%2f240850%2fcustom-logging-future-transaction-control%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