5

Basically what I'm trying to do is to insert an error record (custom object) when an error occurs.

To test if this is working I created a simple test where I try inserting a contact that has a reference to an account that I have just deleted. This throws an exception, which I catch. Then I create an error record with information from the exception.

Now, if I do not have a reentrancy flag in the class to run from the test my error record gets saved to the database (in fact it gets saved twice for a contact insert, once for beforeInsert and once for afterInsert). But if I have the reentrancy flag, it doesn't get saved at all, even though I see in the logs that it is saving it!

I actually created a simple test to reproduce this in the project where I am testing some of my error handling stuff. You can go to https://github.com/SalesforceFoundation/Error_Handling, install it in a brand new org, and try running the test in ERR_Handler_TEST.cls. The test will fail because it does not find any error record, even though you'll see in the logs that it is saving it.

If you comment out the lines in the ParentAccountUpdater class that use the parentAccsAlreadyUpdated variable (3, 7, 29 and 30) you will see that the test fails too, but now it's because it finds two records instead of one.

Any ideas of why this might be happening?


EDIT - To clarify, the only files that intervene in this scenario are ERR_Handler_TEST.cls, ERR_Handler.trigger, and ParentAccountUpdater.cls. The rest of the files can be ignored, since they are there for some other tests I was working on.


EDIT - To summarize:

A. If parentAccsAlreadyUpdated flag in ParentAccountUpdater class is commented out:

Assertion Failed: Expected: 1, Actual: 2 (in line 53)

--> This makes sense. One record saved for the exception thrown during the before insert and one for the after insert

B. If parentAccsAlreadyUpdated flag in ParentAccountUpdater class is NOT commented out:

Assertion Failed: Expected: 1, Actual: 0 (in line 53)

--> This does NOT make sense. One record should have been saved. And we see in the logs that it's trying to save it:

[...]Database.insert(LIST<SObject>, Boolean)
[...]|DML_BEGIN|[26]|Op:Insert|Type:SObject|Rows:1

The only explanation I can give is that the whole thing gets rolled back.

10
  • 1
    Could it simply be that you are using insert records at line 5 in the helper class instead of a database.insert(records,false). The simple insert will rollback all changes to the database on the error for the entire transaction correct?
    – Eric
    Jan 3, 2014 at 21:03
  • The Helper class is not used at all. That's just there for some other tests I was running. The only files that are being used for this test are ERR_Handler_TEST, ERR_Handler.trigger, and ParentAccountUpdater.cls.
    – ceiroa
    Jan 3, 2014 at 21:05
  • I'm not seeing the need for a before trigger here. It seems in all cases you are performing a DML.
    – greenstork
    Jan 3, 2014 at 21:07
  • Yes, everything works fine if I only have a beforeInsert or an afterInsert, and no "parentAccsAlreadyUpdated" flag in ParentAccountUpdater. However, I have it designed this way to simulate a similar scenario we have in the Cumulus project. (Which BTW, I'd love to have you look at, if you have some time, David :)
    – ceiroa
    Jan 3, 2014 at 21:11
  • I wonder if it has to do with your method and variable being static. As a static variable, it's not a class level property. Have you tried referencing it by ParentAccountUpdater.parentAccsAlreadyUpdated?
    – greenstork
    Jan 3, 2014 at 22:28

2 Answers 2

1

The very bright David Habid (creator of Volunteers for Salesforce) has helped me figure it out. What seems to be happening is as follows.

Let's say that you have 3 records that you want to insert with a Database.insert call. If one of them fails Salesforce will roll back all database-related operations and then do the insert again with the 2 that succeeded. HOWEVER, if you have a reentrancy flag, the value of the flag will not be rolled back (after all roll backs affect only the database). Therefore the second time nothing will happen (the reentrancy flag prevents the code from running again).

You see in the logs that the error records are being created, but that is all happening in the first context, which is fully rolled back.

To my knowledge it is not fully documented that this is how the Database methods work, but this seems to be consistent will all the tests that I have been doing.

UPDATE: For some very interesting examples of how #Salesforce's Database.insert method works take a look at these tests.

0

I am in the same situation as yours. Here is a link to my question on developer community: https://developer.salesforce.com/forums/ForumsMain?id=906F0000000D7zuIAC I would be interested to know the resolution to this. Please provide your insights. Thank you!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .