+ Start a Discussion
TrickTrick 

Visual force constructor doubt

Hi Friends,

 

As far as I know from this forum,constructor gets fired as soon as browser loads the page.If that is correct then I should be able to invoke getgreetings getter method and see greeting message .However,I get an error message

 

System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Account.Name.

 

My question is if the constructor has been executed when the page has been loaded then I should be able to invoke grettings getter method and see results.

 

As per me constructor has retreived account record in the current context and passed it to the acct variable and then I am accessing the name field in the getter method.But when I invoke getter method in the visual page then I get the above exception.Why.Your suggestions are most welcome   

 


 

 

public class myControllerExtension {

    private final Account acct;
    
    // The extension constructor initializes the private member  
    
    // variablae acct by using the getRecord method from the standard  
    
    // controller.  
    
    public myControllerExtension(ApexPages.StandardController stdController) {
        this.acct = (Account)stdController.getRecord();
    }

    public String getGreeting() {
        return 'Hello ' + acct.name + ' (' + acct.id + ')';
    }
}

 

 

 

 

<apex:page standardcontroller="account" extensions="mycontrollerextension" >

 

 I have invoked the greeting getter method by invoking{!greeting}; 

 

</apex:page>

 

 

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
jwetzlerjwetzler

When you use the standard controller, Visualforce pages will automatically construct a SOQL query with all of the referenced fields on your page, and the getRecord() method returns the record to you with all of the fields from your page populated.

 

In your example page, you are not referencing any account fields, so the record that is returned to you via the getRecord() method will only have the id field available.  Just like if you were to create a SOQL query like select id from Account where id :='xxxxxxxx' and then try to reference your account's name field in apex, you would get the exact same SObjectException because it was not selected in your query.

 

So you have two ways of getting around this.  Either you can query for the account yourself in your extension, grabbing the fields that you need.  Or you can force the standard controller to pick up these field references by "hiding" them on your Visualforce page.

 

Something like:

<apex:outputPanel style="display:none">

 {!account.name}

</apex:outputPanel>

All Answers

jwetzlerjwetzler

When you use the standard controller, Visualforce pages will automatically construct a SOQL query with all of the referenced fields on your page, and the getRecord() method returns the record to you with all of the fields from your page populated.

 

In your example page, you are not referencing any account fields, so the record that is returned to you via the getRecord() method will only have the id field available.  Just like if you were to create a SOQL query like select id from Account where id :='xxxxxxxx' and then try to reference your account's name field in apex, you would get the exact same SObjectException because it was not selected in your query.

 

So you have two ways of getting around this.  Either you can query for the account yourself in your extension, grabbing the fields that you need.  Or you can force the standard controller to pick up these field references by "hiding" them on your Visualforce page.

 

Something like:

<apex:outputPanel style="display:none">

 {!account.name}

</apex:outputPanel>

This was selected as the best answer
TrickTrick

Thanks Jweltzer,

 

So It means I need to have account field named  name in the visual force page to use it any where in the class.So in order to use name field in the getter method I need to have it in the visual force page.Is that correct.?

 

I am not clear about the explanation on the populated field.

 

Did  u mean that as soon as the visual force page is loaded, the fields on the page are  populated with the values from the database and then constructor gets fired which retrieves the name field value through the getrecord()  method and then we can use it in the getter method .Am I correct on that.I really need to understand this correctly to write programs properly.

 

I appreciate you for enhancing my knowledge

 

Thanks,

Trick 

 

 

 

 

jwetzlerjwetzler

Yes you are correct, you need to have the field on your page if you want to use it in your class.

 

This doesn't really have much to do with your constructor.  When you use a standardController, right when you request the page, we generate a SOQL query that is made up of only the fields that are on your page, and we execute that query and hold on to the record that's returned by that query.

 

Your extension is calling the standardController's getRecord() method in the constructor, so what it's getting is the record from the result of that initial query.  This means that you only have access to the fields that are on your page, because that's all that is in the constructed SOQL query.  So if you want to use a field anywhere in your extension (doesn't matter if it's a getter or an action method or anything else), you must either have that field somewhere on your page so that it gets queried for on initial page load, or you need to execute your own separate query for the record somewhere in your extension, and use that record instead of the one you are getting from the standardController.

TrickTrick

I think I got your point.Let me see if I am correct. As soon as the page is loaded,standard controller executes a default getter method(which in our case would be account getter method) which queries the fields on the page and returns a result.The constructor of the extension class is responsible for getting the record from the initial query through GetRecord() method of the standard controller and then we can access any of the field names which are a part of the query anywhere in the extension class..

 

 

Whether I am right or wrong I am going to disturb you any further because you have already explained a lot.

 

Thanks,

Trick

jwetzlerjwetzler

There is no "default getter method".  The standard controller simply executes a query and stores off the result right when the page is requested.

 

The extension class can call the getRecord() method whenever, doesn't have to be in the constructor, although the constructor is the only point that you actually have access to the standardController object, so yes that's generally when people will call the getRecord() method and store it off in the extension class.

 

Other than that it sounds like you've got it.

TrickTrick

Every standard controller includes a getter method that returns the record specified by the id query string parameter in the page URL. This method allows the associated page markup to reference fields on the context record by using {!object} syntax, where object is the lowercase name of the object associated with the controller. For example, a page that uses the Account standard controller can use {!account.name} to return the value of the name

 field on the account that is currently in context.

 

I have taken the above lines from the help section on the standard controller account.If you carefully read first line given above, you will understand what I am trying to say.

 

Every standard controller includes a getter method that returns the record specified by the id

query string parameter in the page URL.

 

This means that internally system executes getter method which returns a result through queries.I will look for more info on this if I get more info I will come back to you.

 

Thanks Trick

 

 

 

 

TrickTrick

This was possible because the Account standard controller includes a getter method named getAccount

 that returns the specified account record. We can mimic this functionality in a custom controller with the following code:-

 

In the below given code they have actually used standardcontroller method getaccount()(which I called a default getter method in our example).They are actually showing how the standardcontroller getccount() method queries the fields on our page before returning the result.

 

I hope what I am saying makes some sense.

 

Thanks,

Trick

 

 

    public String getName() {
        return 'MyController';
    }

    public Account getAccount() {
        return [select id, name from Account 
                 where id = :ApexPages.currentPage().getParameters().get('id')]; 
    } 
}