5

I have a scenario where I have one Vf page called 'myVisualforce' and a custom controller 'myController'. In myController I have some non-static variables for example 'var1' and 'var2' and I have few static methods for example 'stat1', 'stat2' etc. I am calling these stat1 and stat2 in myVisualforce as Javascript Remoting methods. Now I want to use variables var1 and var2 in these static methods.

Now, 1. One solution is to use var1 and var2 in myVisualforce and pass it to these in remoting methods as parameters. This one I don't want to use. 2. What I was thinking is, if we open the myVisualforce page it calls the custom controller myController and constructor is also being called. As constructor is getting called then there should be an instance 'myInstance' created of myController that is being used in myVisualforce. Now my question is HOW TO ACCESS 'myInstance' IN THE CONTROLLER.

Any other solution is also welcome.

4
  • It'd be really helpful if you shared some code. My first question can you just make the variables static? There are all kinds of reasons why you might or might not do this, but it would help to know by seeing the code.
    – pchittum
    Commented Dec 8, 2014 at 10:43
  • This question is not specific to any code and have faced this problem many times. But still I will develop and share some demo code as my current code is very big. Problem with making the variables static is:- Once the page loads, value is being set in constructor but when I make a Remote call a new transaction will start and the variable will be having null value. Commented Dec 8, 2014 at 13:49
  • I understand the question you're asking. I'm not certain you can call a new instance of an apex class controller from a VF page since they're called from <apex:page controller= >. Its not like you can build up abstract classes and then call a new instance like you can with a trigger. I think you're going to need to use getters and setters to pass the non-static variables to your static methods or else use Custom Settings to set new values for your static variables.
    – crmprogdev
    Commented Dec 8, 2014 at 16:33
  • No, I don't want to create a new instance but wanted to access the instance which was created when VF Page was loaded and called the custom controller. Custom Settings are not required at all and also will not solve the purpose. Commented Dec 8, 2014 at 17:05

1 Answer 1

9

The short answer is quite simply, you cannot get to the instance of the Apex class that was invoked on page load. It is gone.

You are bumping up against one of the architectural peculiarities of Apex. Your Apex code runs in the scope of one single transaction. We don't get access to the persistent application runtime state. This is fundamentally different from most other programming languages.

Because of this accessing the instance of the controller that was created during page load is as impossible as me trying to get a kiss from Audrey Hepburn. Never mind that she is in a class way beyond me, but more importantly that instance of human just like the on-page-load instance of your controller class has long since ceased to exist.

When your VF page loads, it is in the context of a transaction. The instantiation of the controller, and execution of any methods is ephemeral and only lasts for the lifetime of that HTTP request/response cycle. By the time your page has rendered at the client everything your class created and worked with is sitting on the heap waiting to be garbage collected.

When your remote action method is invoked, there are no instances of the controller in memory. Not the one on page load, and not any others. Each HTTP request that uses the traditional postback request architecture creates a brand new instance of your controller with the page view state making each new instance pick up where the last left off as non-transient instance variables get passed back and forth from client to server like the baton in a relay.

If you need to get access to some functionality in your controller from a static remote method, then there are some options including:

  1. Instantiate it inside the remote method
  2. Move the logic/data you want into static methods/variables/helpers

Here's an illustration of option 1:

public class MixedController {

    private ApexPages.StandardController pageController ;

    public MixedController(ApexPages.StandardController ctrl){

        pageController = ctrl;

    }

    private String fetchAString(){
        return 'A String';
    }

    @RemoteAction
    public static List<Contact> fetchAccts(Id ctrlId){
        List<Contact> ctList = new List<Contact>();

        Account acct = [SELECT Id, Name, BillingCity from Account where Id = : ctrlId];

        MixedController locCtrl = new MixedController(new ApexPages.StandardController(acct));

        String aString = locCtrl.fetchAString();

        return ctList;
    }

}

The first technique carries some risk. If you were to change some persistent data (like the account record the controller is referencing), the next time your page did a proper postback, the page view state might be out of sync with the database. I'm not certain what would happen, or how the VF framework would resolve that.

Moving your logic into static class members might be more safe, but if you are relying on the page view state (to track progress of your user, for instance) that isn't an option, unless you devise some other strategy such as manually storing state in something like a custom setting or custom object field.

In general I try to avoid mixing static and non-static page patterns. If my page is intended for use in the traditional salesforce browser UI, I don't tend to use Javascript remoting, no matter what the perceived performance gain. On the other hand when building Visualforce for mobile consumption, I normally only use remote action methods.

I realize that not every project will be able to do this. But clearly, the mixing of static and non-static interaction with the controller needs to be approached with caution, and you need a game plan for how to handle the transient/non-transient nature of static remote action calls versus stateful traditional postback calls.

Have a read of the documentation on VF page execution order to understand the traditional postback architecture a little better:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .