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
disturbed118disturbed118 

static variable scope parent to child class on visualforce page

Hi i am having problems i have class something like this

 

class Parent

{

      public static String id = getParams('Id');

      public static list = new List blaah b;lah

 

     class Child

     {

           public void doSomething()

           {

                  fo(List a : list){

                  }

            }

     }

}

 

the problem is on my page i have table in which you can add a object when you click on add i instantiate the child class and call doSomething but the static list is always null

mtbclimbermtbclimber

Can you post a compiling minification of your issue please?

 

Thanks,

disturbed118disturbed118

Hi Andrew, i basically get that the list is a null exception on my visualforce page.

i have a pageblock table of say contacts each have a add details button when i click the add details

it creates a new subclass child but the list in the outterlcass is now null

 

public pageReference AddDetails()

{

      Child bbc = new Child();

      bbc.doSOmething();//list here is now null?

}

disturbed118disturbed118
although the child class is not inheritanting anything the static list object becomes null? anyone know why this is?
mtbclimbermtbclimber

No, that's why I asked you to provide a minification of the issue in a compiling class/page.  Perhaps you can identify the difference between your implementation and this minification of what I *think* you are trying to do and what you are doing:

 

Page:

 

<apex:page controller="parent">
<apex:form>
<apex:commandButton value="Go" action="{!pgo}"/>
<apex:pageMessages/>
</apex:form>
</apex:page>

 

Controller:

 

 

public class parent {

public static List<String> strings = new List<String>();

public void pgo() {
child c = new child();
c.go();
}

public class child {
public void go() {
for(String s:strings) { }
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'List size: ' + strings.size()));
}
}
}

 

 Clicking go returns the expected string in the message:

 

"List size: 0"

 

And not a null pointer exception which is what your experience might suggest.

 

 

disturbed118disturbed118

Ok here goes, the class entertrialdetails is instantiated from another controller, the problem comes in the newtrial method when the actualtrialexperience class gets created i am passing some of the static objects created in the entertrialdetails constructor.

 

 

<apex:pageBlock title="Clinical Trial Experience" rendered="{!trialInfo.validSpeciality}" id="selectedInterestsBlock"> <apex:pageBlockTable value="{!trialInfo.interests}" var="interest" columns="6" id="selectedInterests"> <apex:column value="{!interest.code}"/> <apex:column value="{!interest.aOfInterest.Speciality_Indication__c}"/> <!-- <apex:column value="{!interest.Speciality_Indication__r.Name}"/> --> <apex:column headerValue="No. Studies Conducted in Last 5 Yrs"> <apex:inputField value="{!interest.aOfInterest.No_Studies_Conducted_in_Last_5_Yrs__c}" styleClass="narrow"></apex:inputField> </apex:column> <apex:column headerValue="No. Studies Currently Recruiting"> <apex:inputField value="{!interest.aOfInterest.No_Studies_Currently_Recruiting__c}" styleClass="narrow"></apex:inputField> </apex:column> <apex:column headerValue="No. Studies Planned in Next Yr"> <apex:inputField value="{!interest.aOfInterest.No_Studies_Planned_in_Next_Yr__c}" styleClass="narrow"></apex:inputField> </apex:column> <apex:column headerValue="Add Trial Details"> <apex:outputPanel > <apex:commandButton action="{!trialInfo.newTrial}" value="Add Details" rerender="debugText" status="trialStatus"> <apex:param name="code" value="{!interest.code}"/> <apex:param name="interestName" value="{!interest.name}"/> <apex:param name="investigatorId" value="{!conInv.Id}"/> </apex:commandButton> </apex:outputPanel> </apex:column> <apex:column > <apex:commandButton immediate="true" value="Delete" action="{!trialInfo.removeInterest}" onclick="{if(!confirm('Are you sure that you want to delete this trial experience?\nNOTE: All related Trial Details will also be deleted.')) return false}" rerender="selectedInterests, selectedTrials, areasOfInterest, theMessages"> <apex:param name="interestName" value="{!interest.name}"/> <apex:param name="code" value="{!interest.code}"/> </apex:commandButton> </apex:column> </apex:pageBlockTable> </apex:pageBlock>

 

 

