You need to sign in to do that
Don't have an account?
Maria22
OrderTrigger: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object
I got stuck at one place on one of my requirement on which I am working on.
My use case is as follows:
I have done the scenario and code is also getting saved but getting System.NullPointerException:Attempt to de-reference a null Object when try to change the status of an upgrade order from a value say"Order-Placed" to "Cancelled"
Below is my Apex Class which runs in before update from Apex Trigger:
Also,attached is the screenshots
Kindly help me.
Any help will be greatly appreciated.
Many thanks
My use case is as follows:
SCENARIO 1: Close Opportunity when Upgrade Order is cancelled GIVEN a a person account record in Salesforce AND the has an open upgrade opportunity record in Salesforce AND the opportunity record type equals "Upgrade Opportunity" AND the opportunity stage is not "Closed - Won" WHEN places an upgrade order AND the status of the upgrade order has been changed to Cancelled THEN the open upgrade opportunity Stage field is set to "Closed - Lost" AND all other related opportunities that also meet this scenario criteria (Upgrade Opportunity, not Closed-Won) are set to "Closed - Lost"
I have done the scenario and code is also getting saved but getting System.NullPointerException:Attempt to de-reference a null Object when try to change the status of an upgrade order from a value say"Order-Placed" to "Cancelled"
Below is my Apex Class which runs in before update from Apex Trigger:
public with sharing class OrderTriggerService extends TriggerService { public void updateOpportunityStage(){ Set<Id> setIds = new Set<Id>(); Map<Id,Order> orderOldMap =(Map<Id,Order>)oldMap; Map<Id,Order> orderNewMap=(Map<Id,Order>)newMap; Set<Opportunity> updateOppties=new Set<Opportunity>(); DateTime statusChange= System.now()-90; for (Order childObj : (List<Order>) newList) { if(childObj.Account_Record_Type_Name__c == 'Recipient' && childObj.Record_Type_Dev_Name__c == 'Upgrade_Order'){ setIds.add(childObj.AccountId); } } if (setIds.isEmpty()) { return; } Map<ID, Account> parentAccts = new Map<Id, Account>( [select id, Upgrade_Order_Booked_Date__c, Upgrade_Order_Status__c, Order_Cancellation_Reason__c,Upgrade_Order_Number__c,Order_Cancellation_Date__c, (select id, Name, Booked_Date__c, Status ,Order_Cancellation_Reason__c,Oracle_Order_Number__c,Order_Cancellation_Date__c from Orders ) from Account where id in :setIds]); System.debug('updateOrderUpgrade parentAccts: ' + parentAccts); Map<Account, Order> accountToLatestOrder = new Map<Account, Order>(); for (Account acc : parentAccts.values()) { if (acc.orders.isEmpty() == false) { accountToLatestOrder.put(acc, acc.orders[0]); } } for(Account acc : [select id, Upgrade_Order_Booked_Date__c, Upgrade_Order_Status__c, Order_Cancellation_Reason__c,Upgrade_Order_Number__c,Order_Cancellation_Date__c, (select Id,Name,closedate,amount,StageName,Oracle_Order_Number__c,Status_Last_Changed_On__c from opportunities where Record_Type_Dev_Name__c='Upgrade_Opportunity') from Account where id in : setIds]){ for(Order orders : accountToLatestOrder.values()){ for(Opportunity opps : acc.opportunities){ if(opps.StageName<>'Upgrade-Closed Won' && orders.Status!=orderOldMap.get(orders.Id).Status && orders.Status=='Cancelled'){ opps.StageName='Upgrade - Closed Lost'; } System.debug('updateOpportunityStage Opportunity: ' + opps); updateOppties.add(opps); } } } List<Opportunity> updateopps=new List<Opportunity>(updateOppties); update updateopps; } }
Also,attached is the screenshots
Kindly help me.
Any help will be greatly appreciated.
Many thanks
I would like to include few points to my question above
1. I mentioned in my question above that code is running in before update call
2. I am getting error in below line
Kindly help
I would put a debug statement to confirm, then put a check in before using an orderOldMap (containsKey) to ensure you get a record back before you try to access its values. Hope that helps!
Thanks again for your response.
I really appreciate you are taking time for my questions. Can you do me a favour. If possible can you help in tweek/modify the code which I have written. That will be a great help for me.
Kindly help.
Many thanks in advance
I can't speak to the effects of not finding orders.Id in the orderOldMap (i.e. whether that logic is "acceptable") - but by checking it this way, you short-circuit it to confirm that it exists before trying to get the status, as those conditional statements will evaluate in order, and it will exit as soon as a condition is NOT met. Hope that helps, and good luck.
Thanks for your response again.
I tried your code and put inside my if condition.No wthe order is getting saved when I am trying to change the status from any thing to Cancelled and I am not getting null pointer exception.But the problem still lies the same.
OPportunity with record type=Upgrade Opportunity and if that oppty is linked with the account to which upgrade order is linked and status of Opportunity is not Closed Won then ideally those opportunities should be set to Clsed Lost.But nothing is happening on opportunities.I can see the same old status on Opportunity.
I don't know whats going wrong with code,I am afraid now.I am running out of time also.
Kindly help.
Many thanks in advance
I checked the debug logs. In debug logs I can see orders.Id is null
Where my logic is going wrong.What I am doing wrong or what should I do in order to rectify the same.
KIndly help.
Many thanks in advance
Actually we are using Event-Dispatcher model for our coding where we have one trigger and one dispatcher and one service class. Trigger.OldMap is our trigger old map list. I am monitoring debug logs in developer console
Below is OrderTriggerDispatcher class
Below is my OrderTriggerService class
For current requirement I have added updateOpportunityStage() method in OrderService Class.
Kindly let me know if you need any more inputs from my side.
I guess or assume that problem is The link between Accounts,Orders and Opportunities are not getting fir correctly.
Kindly help.
Many thanks in advance
I guess you may need to look into Trigger Dispatcher and Trigger Service class as well.So I am putting those classes also.
Below is Trigger Service class:
Below is trigger Dispatcher
Kindly help.
Many thanks in advance
The query starting on line 18 that is retrieving orders appears to be such that it COULD retrieve order that aren't in the trigger's scope, so you would need to anticipate that oldMap may not contain the id for every order in acc.orders. That means the null check is still relevant, so you'll still want that. I'd also expect to see more than one entry in the debug log, and many of them would be null, because you're updating one order, so the trigger scope is one order - and that query is designed to return all orders under the account, correct?
Maybe also debug "updateOppties" to see what's in there? Does line 48 produce any output that isn't null?
Below is the debug logs for updateOppties
Oldmap returning null but updateoppties returns some values
Is there any way we can connect online and can discuss this issue. I am really bothering now and afraid about the same.
If possibel we can connect in some way and discuss.
Kindly help.
Mnay thanks in advance
Yes you are damn correct.I designed the query to return all the orders of record type=upgrade order for an accounnt and if any of those upgrade order status changed to Cancelled then all the opportunities linked to that account where opportunity record type=Upgarde Opportunity and status of opportunity is not equals to closed won will becomes Closed Lost.
Kindly help.
Many thanks in advance
I think what will happen when you start adding only the opportunities that should be updated is that you'll see that at the end of the loop, System.debug('updateOppties: ' + updateOppties) will show an empty list, which is why nothing is being changed (and why you're probably almost ready to put your fist through your laptop screen).
I don't think there's anything spooky going on, but I can tell you that what I would do output the entire opportunity list that's being returned by that query and watch them walk through that bit of logic. I strongly recommend using checkpoints in the dev console to help in diagnosing this further: https://trailhead.salesforce.com/en/modules/apex_basics_dotnet/units/debugging_diagnostics. It will save you a LOT of time with that exercise.
I've been there with the frustration and the pressure. As for chatting, I love a good bug hunt, but I'm afraid I'm mostly hanging out with family today. A little dev boards action I can handle, but I don't think I'm up for a chat. :-) I will check in from time to time, though, to see how it's going and will help if I can.
I will try what you said and update in same tread if I get any success or even not then also I will update.
Hope for the best and best of luck to me.
Mnay thanks
I have fixed my code and is working fine as per requirement. I needed to refactor my code and now its working fine. Currently I am facing one issue.When I am changing upgrade order status to Cancelled then I am receiving error like
Below is my new service class whoich is working fine
I checked in sandbox and found there is a Validation rule on Opportunity object for "Oracle_Status__c" field.
Validation rule:
which means when changing a status or stagename of opportunity becomes Upgrade-Closed Won then oracle status field shpould not be blank.
But in my requirement there may be chance an oppty have some value with oracle status field as null.and if my user change status of order to cancel then trigger will try to update oppty to Upgrade Closed won and hits error as field exception because oracle status field may be blank for that oppty record.
Can you help me to track this in code.How can we track the same in my code. Is there any way I can respect VR in my apex class shown above.
I hope you will respond and help me as you were doing till now.
Kindly help.
Many thanks in advance
BUT, consider what you're doing there. When a user confronts that rule, they can make a decision about what value to put in there, if that's an appropriate decision for their user and that record. When you hit it programmatically, you can either code around it, or you can allow the user to encounter the error.
If the error were on orders, I'd recommend using addError(), but in this trigger, Opportunities aren't in the context, so that won't work. Ultimately, this is a data quality issue, which leaves your choices fairly straightforward:
- Allow the error to occur, and provide the users documentation for what to do when they encounter it.
- Figure out an appropriate "oracle status" for a default behavior (or replicate the business logic for assigning it a value), and then assign it in lines 47/48-ish so they never encounter the error
- Use a try/catch statement and just swallow/debug the error - which I definitely do NOT recommend. Including in the interest of completeness. :-)
Hope that helps. Seems like it's getting pretty close now.