+ Start a Discussion
Dogen ZenjiDogen Zenji 

Second upsert statement within same Apex transaction does not fire trigger

Good morning everyone!  Since one cannot create a lookup field to the standard OpportunityLineItem object, you cannot create a parent child relationship between OLIs as you cannot create a lookup to itself.  I am mimicking this relationship by using wrapper classes and setting a text(18) custom field called Parent_OLI_Id__c on the OLI.  Naturally, I have to save the parents first to get back their IDs, then save the children using the returned IDs.  The following method accomplishes this beautifully...

 

 

public static void upsertOLIsFromOLIMs(OpportunityLineItemModel[] olims)

{

OpportunityLineItem[] oliParentsToUpsert = new OpportunityLineItem[0];

//Loop thru incoming OLIMs and extract parents only to upsert array

for(OpportunityLineItemModel olim : olims)

{

if(olim.isParent)

oliParentsToUpsert.add(olim.record);

}

try

{

//Upsert parents

upsert oliParentsToUpsert;

//Loop thru incoming OLIMs again and set parent Id of child records

//which has now been returned from previous upsert call

//Extract children to upsert array

OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0];

for(OpportunityLineItemModel olim : olims)

{

if(olim.isParent)

{

for(OpportunityLineItemModel childOLIM : olim.childRecords)

{

childOLIM.record.Parent_OLI_Id__c = olim.record.Id;

oliChildrenToUpsert.add(childOLIM.record);

}

}

}

//Upsert children

upsert oliChildrenToUpsert;

}

catch(DmlException dmle)

{

...

}

}


 

 

This method is called from a Save button on a VisualForce page.  Enough background, now let's get to the problem.  I have a trigger that runs after insert and after update of OLIs but is only firing on the first upsert statement of the method above, when upserting the parents.  To prevent infinite recursion I am using the usual trick of setting a static Boolean to true the first time the trigger is run.  While grasping at straws, I thought this might be causing the problem so I removed the static Boolean condition and let the trigger run ad infinitum.  Every single System.debug statement outputted still showed that only parent OLIs were ever being passed to the trigger.  Has anyone seen anything like this?  I hope it's just because it's late and I'm doing something wrong...

 

Message Edited by Dogen Zenji on 03-12-2010 02:51 AM
Message Edited by Dogen Zenji on 03-12-2010 02:54 AM
Message Edited by Dogen Zenji on 03-12-2010 03:00 AM
Best Answer chosen by Admin (Salesforce Developers) 
Dogen ZenjiDogen Zenji

I figured it out; of course I was doing something wrong and went looking for the solution in the wrong place.  It was my trigger that was wrong, not the code I posted.  Originally, the trigger called one method which used one static Boolean to break out of infinite recursion.  The solution was to check to see if the current batch of OLIs were parents or children, then call one of two methods that each had its own static Boolean as below...

 

 

trigger OpportunityLineItemAIAUADAR on OpportunityLineItem (after delete, after insert, after undelete, after update)

{

if(Trigger.isInsert || Trigger.isUpdate)

{

if(Trigger.size > 0)

{

if(Trigger.new[0].Parent_OLI_Id__c == 'PARENT' || Trigger.new[0].Parent_OLI_Id__c == 'STANDALONE')

OpportunityLineItemModel.upsertWOPsFromParentOLIs(Trigger.new);

else

OpportunityLineItemModel.upsertWOPsFromChildOLIs(Trigger.new);

}

}

else if(Trigger.isDelete)

OpportunityLineItemModel.deleteWOPsFromOLIs(Trigger.old);

}

 

public static void upsertWOPsFromParentOLIs(OpportunityLineItem[] olis)

{

if(!OpportunityLineItemModel.didParentTriggerRun)

{

OpportunityLineItemModel.didParentTriggerRun = true;

OpportunityLineItemModel.upsertWOPsFromOLIs(olis);

}

}

 

public static void upsertWOPsFromChildOLIs(OpportunityLineItem[] olis)

{

if(!OpportunityLineItemModel.didChildTriggerRun)

{

OpportunityLineItemModel.didChildTriggerRun = true;

OpportunityLineItemModel.upsertWOPsFromOLIs(olis);

}

}

 

 

 

 

All Answers

rksfdcrksfdc

This line OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0]; doesn't it set the array to just 1? you only get array index of 1 always. For ur example it has to keep increasing

 

  SObject[] sObjects = new SObject[2];
// Add the accounts to the SObject array
sObjects[0] = account1;
sObjects[1] = account2;

- RK

Dogen ZenjiDogen Zenji

Thanks RK for your assistance!  Unfortunately your suggestion is incorrect because the code I posted is working fine; the children are upserted correctly.  It's the fact that the trigger doesn't fire when upserting the children that is the problem.  The line you refer to uses array notation instead of list notation.

 

OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0];

 

... is equivalent to...

 

List<OpportunityLineItem> oliChildrenToUpsert = new List<OpportunityLineItem>();

 

See Apex docs here regarding array notation.

Dogen ZenjiDogen Zenji

I figured it out; of course I was doing something wrong and went looking for the solution in the wrong place.  It was my trigger that was wrong, not the code I posted.  Originally, the trigger called one method which used one static Boolean to break out of infinite recursion.  The solution was to check to see if the current batch of OLIs were parents or children, then call one of two methods that each had its own static Boolean as below...

 

 

trigger OpportunityLineItemAIAUADAR on OpportunityLineItem (after delete, after insert, after undelete, after update)

{

if(Trigger.isInsert || Trigger.isUpdate)

{

if(Trigger.size > 0)

{

if(Trigger.new[0].Parent_OLI_Id__c == 'PARENT' || Trigger.new[0].Parent_OLI_Id__c == 'STANDALONE')

OpportunityLineItemModel.upsertWOPsFromParentOLIs(Trigger.new);

else

OpportunityLineItemModel.upsertWOPsFromChildOLIs(Trigger.new);

}

}

else if(Trigger.isDelete)

OpportunityLineItemModel.deleteWOPsFromOLIs(Trigger.old);

}

 

public static void upsertWOPsFromParentOLIs(OpportunityLineItem[] olis)

{

if(!OpportunityLineItemModel.didParentTriggerRun)

{

OpportunityLineItemModel.didParentTriggerRun = true;

OpportunityLineItemModel.upsertWOPsFromOLIs(olis);

}

}

 

public static void upsertWOPsFromChildOLIs(OpportunityLineItem[] olis)

{

if(!OpportunityLineItemModel.didChildTriggerRun)

{

OpportunityLineItemModel.didChildTriggerRun = true;

OpportunityLineItemModel.upsertWOPsFromOLIs(olis);

}

}

 

 

 

 

This was selected as the best answer
rksfdcrksfdc
Nice Mr. 9869!!
Message Edited by rksfdc on 03-12-2010 10:01 AM