public with sharing class EnterTrialDetailsController { //data collections used in the page List<DataCol> selectedData = new List<DataCol>(); Map<String, DataCol> selectedDataMap = new Map<String, DataCol>();//map of name to dataCol List<DataCols> dataColumns = new List<DataCols>(); List<AreaOfInterest> interests = new List<AreaOfInterest>(); //map of name to area of interest, these are the areas of interest ed on the page Map<String, AreaOfInterest> interestsMap = new Map<String, AreaOfInterest>(); //map of code to actual trial experience. The code links the trial experience to the area of interest Map<Long, ActualTrialExperience> trials = new Map<Long, ActualTrialExperience>(); //a map of interest Id's to code associated with interest Map<Id, Integer> interestIdToCodeMap = new Map<Id, Integer>(); //data from the Speciality__c object static Map<String, List<Speciality__c>> indicationsData = new Map<String, List<Speciality__c>>(); Integer countCode; //is the speciality associated with the investigator valid? public Boolean validSpeciality {get; set;} public String invSpeciality {get; private set;} //data to initialise //investigator id public static Id invId; //investigator record public static Contact myinvestigator; public static Map<Id, Speciality__c> indSpecial; //find what Therapeutic_Areas_of_Interest__c are in the database at the moment public static Map<Id, Therapeutic_Areas_of_Interest__c> interestsFromDBmap; public EnterTrialDetailsController(Contact c) { invId = System.currentPagereference().getParameters().get('invid'); myinvestigator = [Select Id, Name, Speciality_Picklist_Test__c from contact where Id = :invId]; indSpecial = new Map<Id, Speciality__c>([Select id, s.Name, s.Detailed_Indication__c From Speciality__c s where Speciality__c = :myinvestigator.Speciality_Picklist_Test__c]); system.debug('indSpecial on creation: ' + indSpecial); interestsFromDBmap = new Map<Id, Therapeutic_Areas_of_Interest__c> ([Select t.Speciality_Indication__r.Detailed_Indication__c, t.Speciality_Indication__r.Name, t.Speciality_Indication__c, t.No_Studies_Planned_in_Next_Yr__c, t.No_Studies_Currently_Recruiting__c, t.No_Studies_Conducted_in_Last_5_Yrs__c, t.Investigator__c, t.Name From Therapeutic_Areas_of_Interest__c t Where t.Investigator__c = :invId]); Contact investigator = c; //code for associating Trial Experience with Trial Details countCode = 0; //check if the Investogator has a Speciaility, if they havent we cant do anything //invId = System.currentPagereference().getParameters().get('invid'); if(invId == null) { validSpeciality = false; } else { if(investigator.Speciality_Picklist_Test__c == null || investigator.Speciality_Picklist_Test__c == '') { validSpeciality = false; } else { validSpeciality = true; invSpeciality = investigator.Speciality_Picklist_Test__c; makeDataColumns(investigator.Speciality_Picklist_Test__c); } //set up any existing interests //create a list of "dCol" objects //get the data from the database setupInterests();//version of the method that gets the interests from the DB //create a list of ID's of the interests List<Id> interestIds = new List<Id>(); for(AreaOfInterest interest : interests) { interestIds.add(interest.aOfInterest.Id); } setupTrials(interestIds); } } //this is where those statis vars become null public PageReference newTrial() { /*String code = apexpages.currentpage().getparameters().get('code'); String interestName = apexpages.currentpage().getparameters().get('interestName'); String investigatorId = apexpages.currentpage().getparameters().get('investigatorId'); System.debug('investigatorId parameter from details button: ' + investigatorId); //This is weird when add details is pressed the static objects such as myinvestiagtor //and indSpecial become null help? debug += '<br/>Investigator Id: ' + investigatorId; if(myinvestigator == null)myinvestigator = [Select Id, Speciality_Picklist_Test__c from contact where Id = :investigatorId]; //debug += '<br/>Investigator Name: ' + myinvestigator.Speciality_Picklist_Test__c; //if(indSpecial == null)indSpecial = new Map<Id, Speciality__c>([Select id, s.Name, s.Detailed_Indication__c From Speciality__c s where Speciality__c = :myinvestigator.Speciality_Picklist_Test__c]); //if(invId == null)invId = myinvestigator.Id; Actual_Trial_Experience__c aTe = new Actual_Trial_Experience__c(); Long now = Datetime.now().getTime(); System.debug('myinvestigator just before new ActualTrialExperience: ' + myinvestigator); System.debug('indSpecial just before new ActualTrialExperience: ' + indSpecial); ActualTrialExperience aTeW = new ActualTrialExperience(code, aTe, now, interestName); trials.put(now, aTeW); */ //childTest ab = new childTest(myinvestigator); //debug = ab.hasId; debug += '<br/>' + EnterTrialDetailsController.invId; return null; } public Pagereference save() { if(commitData()) { PageReference pageRef = new PageReference('/'+ invId); return pageRef; } else { return null; } } /*Sub CLass*/ /* Purpose: wrapper for Actual_Trial_Experience__c */ public static Integer testInt = 0; public class ActualTrialExperience { public String code {get; set;} public Long uniqueCode {get; set;} public String interestName; public Id investigatorId; public String selectedDetailId; public Actual_Trial_Experience__c actualTrialExp {get; set;} public List<Speciality__c> detailedIndications {get; set;}//for the picklist public ActualTrialExperience(String cd, Actual_Trial_Experience__c aTrE, Long uCode, String intName) { code = cd; actualTrialExp = aTrE; uniqueCode = uCode; testInt = 3; interestName = intName; investigatorId = EnterTrialDetailsController.invId; //get the detailed indications that apply to this Actual Trial Experience detailedIndications = new List<Speciality__c>(); //want the value to be selected if it already has a value selectedDetailId = actualTrialExp.Select_Detailed_Indication__c; System.debug('investigatorId : ' + investigatorId); System.debug('interestName.toLowercase(): ' + interestName.toLowercase()); if(indicationsData.size() < 1) { //Contact investigator = [Select Id, Speciality_Picklist_Test__c from contact where Id = :investigatorId]; // List<Speciality__c> allIndicationsForSpeciality = [Select id, s.Name, s.Detailed_Indication__c From Speciality__c s where Speciality__c = :investigator.Speciality_Picklist_Test__c order by s.Name]; //system.debug('indSpecial' + indSpecial); //system.debug('indSpecial.values()' + indSpecial.values()); makeIndicationsData(indSpecial.values()); } List<Speciality__c> detailsForThisTrialExperience = indicationsData.get(interestName.toLowercase()); System.debug('indicationsData: ' + indicationsData); System.debug('detailsForThisTrialExperience: ' + detailsForThisTrialExperience); if(detailsForThisTrialExperience != null) { detailedIndications.addAll(detailsForThisTrialExperience); } System.debug('detailedIndications: ' + detailedIndications); //detailedIndications = new List<String>(); //detailedIndications.add('test'); } }

 

 

mtbclimbermtbclimber

Ok, thanks for posting that though I was hoping that you would remove as much as you could from it to isolate the issue.  Also, I don't see a "trialInfo" property or "getTrialInfo()" method in your controller though the button you are describing as having the issue is bound with this expression: 

 

 

{!trialInfo.newTrial}

 

Is your page bound to the controller you've provided?

 

Can you constrict the code to something with a little less "noise"?

 

Thanks,

 

 

 

 

disturbed118disturbed118

Hi basically the entertrialdetails controller is created from my custom controller in there i instantiate entertrialdetails controller called trialInfo and redirect to the visualforce page posted above.

 

Here is the page where my custom controller calls the entertrialdetails controller

 

<apex:page controller="ClinicalTrialSurvey" sidebar="false" showHeader="false" standardStylesheets="true" action="{!CheckValidRoute}">

 

 So here is the route on how this works, i have a page with my custom controller, when the user clicks on next i instantiate the entertrialdetails controller in my custom controller and then redirect the user to the new visualforce page keeping the same state across all pages. So the trialInfo is the newly created entertrialdetails controller in my custom controller.

 

 

 

The trialInfo.newTrial calls this method in the entertrialdetails controller

public PageReference newTrial() { String code = apexpages.currentpage().getparameters().get('code'); String interestName = apexpages.currentpage().getparameters().get('interestName'); String investigatorId = apexpages.currentpage().getparameters().get('investigatorId'); System.debug('investigatorId parameter from details button: ' + investigatorId); //This is weird when add details is pressed the static objects such as myinvestiagtor //and indSpecial become null help? Actual_Trial_Experience__c aTe = new Actual_Trial_Experience__c(); Long now = Datetime.now().getTime(); System.debug('myinvestigator just before new ActualTrialExperience: ' + myinvestigator); System.debug('indSpecial just before new ActualTrialExperience: ' + indSpecial); ActualTrialExperience aTeW = new ActualTrialExperience(code, aTe, now, interestName); trials.put(now, aTeW); return null; }

 

Now everthing works fine until you call newTrial this creates the object

ActualTrialExperience

 

Which is a subclass in the entertrialdetails controller i pass some of the static objects created in constructor of entertrialdetails controller, these become null.

 

disturbed118disturbed118
I wish i could solve this, its major issue i am having i can't seem to move forward?
mtbclimbermtbclimber
There's too much missing from this thread. How are you constructing the entertrialdetails class in the method?  You probably know but in case not request params on the original request are not maintained in post-backs.
disturbed118disturbed118

the entertrialdetails controller is constructed in my custom controller called ClinicalTrialSurvey when the user clicks on the next button i create the entertrialdetails controller like this:

 

This is in my ClinicalTrialSurvey Controller

public PageReference TrialsPageNext() { //If investigator details are valid then return to clinical trials page. if(IsValidInvestigator()) { //Pass to Ray's controller the investigator id. Apexpages.currentPage().getParameters().put('invId', conInv.Id); //Pass in the updated speciality as well. conInv.Speciality_Picklist_Test__c = surInv.Speciality_Picklist__c; trialInfo = new EnterTrialDetailsController(conInv); return Page.clinicaltrialdetails; } return null; }

 

here i create the entertrialdetails controller i.e. trialInfo and then redirect to the page above clinicaltrialdetails which has the trialInfo. Initially the static object have the data but when i click on a button it looses its value?

 

 

mtbclimbermtbclimber

The good news: I've finally reproduced the behavior you are describing.

 

The bad news: I'm not sure this wasn't intentional. 

 

For now, your implementation choice here is pretty much to change these to be instance variables.  I'd also recommend passing them as args rather than sticking them into the request context as request parameters.  It'll make your testing a little easier and you can use types besides strings more easily.

 

For reference, here's my minification of the issue based loosely on your case (it assumes there is at least one contact record in your environment):

 

Page:

 

<apex:page controller="staticvarreprocon">
<apex:form >
<apex:commandButton value="Instantiate" action="{!instantiate}" rendered="{!ISNULL(i)}"/>
<apex:commandButton value="Postback" rendered="{!NOT(ISNULL(i))}"/>
<apex:outputPanel layout="block">
Contact name:{!i.name}
</apex:outputPanel>
<apex:pageMessages />
</apex:form>
</apex:page>

 

 

 Controller:

 

public class staticvarreprocon {

public static Contact con;
public InnerClass i { get; set; }

public void instantiate() {
i = new InnerClass([select id from contact limit 1].id);
}

public class InnerClass {

public String getName() {
return con.name;
}

public InnerClass(Id id) {
cid = id;
con = [select name from contact where id = :cid];
}
}

static Id cid;
}

 

 Notice when you click the "Postback" button, after clicking "Instantiate" there is an NPE. Moving the static variables to instance variables removes the NPE issue. My sample refactored accordingly:

 

(same page)

 

Controller:

 

 

public class staticvarreprocon {

public Contact con;
public InnerClass i { get; set; }

public void instantiate() {
con = [select name from contact limit 1];
i = new InnerClass(con);
}

public class InnerClass {

public String getName() {
return con.name;
}

public InnerClass(Contact c) {
con = c;
}

Contact con;
}
}

 

 

 

Sorry there isn't a clear answer yet. I'll post back here when there is. For now I hope this workaround will work for you.

 

 

Thanks for your patience,