You need to sign in to do that
Don't have an account?
Mike Ferraro
Longtime Apex Trigger failing after 8+ years... help!
Hi Everyone, recently a time based workflow has started throwing an error after working since 2012. This process triggers a checkbox field that creates a new opportunity for contracts expiring in 120 days.
Error:Apex trigger UpdateAccountDummyVariable caused an unexpected exception, contact your administrator: UpdateAccountDummyVariable: execution of BeforeUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0015000000Oa1XaAAJ; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CreateOpportunity: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0015000000Oa1Xa) is currently in trigger CreateOpportunity, therefore it cannot recursively update itself: [] Trigger.CreateOpportunity: line 21, column 1: []: Trigger.UpdateAccountDummyVariable: line 9, column 1
Here are the two triggers referenced:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
trigger CreateOpportunity on Account (before update) {
List<Opportunity> o = new List<Opportunity>();
for (Account thisAccount : Trigger.new) {
// A workflow rule will enable dummy_COW variable which in turn will tell the trigger to create the opportunity.
if (thisAccount.dummy_CreateOpportunityWorkflow__c) {
o.add (new Opportunity (
Name = thisAccount.name + ' 2020 Renewal',
OwnerId = thisAccount.OwnerID,
Probability = 15,
Opportunity_Value__c = thisAccount.Current_Contract_Value__c,
Expiring_Contract_Value__c = thisAccount.Current_Contract_Value__c,
Description = 'Auto-created by workflow.',
Renewal__c = true,
CloseDate = date.today()+120,
Current_Contract_Expiration__c = date.today()+120,
AccountId = thisAccount.id,
StageName = 'Analysis Needed'));
}
if (!o.isEmpty()) {
insert o;
// clear the variable so subsequent edits do not create a new opportunity.
thisAccount.dummy_CreateOpportunityWorkflow__c = false;
} }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
trigger UpdateAccountDummyVariable on Contract (before update) {
for (Contract thisContract : Trigger.new)
{
if (thisContract.Dummy_Create_New_Opportunity_Workflow__c)
{
Account a = new Account(id = thisContract.AccountId);
a.Dummy_CreateOpportunityWorkflow__c = true;
update a;
thisContract.Dummy_Create_New_Opportunity_Workflow__c = false;
}
}
}
Thanks for any suggestions!
Mike
Error:Apex trigger UpdateAccountDummyVariable caused an unexpected exception, contact your administrator: UpdateAccountDummyVariable: execution of BeforeUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0015000000Oa1XaAAJ; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CreateOpportunity: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0015000000Oa1Xa) is currently in trigger CreateOpportunity, therefore it cannot recursively update itself: [] Trigger.CreateOpportunity: line 21, column 1: []: Trigger.UpdateAccountDummyVariable: line 9, column 1
Here are the two triggers referenced:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
trigger CreateOpportunity on Account (before update) {
List<Opportunity> o = new List<Opportunity>();
for (Account thisAccount : Trigger.new) {
// A workflow rule will enable dummy_COW variable which in turn will tell the trigger to create the opportunity.
if (thisAccount.dummy_CreateOpportunityWorkflow__c) {
o.add (new Opportunity (
Name = thisAccount.name + ' 2020 Renewal',
OwnerId = thisAccount.OwnerID,
Probability = 15,
Opportunity_Value__c = thisAccount.Current_Contract_Value__c,
Expiring_Contract_Value__c = thisAccount.Current_Contract_Value__c,
Description = 'Auto-created by workflow.',
Renewal__c = true,
CloseDate = date.today()+120,
Current_Contract_Expiration__c = date.today()+120,
AccountId = thisAccount.id,
StageName = 'Analysis Needed'));
}
if (!o.isEmpty()) {
insert o;
// clear the variable so subsequent edits do not create a new opportunity.
thisAccount.dummy_CreateOpportunityWorkflow__c = false;
} }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
trigger UpdateAccountDummyVariable on Contract (before update) {
for (Contract thisContract : Trigger.new)
{
if (thisContract.Dummy_Create_New_Opportunity_Workflow__c)
{
Account a = new Account(id = thisContract.AccountId);
a.Dummy_CreateOpportunityWorkflow__c = true;
update a;
thisContract.Dummy_Create_New_Opportunity_Workflow__c = false;
}
}
}
Thanks for any suggestions!
Mike
I can see that recursion is happening between your triggers or workflows. I can guess the flow of execution as :
- UpdateAccountDummyVariable: This trigger executes and updates the Account.
- CreateOpportunity: On Account update in the previous trigger, this trigger executes and updates the Opportunity.
- Now there might be a new Flow, Process Builder or Trigger on Opportunity which updates its parent Account.
- So again the Account Trigger executes and creates the recursion.
To solve this problem we usually use a Static Boolean variable in Class and runs the Trigger method if the variable is true and after the first run we set it to false so recursion won't happen. But it requires to separate your logic from trigger into a public class. That's why it is always recommended not to write logic inside your trigger and use a class with methods instead.Thanks and Regards
Ayush Sharma
Ayush,
Thanks so much for your help on this. I'm new to using Apex and don't come from a technical background... can you or someone outline the steps I would take to fix these? Do I need to write new triggers or classes, or just alter the above?
Thanks again!
Mike
First, let's create a helper class for Trigger CreateOpportunity:
Now modify your CreateOpportunity Trigger as:
Do the same steps for UpdateAccountDummyVariable as follow:
and Trigger
Please try the above steps. And before doing code make sure to take the backup of your present Triggers.
Try and let me know if it works or not.
Thanks and Regards
Ayush Sharma
Ayush,
Thanks again for your help; it only allowed me to create the class for UpdateAccountDummyHelper; the rest came back as errors:
This is all in a Sandbox I created to work on this. Any ideas what the issues are?
Thanks again!
Mike
Sorry for the inconvenience please try the below code.
Please try and let me know if the error still occurs.
Thanks
Thanks!
Mike
Ayush,
That worked! I'm going to test on Sandbox... I can't thank you enough for your guidance.
Stay safe and healthy.
Mike
You too take care.
If an error occurs again let me know. We will solve this problem don't worry.
Ayush
Everything worked overnight but now I"m having trouble deploying to production. What components do I need to add to the change set? I added both helper classes and the apex triggers but got this:
Thank you!
Mike
@isTest
private class Test_CreateOpportunity {
static testMethod void myOpportunityCreateUnitTest() {
Account a = new Account(Name = 'Test Account', Current_Contract_Value__c=10000);
insert a;
a.dummy_CreateOpportunityWorkflow__c = true;
update a;
List<opportunity> newOpportunity = [SELECT Name, Description, Renewal__c, StageName, Expiring_Contract_Value__c, Current_Contract_Expiration__c, Probability, Opportunity_Value__c, CloseDate
FROM Opportunity
WHERE AccountID = :a.Id];
for (Opportunity o : newOpportunity) {
System.assertEquals('Auto-created by workflow.',o.Description);
System.assertEquals(true,o.Renewal__c);
System.assertEquals(a.Name + ' 2020 Renewal',o.Name);
System.assertEquals('Analysis Needed',o.StageName);
System.assertEquals(15,o.Probability);
System.assertEquals(a.Current_Contract_Value__c,o.Expiring_Contract_Value__c);
System.assertEquals(a.Current_Contract_Value__c,o.Opportunity_Value__c);
System.assertEquals(date.today()+120,o.CloseDate);
System.assertEquals(date.today()+120,o.Current_Contract_Expiration__c);
}
}
}
@isTest
private class Test_UpdateAccountDummyVariable {
static testMethod void updateDummyUnitTest() {
Account a = new Account(Name = 'Test Account');
insert a;
Contract c = new Contract(Name = 'My Test Contract',
AccountID = a.Id,
Total_Contracted_Amount__c = 10000,
Annualized_Cappex_Value__c = 10000,
Included_Product_s__c = 'Cappex',
Unit_Price__c = 15000,
StartDate = Date.today(),
EndDate = Date.today()+365,
ContractTerm = 12);
insert c;
c.Dummy_Create_New_Opportunity_Workflow__c = true;
update c;
List<contract> newContract = [SELECT Name, Dummy_Create_New_Opportunity_Workflow__c
FROM Contract
WHERE Id = :c.Id];
List<account> newAccount = [SELECT Name, Description, Dummy_CreateOpportunityWorkflow__c
FROM Account
WHERE Id = :a.Id];
for (Contract thisContract : newContract) {
System.assertEquals(false,thisContract.Dummy_Create_New_Opportunity_Workflow__c); // after execution make sure it resets to false
}
for (Account thisAccount : newAccount) {
System.assertEquals(false,thisAccount.Dummy_CreateOpportunityWorkflow__c); // after execution make sure it resets to false
}
}
}
Have you tested it in Sandbox first before deploying on Production?
I did! The workflow behaved as expected, I set it up to run last night and it worked correctly!
Mike
If test classes are running successfully in the sandbox then make sure you are uploaded triggers and classes on the Production. By any chance if you have forgotten to add triggers to change set?
Ayush
Mike
The Class is throwing the following error:
Error: Compile Error: Type name already in use: CreateOpportunityHelper at line 7 column 18
Please Update class and Trigger.
Ayush
Hi Ayush,
I updated the Class and Trigger, then Uploaded and Deployed, and got the same error. Any idea where to go from here?
Mike
Try Converting Contract Trigger on After Update:
As I assume we might be updating the Account which is already in the context of Before Account Trigger. I am not sure but lets troubleshoot. I know it gets frustrating sometimes but lets do our best to solve this.
Ayush
Mike
Mike
Mike