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
TC AdminTC Admin 

Apex Code to refresh child items error " Attempt to de-reference a null object An unexpected error has occurred. Your development organization has been notified."

Hi all. i'm trying to create a button that refreshes the child opportunity products when discounts are changed on a opportunity.

The Apex code ges a list of the child opportunity products and updates them.
The Visual Force button runs the method. howveer i get an error saying:

Attempt to de-reference a null object 
An unexpected error has occurred. Your development organization has been notified.


Any idea what I am doing wrong?
Apex Class
PUBLIC CLASS OpportunityProductCostRefreshController 
{
    //add an instance variable for the standard controller
    private ApexPages.StandardController controller {get; set;}
    
    // add the instance for the variables being passed by id on the url
    public opportunity OP {get;set;}
    
    // set the id of the record that is created -- ONLY USED BY THE TEST CLASS
    public ID newRecordId {get;set;}
    
    //Add the variable for the list being queried
    PUBLIC LIST <OpportunityLineItem> GetItemsList {get;set;}   

    // Initialize the controller
    PUBLIC OpportunityProductCostRefreshController(ApexPages.StandardController ctrl)
    {     
        //initialize the standard controller
        this.controller = controller;
        // load the current record
        OP = (Opportunity)controller.getRecord();
    }

    // method called from the VF's action attribute to refreshing the op lines
    public PageReference RefreshOpLines() 
    {
    
        // setup the save point for rollback
        Savepoint sp = Database.setSavepoint();

        TRY
        {
        // Get the list of opportunity line items we want to refresh costs for
        GetItemsList = [
            SELECT Id,OpportunityId, productcode, Quantity, unitprice
            FROM OpportunityLineItem OPL
            WHERE       Opportunityid= :OP.id ORDER BY  productcode ASC
            ];
            {
            UPDATE GetItemsList ;
            return null;
            }
        }
        catch (Exception e){
         // roll everything back in case of error
        Database.rollback(sp);
        ApexPages.addMessages(e);

        }
            
        return new PageReference('/'+OP.id);
    }
}

VF Page
<apex:page standardController="Opportunity"
     extensions="OpportunityProductCostRefreshController"
     action="{!RefreshOpLines}">
     <apex:pageMessages />
</apex:page>

​​​​​​​
Steven NsubugaSteven Nsubuga
The error is in your controller's constructor, particularly the line this.controller = controller; you are setting the variable to itself rather than to the argument in the constructor.
It should be this.controller = ctrl;
I have made the change below.
PUBLIC CLASS OpportunityProductCostRefreshController 
{
    //add an instance variable for the standard controller
    private ApexPages.StandardController controller {get; set;}
    
    // add the instance for the variables being passed by id on the url
    public opportunity OP {get;set;}
    
    // set the id of the record that is created -- ONLY USED BY THE TEST CLASS
    public ID newRecordId {get;set;}
    
    //Add the variable for the list being queried
    PUBLIC LIST <OpportunityLineItem> GetItemsList {get;set;}   

    // Initialize the controller
    PUBLIC OpportunityProductCostRefreshController(ApexPages.StandardController ctrl)
    {     
        //initialize the standard controller
        this.controller = ctrl;
        // load the current record
        OP = (Opportunity)controller.getRecord();
    }

    // method called from the VF's action attribute to refreshing the op lines
    public PageReference RefreshOpLines() 
    {
        // setup the save point for rollback
        Savepoint sp = Database.setSavepoint();

        TRY
        {
        // Get the list of opportunity line items we want to refresh costs for
        GetItemsList = [
            SELECT Id,OpportunityId, productcode, Quantity, unitprice
            FROM OpportunityLineItem OPL
            WHERE       Opportunityid= :OP.id ORDER BY  productcode ASC
            ];
            {
            UPDATE GetItemsList ;
            return null;
            }
        }
        catch (Exception e){
         // roll everything back in case of error
        Database.rollback(sp);
        ApexPages.addMessages(e);

        }
            
        return new PageReference('/'+OP.id);
    }
}

 
TC AdminTC Admin
Hi Steven, THANK YOU!! I have been looking at it for hours and could not see the woods through the trees.
Now I just need to get the button to go back to the orginal page again.

Thank you.
Steven NsubugaSteven Nsubuga
Hi TC, you should remove the return null line below UPDATE GetItemsList ;
I have commented it out below
PUBLIC CLASS OpportunityProductCostRefreshController 
{
    //add an instance variable for the standard controller
    private ApexPages.StandardController controller {get; set;}
    
    // add the instance for the variables being passed by id on the url
    public opportunity OP {get;set;}
    
    // set the id of the record that is created -- ONLY USED BY THE TEST CLASS
    public ID newRecordId {get;set;}
    
    //Add the variable for the list being queried
    PUBLIC LIST <OpportunityLineItem> GetItemsList {get;set;}   

    // Initialize the controller
    PUBLIC OpportunityProductCostRefreshController(ApexPages.StandardController ctrl)
    {     
        System.debug('controller constructor');
        //initialize the standard controller
        this.controller = ctrl;
        // load the current record
        OP = (Opportunity)controller.getRecord();
    }

    // method called from the VF's action attribute to refreshing the op lines
    public PageReference RefreshOpLines() 
    {
        System.debug('controller RefreshOpLines');
        // setup the save point for rollback
        Savepoint sp = Database.setSavepoint();

        TRY
        {
        // Get the list of opportunity line items we want to refresh costs for
        GetItemsList = [
            SELECT Id,OpportunityId, productcode, Quantity, unitprice
            FROM OpportunityLineItem OPL
            WHERE       Opportunityid= :OP.id ORDER BY  productcode ASC
            ];
            {
            UPDATE GetItemsList;
            //return null;
            }
        }
        catch (Exception e){
         // roll everything back in case of error
        Database.rollback(sp);
        ApexPages.addMessages(e);

        }
            
        return new PageReference('/'+OP.id);
    }
}


 
TC AdminTC Admin
Hi,
That does not work. The whole method does not run if i remove that line.
Steven NsubugaSteven Nsubuga
Why would you have that line return null; and then also have return new PageReference('/'+OP.id); ?
You need to sort it out, use debug statements to verify which of those will actually run. My assumption looking at your code was that the return null would run after the update statement and if so then the final return statement would never get executed.
You only need 1 of those statements. 
TC AdminTC Admin
Hi Steven.  The button needs to update the line then return back to the orginal object page. If I remove the return Null; then the button loads the orginal page again but does not do the actual line update. If I leave the return null; it does the update but loads a blank SF page so i have to go back to the orginal page manually.  I've used this page ref befoer on other buttons to load the orginal page ofter inserting new lines.

Any ideas how I can do both?