2

I have a controller that builds a map from CaseNumbers to arrays of booleans, which decide how to render a column on a table: public Map<String, Boolean[]> caseMap { get; set; }

After setting up the map I use System.debug to ensure everything is in the map. The cases are filtered so that only a certain record type is selected like this:

public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                    [SELECT Id, CaseNumber, Subject, Status, Expected_Start_Date__c, Expected_Close_Date__c, RecordType.Name FROM Case
                   WHERE RecordType.Name = 'rm']));
            }
            return setCon;
        }
        set;
    }

public MyController() {
        this.cases = setCon.getRecords();
...

The way the map is built is by looping over this.cases and inserting a boolean array in it:

for(Case c : this.cases) {
    System.debug('Case: ' + c.CaseNumber);

    // init array
    Boolean[] barr = new Boolean[nmonths];

    // setup array
    ...
    System.debug('Finished setting up boolean array: ' + string.valueOf(barr));

    // Put boolean array into map
    caseMap.put(c.CaseNumber, barr);
}

In my VF page I do:

<apex:pageBlockTable value="{!cases}" var="rmcase">
        <apex:column value="{!rmcase.CaseNumber}"/>
        <apex:repeat value="{!caseMap[rmcase.CaseNumber]}" var="rbool">
            <column value="foo"/>
        </apex:repeat> 
</apex:pageBlockTable>

However this returns:

Map key null not found in map
Error is in expression '{!caseMap[rmcase.CaseNumber]}' in component <apex:pageBlockTable> in page rmoverview

This is completely /ridiculous/ as I have checked and there are no nulls inside the cases list. There are 20 cases and these are the case in caseMap.

How can I dig further into this problem? Any suggestions?

  • Something like this: fir loop to populate the map and avoid the null error for(Case c : this.cases) { caseMap.put(c.CaseNumber, new Boolean[]);} then for(Case c : this.cases) { /*before placing values check if the key exist in the map*/ if(case.containsKey(c.CaseNumber)) caseMap.put(c.CaseNumber, barr; } – Carlos Dec 3 '16 at 0:34
  • 1
    Does the running user have access to the CaseNumber field? How ares you populating cases. Error is basically saying that encase.casenumber is NULL so review your code / page for all possibilities for that field to be null. – Eric Dec 3 '16 at 0:39
  • 1
    is caseMap instantiated in the controller before the page displays? – cropredy Dec 3 '16 at 1:35
  • @cropredy yes, it's instantiated in the controller constructor as this.caseMap = new Map<String, Boolean[]>(); and defined as a field as public Map<String, Boolean[]> caseMap { get; set; } – Lily Dec 3 '16 at 22:12
  • @Lily, I came across an interesting known issue link related to your problem. Looks like, this error occurs when the value for that key in the map is null. Follow this link pls-success.salesforce.com/issues_view?id=a1p30000000T3k2AAC – SF Learner Dec 4 '16 at 22:39
2

I don't know exactly why yet, but it is something to do with the apex:pageBlockTable iterating over the map keys. If you swap it out with a basic apex:repeat it works fine.

E.g. Change this:

<apex:pageBlock>
    <apex:pageBlockTable value="{!cases}" var="rmcase"> 
        <apex:column value="{!rmcase.CaseNumber}"/>
        <apex:repeat value="{!caseMap[rmcase.CaseNumber]}" var="rbool">
            <column value="foo"/>
        </apex:repeat>
    </apex:pageBlockTable>
</apex:pageBlock>

To:

<table>
    <apex:repeat value="{!caseMap}" var="idx">
    <tr>
        <td>{!idx}</td>
        <apex:repeat value="{!caseMap[idx]}" var="r_col">
            <td>{!r_col}</td>
        </apex:repeat>
    </tr>
    </apex:repeat>
</table>

For reference, this is the basic controller I used.

public class CaseController {
    public Map<string, Boolean[]> caseMap { get; set; }
    public List<Case> cases { get; set; }

    public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                    [SELECT Id, CaseNumber, Subject, Status, RecordType.Name FROM Case]));
            }
            return setCon;
        }
        set;
    }

    public CaseController() {
        this.cases = setCon.getRecords();

        this.caseMap = new Map<string, Boolean[]>();

        for(Case c : this.cases) {           
            integer nmonths = 2;
            // init array
            Boolean[] barr = new Boolean[nmonths];
            for(integer i = 0; i < nmonths; i++) {
                barr[i] = false;
            }

            // Put boolean array into map
            System.assertNotEquals(null, c.CaseNumber);
            System.assertNotEquals('', c.CaseNumber);
            caseMap.put(c.CaseNumber, barr);
        }
    }

}

Just playing around, something very fishy is going on with the map key access in the inner repeat.

Input: <apex:repeat value="{!caseMap[rmcase.CaseNumber]}" var="r">

Map key null not found in map
Error is in expression '{!caseMap[rmcase.CaseNumber]}' in component in page casespage

Input: <apex:repeat value="{!caseMap[rmcase.CaseNumber + '']}" var="r">

Map key null not found in map
Error is in expression '{!caseMap[rmcase.CaseNumber + '']}' in component in page casespage

Input: <apex:repeat value="{!caseMap[rmcase.CaseNumber + '00001033']}" var="r"> produces

Map key 0000103300001033 not found in map
Error is in expression '{!caseMap[rmcase.CaseNumber + '00001033']}' in component in page casespage

Note how in the last case it decides the map key is no longer null.

It's something around how the parent apex:pageBlockTable is sending the CaseNumber into the apex:Repeat as the key because the following doesn't fall over on the key.

<apex:pageBlockTable value="{!cases}" var="rmcase"> 
    <apex:column value="{!rmcase.CaseNumber}"/>
    <apex:column value="{!caseMap['00001033']}"/>
    <apex:column value="{!caseMap[rmcase.CaseNumber]}"/>
</apex:pageBlockTable>

For reference, there are other occurrences of problems with keys not working correctly within apex:pageBlockTable:

| improve this answer | |

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.