You need to sign in to do that
Don't have an account?
disturbed118
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
Can you post a compiling minification of your issue please?
Thanks,
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?
}
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.
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'); } }
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,
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}">
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
Which is a subclass in the entertrialdetails controller i pass some of the static objects created in constructor of entertrialdetails controller, these become null.
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?
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,