function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ArleneArlene 

Exception Handling and Logging

We would like to have information logged from exceptions caught in Apex.  We have a custom object to store it in (Error_Detected__c).  Query exceptions are successfully stored.  I have been unable to find a way to capture DML exceptions that occur as the result (for example) of a user clicking the Submit button on a VF page with a custom controller.  Following http://wiki.developerforce.com/page/An_Introduction_to_Exception_Handling, this is what I have attempted.

 

1.  Insert an entry into Error_Detected__c  in the catch clause of a try/catch which surrounds the failed insert statement.  It doesn't work, as the entry into Error_Detected__c is rolled back along with the failed insert.

 

2.  Call a future menthod to insert an entry into Error_Detected__c  in the catch clause of a try/catch which surrounds the failed insert statement.  It doesn't work, as the entry into Error_Detected__c is rolled back along with the failed insert.

 

3.  Call out to a web service in the catch clause of a try/catch which surrounds the failed insert statement.   The web service would do the insert into Error_Detected__c.  This fails with a message about needing to commit or rollback before making a callout, even if the very first statement in the Submit method is a SavePoint and the very last statement before the callout is a rollback to that savepoint.

 

I must be missing something completely obvious.  Has anyone implemented a successful error logging mechanim for DML that is triggered by a user action in VF pages?

digamber.prasaddigamber.prasad

Hi,

 

We are using Async call for log entry and working fine for uw. could you please share your trigger and your class where you are trying to log failure message.

ArleneArlene

Thanks for responding!  I think I've reduced the code to the minimum possible so you won't have to look at so much.  There are both workflows and a trigger under the insert, but I don't think that makes any difference due to the rollback.    The Insert I'm forcing to fail (for testing) is in a method in a custom controller class.  The method is invoked from this VF statement:

 

<apex:commandButton value="Submit" action="{!submit}" styleClass="nextSubmit" />

 

The controller method and referenced attribute looks like this:

 

    public Claim__c clm {get; private set;}

 

    public PageReference submit() {
        Savepoint sp = Database.setSavepoint();
        try {
            this.clm.id = '123'; // this is only here to cause the failure
            insert this.clm;
        } catch (Exception e) {
             Database.Rollback(sp);
             ErrorLogging.LogErrorDetected (e);
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Unable to submit your claim.'));

            return null;
        }
        return null;  // normally returns a reference to another page instead
    }

 

The ErrorLogging class looks like this:

 

global class ErrorLogging {

    public static void LogErrorDetected (Exception e) {
        ErrorLoggingConnector.ErrorLogging log = new ErrorLoggingConnector.ErrorLogging();
        log.Sessionheader = new ErrorLoggingConnector.SessionHeader_element ();
        log.SessionHeader.sessionId = UserInfo.getSessionId();
        log.logError (e.getLineNumber(), e.getMessage(), e.getStackTraceString(), e.getTypeName());

        // re-throw the error so it can be handled by the caller
        throw e;
    }

    webService static void logError (Integer lineNumber, String message, String stackTrace, String exceptionType) {
        Error_Detected__c newError = new Error_Detected__c (
            Line_Number__c = lineNumber,
            Message__c = message,
            Stack_Trace__c = stackTrace,
            Exception_Type__c = exceptionType );
        insert newError;
    }
}

 

And the ErrorLoggingController was created the WSDL for the ErrorLogging class and not modified.

 

Even this, executed in an Anonymous Window gives the same error:

 

claim__c clm;
Savepoint sp = Database.setSavepoint();
try {
  clm.id = '123'; // this is only here to cause the failure
  insert clm;
} catch (Exception e) {
  Database.Rollback(sp);
  ErrorLogging.LogErrorDetected (e);
}

 

And the exact error is:

 

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.