1

I am trying to return a JSON string to my controller for rendering on a Visualforce page. The query builds correctly and the JSON string builds locally within the method buildQuery.

However my top level public string agricultureContacts still returns null. I am confused as it is public.

Clearly I am missing something fundamental here, shouldn't the method assign the string a value?

public class example_Controller {

    public boolean booleanFlag {get; set;}
    public String agricultureContacts {get; set;}


    public PageReference buildQuery(){

        String userQuery = 'SELECT LastName, FirstName FROM Contact WHERE FirstName != null' + ' AND Agriculture__c = ' + booleanFlag;

        List<Contact> returnedContacts = database.query(returnedQuery);
        String agricultureContacts = JSON.serialize(userContacts);

        system.debug(agricultureContacts);

        PageReference pageRef = ApexPages.currentPage();
        return pageRef;
    }         
}
5

You have declared both a local and class variable, remove the local declaration in your method

public class example_Controller {

public boolean booleanFlag {get; set;}
public String agricultureContacts {get; set;}


public PageReference buildQuery(){

    String userQuery = 'SELECT LastName, FirstName FROM Contact WHERE FirstName != null' + ' AND Agriculture__c = ' + booleanFlag;

    List<Contact> returnedContacts = database.query(returnedQuery);
    agricultureContacts = JSON.serialize(userContacts); //CHANGE HERE

    system.debug(agricultureContacts);

    PageReference pageRef = ApexPages.currentPage();
    return pageRef;

}         
}

You had used String in front of agricultureContacts in the method which made it a local variable and the value was assigned to it instead of the class variable with the same name

  • @ManifestDestiny - We have all been there and done that. We tend to revisit once in a while too depending on the day lol... – Eric May 1 '17 at 19:16
4

Adding to Eric's answer, the technical name for what you have done here (declaring a variable with the same name in an inner scope) is called "shadowing".

public class MyClass{
    // This property and class variable (respectively) are declared in the Class' scope.
    // In this example, this is the outermost scope.
    public String myStringVar {get;set;}
    public String myOtherStringVar;

    public MyClass(){
        myStringVar = 'abc';
        myOtherStringVar = null;
    }

    public void myMethod(){
        // These variables have the same name, but are in a sub-scope of the class.
        // These variables are said to "shadow" the variables we've defined in the class scope
        String myStringVar = '123';
        String myOtherStringVar = '456';

        system.debug(myStringVar);        // Will output '123'
        system.debug(myOtherStringVar);   // Will output '456'
    }

    public void myOtherMethod(){
        // Since this method has its own scope, and we haven't shadowed the variables
        //   in this scope...

        system.debug(myStringVar);        // Will output 'abc'
        system.debug(myOtherStringVar);   // Will output null
    }
}

In most languages (I don't have any counterexamples), when we run into a variable name, the system will look for a declaration for that variable name starting in the current scope. If a declaration isn't found in the current scope, the system looks for a declaration in the next larger scope (in this example, the scope of the Class itself). This continues until a declaration is found, and you get an error if you reach the highest-level scope and still haven't found a declaration.

So when you shadowed agricultureContacts, the value was set on the variable instance contained in the scope of your method. agricultureContacts at the class level remains uninitialized, and when you try to get the value, you get null.

In this simple case, Eric's answer (which removes the String keyword from agricultureContacts in your method) is all that needed to be done to get your controller working as expected.

Sometimes, you may want to shadow variables. Maybe agricultureContacts is the most descriptive, most concise name to use, and anything else would be confusing or cumbersome (naming things is, after all, one of the 2 hard problems in computer science...right up there with cache invalidation and off-by-one errors).

In this situation, where you shadow a class-level variable in a method scope (or some sub-scope of a method), you can still access the variable in the class-level scope by using the this keyword.

public void myMethod(){
    // These variables have the same name, but are in a sub-scope of the class.
    // These variables are said to "shadow" the variables we've defined in the class scope
    String myStringVar = '123';
    String myOtherStringVar = '456';

    system.debug(myStringVar);            // Will output '123'
    system.debug(myOtherStringVar);       // Will output '456'

    // Getting at the variable in the Class' outermost scope, when
    //   variables are shadowed, requires using 'this'
    system.debug(this.myStringVar);       // Will output 'abc'
    system.debug(this.myOtherStringVar);  // Will output null
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.